{"id":20767081,"url":"https://github.com/semanticdata/svelte-milkdown","last_synced_at":"2025-07-05T11:36:11.858Z","repository":{"id":211661627,"uuid":"729675615","full_name":"semanticdata/svelte-milkdown","owner":"semanticdata","description":"🥛 Simple example for using Svelte with Milkdown, a plugin driven WYSIWYG markdown editor framework. ","archived":false,"fork":false,"pushed_at":"2024-04-29T20:28:46.000Z","size":438,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-14T19:11:56.162Z","etag":null,"topics":["example","markdown","markdown-editor","milkdown","postcss","svelte","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://svelte-milkdown.vercel.app","language":"Svelte","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/semanticdata.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-10T01:24:36.000Z","updated_at":"2025-03-04T22:45:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"d741a5d2-23bb-4502-9250-f9de9ebfaf0d","html_url":"https://github.com/semanticdata/svelte-milkdown","commit_stats":null,"previous_names":["semanticdata/svelte-milkdown"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/semanticdata/svelte-milkdown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semanticdata%2Fsvelte-milkdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semanticdata%2Fsvelte-milkdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semanticdata%2Fsvelte-milkdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semanticdata%2Fsvelte-milkdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/semanticdata","download_url":"https://codeload.github.com/semanticdata/svelte-milkdown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semanticdata%2Fsvelte-milkdown/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263734163,"owners_count":23503270,"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","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":["example","markdown","markdown-editor","milkdown","postcss","svelte","tailwindcss","typescript"],"created_at":"2024-11-17T11:27:40.224Z","updated_at":"2025-07-05T11:36:11.782Z","avatar_url":"https://github.com/semanticdata.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Svelte 🥛 Milkdown\n\n![code size](https://img.shields.io/github/languages/code-size/semanticdata/svelte-milkdown) ![repo size](https://img.shields.io/github/repo-size/semanticdata/svelte-milkdown) ![commit activity](https://img.shields.io/github/commit-activity/t/semanticdata/svelte-milkdown) ![last commit](https://img.shields.io/github/last-commit/semanticdata/svelte-milkdown) ![website up?](https://img.shields.io/website/https/svelte-milkdown.vercel.app.svg)\n\nA simple example for using [Milkdown](https://milkdown.dev/) with [Svelte](https://svelte.dev/).\n\n[![Github Pages](https://img.shields.io/badge/github%20pages-121013?style=for-the-badge\u0026logo=github\u0026logoColor=white)](https://semanticdata.github.io/svelte-milkdown/) [![Vercel](https://img.shields.io/badge/vercel-%23000000.svg?style=for-the-badge\u0026logo=vercel\u0026logoColor=white)](https://svelte-milkdown.vercel.app/)\n\n[![deploy to stackblitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/Milkdown/examples/tree/main/svelte-commonmark)\n\n## 🚀 Getting Started\n\n1. Clone the repo: `git clone https://github.com/semanticdata/svelte-milkdown.git`.\n\n2. Install dependencies: `pnpm install`.\n\n3. Run the example: `pnpm start`.\n\n4. Open `http://localhost:5173/` in your browser.\n\n## Helpful Links\n\n- Svelte - [Documentation](https://svelte.dev/docs/introduction)\n- Milkdown - [Documentation](https://milkdown.dev/docs)\n  - [Svelte recipe](https://milkdown.dev/docs/recipes/svelte)\n  - [Interacting with the Editor](https://milkdown.dev/docs/guide/interacting-with-editor)\n\n## Interacting with Editor\n\n### Register to DOM\n\nBy default, milkdown will create editor on the document.body. Alternatively, you can also point out which dom node you want it to load into:\n\n```js\nimport {rootCtx} from '@milkdown/core'\n\nEditor.make().config((ctx) =\u003e {\n  ctx.set(rootCtx, document.querySelector('#editor'))\n})\n```\n\nIt's also possible to just pass a selector to rootCtx:\n\n\u003e The selector will be passed to document.querySelector to get the dom.\n\n```js\nimport {rootCtx} from '@milkdown/core'\n\nEditor.make().config((ctx) =\u003e {\n  ctx.set(rootCtx, '#editor')\n})\n```\n\n### Setting Default Value\n\nWe support three types of default values:\n\n- Markdown strings.\n- HTML DOM.\n- Prosemirror documentation JSON.\n\n### Markdown\n\nYou can set a markdown string as the default value of the editor.\n\n```js\nimport {defaultValueCtx} from '@milkdown/core'\n\nconst defaultValue = '# Hello milkdown'\nEditor.make().config((ctx) =\u003e {\n  ctx.set(defaultValueCtx, defaultValue)\n})\n```\n\nAnd then the editor will be rendered with default value.\n\n### DOM\n\nYou can also use HTML as default value.\n\nLet's assume that we have the following html snippets:\n\n```js\n\u003cdiv id=\"pre\"\u003e\n  \u003ch1\u003eHello milkdown!\u003c/h1\u003e\n\u003c/div\u003e\n```\n\nThen we can use it as a defaultValue with a type specification:\n\n```js\nimport {defaultValueCtx} from '@milkdown/core'\n\nconst defaultValue = {\n  type: 'html',\n  dom: document.querySelector('#pre')\n}\nEditor.make().config((ctx) =\u003e {\n  ctx.set(defaultValueCtx, defaultValue)\n})\n```\n\n### JSON\n\nWe can also use a JSON object as a default value.\n\nThis JSON object can be obtained by a listener through the listener-plugin, for example:\n\n```js\nimport {listener, listenerCtx} from '@milkdown/plugin-listener'\n\nlet jsonOutput\n\nEditor.make()\n  .config((ctx) =\u003e {\n    ctx.get(listenerCtx).updated((ctx, doc, prevDoc) =\u003e {\n      jsonOutput = doc.toJSON()\n    })\n  })\n  .use(listener)\n```\n\nThen we can use this jsonOutput as default Value:\n\n```js\nimport {defaultValueCtx} from '@milkdown/core'\n\nconst defaultValue = {\n  type: 'json',\n  value: jsonOutput\n}\nEditor.make().config((ctx) =\u003e {\n  ctx.set(defaultValueCtx, defaultValue)\n})\n```\n\n## Inspecting Editor Status\n\nYou can inspect the editor's status through the status property.\n\n```js\nimport {Editor, EditorStatus} from '@milkdown/core'\n\nconst editor = Editor.make().use(/*some plugins*/)\n\nassert(editor.status === EditorStatus.Idle)\n\neditor.create().then(() =\u003e {\n  assert(editor.status === EditorStatus.Created)\n})\n\nassert(editor.status === EditorStatus.OnCreate)\n\neditor.destroy().then(() =\u003e {\n  assert(editor.status === EditorStatus.Destroyed)\n})\n\nassert(editor.status === EditorStatus.OnDestroyed)\n```\n\nYou can also listen to the status changes:\n\n```js\nimport { Editor, EditorStatus } from '@milkdown/core';\n\nconst editor = Editor.make().use(/*some plugins*/);\n\neditor.onStatusChange((status: EditorStatus) =\u003e {\n  console.log(status);\n});\n```\n\n## Adding Listeners\n\nAs mentioned above, you can add a listener to the editor, in order to get it's value when needed.\n\nMarkdown Listener\n\nYou can add markdown listener to get the editor's contents as a markdown string.\n\nYou can add as many listeners as you want, all the listeners will be triggered at once.\n\n```js\nimport {listener, listenerCtx} from '@milkdown/plugin-listener'\n\nlet output = ''\n\nEditor.make()\n  .config((ctx) =\u003e {\n    ctx.get(listenerCtx).markdownUpdated((ctx, markdown, prevMarkdown) =\u003e {\n      output = markdown\n    })\n  })\n  .use(listener)\n```\n\n### Doc Listener\n\nYou can also listen to the raw prosemirror document node, and do things you want from there.\n\n```js\nimport {listener, listenerCtx} from '@milkdown/plugin-listener'\n\nlet jsonOutput\n\nEditor.make()\n  .config((ctx) =\u003e {\n    ctx.get(listenerCtx).updated((ctx, doc, prevDoc) =\u003e {\n      jsonOutput = doc.toJSON()\n    })\n  })\n  .use(listener)\n```\n\nFor more details about listeners, please check Using Listeners.\n\n## Readonly Mode\n\nYou can set the editor to readonly mode by setting the editable property.\n\n```js\nimport {editorViewOptionsCtx} from '@milkdown/core'\n\nlet readonly = false\n\nconst editable = () =\u003e !readonly\n\nEditor.make().config((ctx) =\u003e {\n  ctx.update(editorViewOptionsCtx, (prev) =\u003e ({\n    ...prev,\n    editable\n  }))\n})\n\n// set to readonly after 5 secs.\nsetTimeout(() =\u003e {\n  readonly = true\n}, 5000)\n```\n\n## Using Actions\n\nYou can use an action to get the context value in a running editor on demand.\n\nFor example, to get the markdown string by running an action:\n\n```js\nimport {Editor, editorViewCtx, serializerCtx} from '@milkdown/core'\n\nasync function playWithEditor() {\n  const editor = await Editor.make().use(commonmark).create()\n\n  const getMarkdown = () =\u003e\n    editor.action((ctx) =\u003e {\n      const editorView = ctx.get(editorViewCtx)\n      const serializer = ctx.get(serializerCtx)\n      return serializer(editorView.state.doc)\n    })\n\n  // get markdown string:\n  getMarkdown()\n}\n```\n\nWe provide some macros out of the box, you can use them as actions:\n\n```js\nimport {insert} from '@milkdown/utils'\n\neditor.action(insert('# Hello milkdown'))\n```\n\nFor more details about macros, please check macros.\n\n## Destroying\n\nYou can call editor.destroy to destroy an existing editor. You can create a new editor again with editor.create.\n\n```js\nawait editor.destroy()\n\n// Then create again\nawait editor.create()\n```\n\nIf you just want to recreate the editor, you can use editor.create, it will destroy the old editor and create a new one.\n\n```js\nawait editor.create()\n\n// This equals to call `editor.destroy` and `editor.create` again.\nawait editor.create()\n```\n\nIf you want to clear the plugins and configs for the editor when calling editor.destroy, you can pass true to editor.destroy.\n\n```js\nawait editor.destroy(true)\n```\n\n## Official Plugins\n\nMilkdown provides the following official plugins: | name | description | | :--------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- | | [@milkdown/preset-commonmark](https://www.npmjs.com/package/@milkdown/preset-commonmark) | Add [commonmark](https://commonmark.org/) syntax support | | [@milkdown/preset-gfm](https://www.npmjs.com/package/@milkdown/preset-gfm) | Add [gfm](https://github.github.com/gfm/) syntax support | | [@milkdown/plugin-history](https://www.npmjs.com/package/@milkdown/plugin-history) | Add undo \u0026 redo support | | [@milkdown/plugin-clipboard](https://www.npmjs.com/package/@milkdown/plugin-clipboard) | Add markdown copy \u0026 paste support | | [@milkdown/plugin-cursor](https://www.npmjs.com/package/@milkdown/plugin-cursor) | Add drop \u0026 gap cursor | | [@milkdown/plugin-listener](https://www.npmjs.com/package/@milkdown/plugin-listener) | Add listener support | | [@milkdown/plugin-collaborative](https://www.npmjs.com/package/@milkdown/plugin-collaborative) | Add collaborative editing support | | [@milkdown/plugin-prism](https://www.npmjs.com/package/@milkdown/plugin-prism) | Add [prism](https://prismjs.com/) support for code block highlight | | [@milkdown/plugin-math](https://www.npmjs.com/package/@milkdown/plugin-math) | Add [LaTeX](https://en.wikipedia.org/wiki/LaTeX) support for math | | [@milkdown/plugin-tooltip](https://www.npmjs.com/package/@milkdown/plugin-tooltip) | Add selected tooltip for text | | [@milkdown/plugin-slash](https://www.npmjs.com/package/@milkdown/plugin-slash) | Add slash commands support | | [@milkdown/plugin-emoji](https://www.npmjs.com/package/@milkdown/plugin-emoji) | Add emoji support | | [@milkdown/plugin-diagram](https://www.npmjs.com/package/@milkdown/plugin-diagram) | Add [mermaid](https://mermaid-js.github.io/mermaid/#/) diagram support | | [@milkdown/plugin-indent](https://www.npmjs.com/package/@milkdown/plugin-indent) | Add tab indent support | | [@milkdown/plugin-upload](https://www.npmjs.com/package/@milkdown/plugin-upload) | Add drop and upload support |\n\n## Community Plugins\n\n- [milkdown-plugin-shiki](https://www.npmjs.com/package/milkdown-plugin-shiki)  \n  Add [shiki](https://shiki.matsu.io/) support for code block highlight.\n- [@star-dancer/milkdown](https://www.npmjs.com/package/@star-dancer/milkdown)  \n  Angular integration for milkdown.\n- [@ezone-devops/milkdown-plugin-directive-fallback](https://www.npmjs.com/package/@ezone-devops/milkdown-plugin-directive-fallback)  \n  Render all directive as text to avoid parse error when use remark-directive.\n- [milkdown-plugin-image-picker](https://github.com/LittleSound/milkdown-plugin-image-picker)  \n  Add support for select and upload pictures from file picker.\n- [milkdown-plugin-placeholder](https://github.com/HexMox/milkdown-plugin-placeholder)  \n  🌈 Placeholder plugin for milkdown.\n- [@milkdown-lab/plugin-split-editing](https://www.npmjs.com/package/@milkdown-lab/plugin-split-editing)  \n  Show split editing view for milkdown.\n- [milkdown-lab](https://github.com/enpitsuLin/milkdown-lab)  \n  Unofficial plugins collection for milkdown.\n\n## Apps and Integrations\n\n- [milkdown-vscode](https://github.com/Saul-Mirone/milkdown-vscode)  \n  Use milkdown as markdown editor of VSCode.\n- [standardnotes](https://github.com/standardnotes/app)  \n  Use milkdown as editor of [Standard Notes](https://standardnotes.com/), it's made by the official of standardnotes.\n- [tagspaces](https://www.tagspaces.org/)  \n  Use milkdown as editor of markdown files.\n- [MarginNote-Milkdown](https://github.com/marginnoteapp/milkdown)  \n  Use milkdown as markdown editor of [MarginNote](https://www.marginnote.com/), it's made by the official of MarginNote. MarginNote is a brand new e-reader to better study and digest your books.\n- [lactose](https://github.com/lactoseapp/lactose)  \n  A web based note-taking tool.\n- [vite-plugin-book](https://github.com/Saul-Mirone/vite-plugin-book)  \n  A magical vite plugin that helps you to generate and manage documentation website.\n- [Howdz Dashboard](https://github.com/leon-kfd/Dashboard)  \n  Custom your personal browser start page from some configurable components.\n- [Doclea](https://github.com/FalkZ/doclea)  \n  Online doc editor.\n- [ezone](https://ezone.work/)  \n  一站式云原生企业研发协同与效能平台.\n- [standardnotes-milkdown](https://github.com/chuangzhu/standardnotes-milkdown)  \n  Use milkdown as editor of [Standard Notes](https://standardnotes.com/).\n- [typelog](https://typelog.dev)  \n  Microblogging platform for devs. Uses milkdown as the editor for writing posts and comments.\n\n## 🛠️ Technology\n\nThe site uses various technologies cobbled together. Here's some of them:\n\n- [Vite](https://vitejs.dev/): next generation frontend tooling.\n- [Svelte](https://svelte.dev/): s new way to build web applications.\n- [Milkdown](https://milkdown.dev/): plugin driven Markdown framework/editor.\n- [Tailwind CSS](https://tailwindcss.com/): utility-first CSS framework.\n- [Prettier](https://github.com/prettier/prettier): opinionated code formatter.\n\n\u003c!-- ## 💜 Attributions --\u003e\n\n## © License\n\nSource code in this repository is available under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemanticdata%2Fsvelte-milkdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsemanticdata%2Fsvelte-milkdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemanticdata%2Fsvelte-milkdown/lists"}