{"id":18398137,"url":"https://github.com/ousc/ng-milkdown","last_synced_at":"2025-07-29T22:11:55.085Z","repository":{"id":211468384,"uuid":"726313811","full_name":"ousc/ng-milkdown","owner":"ousc","description":"Milkdown(WYSIWYG markdown Editor ) for Angular out-of-box.","archived":false,"fork":false,"pushed_at":"2025-02-13T17:35:06.000Z","size":17836,"stargazers_count":12,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-07T04:34:02.797Z","etag":null,"topics":["milkdown"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ousc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-02T02:49:04.000Z","updated_at":"2025-04-02T01:17:05.000Z","dependencies_parsed_at":"2024-06-03T19:30:14.530Z","dependency_job_id":"63164e23-5739-443f-b074-9458b306896d","html_url":"https://github.com/ousc/ng-milkdown","commit_stats":null,"previous_names":["ousc/ng-milkdown"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ousc/ng-milkdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ousc%2Fng-milkdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ousc%2Fng-milkdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ousc%2Fng-milkdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ousc%2Fng-milkdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ousc","download_url":"https://codeload.github.com/ousc/ng-milkdown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ousc%2Fng-milkdown/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267771187,"owners_count":24142015,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["milkdown"],"created_at":"2024-11-06T02:19:56.818Z","updated_at":"2025-07-29T22:11:55.071Z","avatar_url":"https://github.com/ousc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://ousc.github.io/ng-milkdown\"\u003e\n    \u003cimg src=\"https://github.com/ousc/ng-milkdown/raw/main/milkdownLogo.png\" width=\"230\" style=\"vertical-align: middle;\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\nNG-MILKDOWN\n\u003c/h1\u003e\n\n[![NPM version](https://img.shields.io/npm/v/ng-milkdown.svg)](https://www.npmjs.com/package/ng-milkdown)\n\nWYSIWYG markdown Editor 🍼 [**Milkdown**](https://github.com/Milkdown/milkdown) for [**Angular**](https://angular.dev/) out of box, only supports Angular **17**+.\nAllow you to use native Angular components to create nodeView/pluginView/widgetView, and provide corresponding examples.\n\n## Version\n`ng-milkdown` is only supported by `Angular` version `\u003e=17.0.0`.\n\n`ng-milkdown-crepe` only supports `Angular` version `\u003e=18.0.0`.\n\n| Angular | ng-milkdown |\n|---------|-------------|\n| 17.0.0+ | 0.0.3       |\n| 18.0.0+ | 0.1.0-beta0 |\n\n\n## Example\n\nYou can run this example by:\n\n```bash\ngit clone https://github.com/ousc/ng-milkdown.git\ncd ng-milkdown\nnpm install\nnpm run start\n```\n\n## Online Demo And Documentation\n\n[https://ousc.github.io/ng-milkdown](https://ousc.github.io/ng-milkdown)\n\n## ng-prosemirror-adapter(Latest Version 0.0.9)\n\nAngular adapter for ProseMirror, only supports Angular 17+.\n\n[https://github.com/ousc/ng-prosemirror-adapter](https://github.com/ousc/ng-prosemirror-adapter)\n\n## Official plugins support on NgMilkdown:\n\n- [X]  `theme-nord`**(preset)**\n- [X]  `preset-commonmark`**(preset)**\n- [X]  `plugin-listener`**(preset)**\n- [X]  `preset-gfm`**(supported)**\n- [X]  `plugin-history`**(supported)**\n- [X]  `plugin-shiki`**(supported)**\n- [X]  `plugin-clipboard`**(supported)**\n- [X]  `plugin-cursor`**(supported)**\n- [X]  `plugin-latex`**(supported)**\n- [X]  `plugin-block`**(supported)**\n- [X]  `plugin-indent`**(supported)**\n- [X]  `plugin-tooltip`**(supported)**\n- [ ]  `plugin-slash`**(working)**\n- [ ]  `plugin-diagram`**(working)**\n- [ ]  `plugin-emoji`**(working)**\n- [X]  `plugin-cursor`**(supported)**\n- [X]  `plugin-trailing`**(supported)**\n- [X]  `plugin-upload`**(supported)**\n- [ ]  `plugin-collab`**(working)**\n- [ ]  `plugin-copilot`**(working)**\n\nusage of plugins can be found in [example](https://github.com/ousc/ng-milkdown/tree/main/src/app/components);\n\n## Quick Start\n\n### Install\n\n```bash\nnpm install ng-milkdown -S\n```\n\n### Crepe\n#### crepe-editor.component.html\n```html\n\u003cng-milkdown-provider\u003e\n  \u003cng-milkdown-crepe\n    [(ngModel)]=\"value\"\n    [plugins]=\"plugins\"\n    [features]=\"features\"\n    [featureConfigs]=\"featureConfigs\"\n    [(loading)]=\"loading\"\n    [spinner]=\"spinner\"\n    (beforeReady)=\"beforeReady($event)\"\n    (ngModelChange)=\"onChange($event)\"\n  /\u003e\n\u003c/ng-milkdown-provider\u003e\n```\n\n#### crepe-editor.component.ts\n\n```typescript\nimport \"@milkdown/crepe/theme/common/style.css\";\nimport \"@milkdown/crepe/theme/nord.css\";\nimport {NgMilkdownCrepeEditor} from \"./ng-milkdown.type\";\n\n@Component({...})\nexport class CrepeEditorComponent {\n  features = {\n    [Crepe.Feature.Placeholder]: false\n  }\n  \n  beforeReady({crepe}: NgMilkdownCrepeEditor) {\n    editor.config(ctx =\u003e {\n      ctx.set(blockquoteAttr.key, () =\u003e ({\n        class: \"border-l-4 border-nord10 pl-4 dark:border-nord8\",\n      }));\n\n      ctx.set(inlineCodeAttr.key, () =\u003e ({\n        class: \"font-mono text-nord10 tracking-tight dark:text-nord8\",\n      }));\n    });\n  }\n\n  plugins = [imageInlineComponent];\n\n  value = 'Hello, World!';\n\n  onChange(markdownText: string) {\n    console.log({markdownText});\n  }\n}\n\n```\n### Milkdown Editor\n#### editor.component.html\n```html\n\u003cng-milkdown-provider\u003e\n  \u003cng-milkdown\n    [(ngModel)]=\"value\"\n    [plugins]=\"plugins\"\n    [(loading)]=\"loading\"\n    [spinner]=\"spinner\"\n    (beforeReady)=\"beforeReady($event)\"\n    (ngModelChange)=\"onChange($event)\"\n  /\u003e\n\u003c/ng-milkdown-provider\u003e\n```\n\n#### editor.component.ts\n\n```typescript\n\nconst tooltip = tooltipFactory('text-tooltip')\n\n@Component({...})\nexport class WorkGroundComponent {\n  @ViewChild(NgMilkdownProvider, {static: true}) provider: NgMilkdownProvider;\n\n  beforeReady({editor}: NgMilkdownEditor) {\n    editor.config(ctx =\u003e {\n      ctx.set(editorViewOptionsCtx, {\n        attributes: {\n          class: \"prose dark:prose-invert outline-none mx-auto px-2 py-4 max-w-full box-border milkdown-theme-nord editor\",\n          spellcheck: \"false\",\n        },\n      });\n\n      ctx.set(blockquoteAttr.key, () =\u003e ({\n        class: \"border-l-4 border-nord10 pl-4 dark:border-nord8\",\n      }));\n\n      ctx.set(inlineCodeAttr.key, () =\u003e ({\n        class: \"font-mono text-nord10 tracking-tight dark:text-nord8\",\n      }));\n    });\n  }\n\n  plugins = [\n    commonmark,\n    link,\n    history,\n    imageInlineComponent,\n    iframeComponent,\n    trailing,\n    block,\n    indent,\n    milkShiki,\n    $nodeView(codeBlockSchema.node, {component: CodeBlock}),\n    $pluginView(block.key, {component: Block}),\n    $nodeView(listItemSchema.node, {component: ListItem}),\n    tooltip,\n    $pluginView(tooltip.key, {component: Tooltip}),\n    $prosePlugin({component: Size}),\n    latex,\n  ];\n\n  value = 'Hello, World!';\n\n  onChange(markdownText: string) {\n    console.log({markdownText});\n  }\n}\n\n```\n\n### API\n\n| Property          | Description                                                       | Type                      | Default                |\n|-------------------|-------------------------------------------------------------------|---------------------------|------------------------|\n| `[classList]`     | editor element class names                                        | `string[]`                | `[]`                   |\n| `[plugins]`       | milkdown plugin to use                                            | `NgMilkdownPlugin[]`      | `[]`                   |\n| `[editor]`        | pass in a fully controlled editor object                          | `(HTMLElement) =\u003e Editor` | -                      |\n| `[loading]`       | set the loading status of editor                                  | `boolean`                 | `true`                 |\n| `[spinner]`       | custom spinner                                                    | `TemplateRef\u003cany\u003e`        | -                      |\n| `[ngModel]`       | current value , double binding                                    | `DefaultValue`            | -                      |\n| `(ngModelChange)` | callback when markdown change                                     | `EventEmitter\u003cstring\u003e`    | -                      |\n| `(onReady)`       | A callback function, can be executed when editor has bean created | `Editor`                  | -                      |\n\n## OutOfBox Plugins\n\n### ng-milkdown-tooltip\n\n```typescript\n@Component({\n  template: `\n      \u003cbutton (click)=\"setBold($event)\"\u003e\n        Bold\n      \u003c/button\u003e\n  `,\n  ...\n})\nexport class ImageTooltipComponent extends NgMilkdownTooltip {\n    setBold(e: MouseEvent) {\n      e.preventDefault();\n      this.action(callCommand(toggleStrongCommand.key));\n    }\n}\n```\n\n\n### ng-milkdown-block\n\n```typescript\n@Component({\n  selector: 'block',\n  template: `\n      \u003cdiv class=\"w-6 bg-slate-200 rounded hover:bg-slate-300 cursor-grab\"\u003e\n          \u003csvg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width={1.5} stroke=\"currentColor\" class=\"w-6 h-6\"\u003e\n              \u003cpath stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 12.75a.75.75 0 110-1.5.75.75 0 010 1.5zM12 18.75a.75.75 0 110-1.5.75.75 0 010 1.5z\" /\u003e\n          \u003c/svg\u003e\n      \u003c/div\u003e\n  `,\n  styles:[],\n  standalone: true\n})\nexport class BlockComponent extends NgMilkdownBlock {}\n```\n\nMore detailed examples and more plugins can be found in [example](https://github.com/ousc/ng-milkdown/tree/main/src/app/components);\n\n## license\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fousc%2Fng-milkdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fousc%2Fng-milkdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fousc%2Fng-milkdown/lists"}