{"id":31940344,"url":"https://github.com/ruihe774/markdown-it-v","last_synced_at":"2026-04-05T08:33:17.822Z","repository":{"id":276075186,"uuid":"566401662","full_name":"ruihe774/markdown-it-v","owner":"ruihe774","description":"A custom markdown-it renderer that outputs virtual DOM","archived":false,"fork":false,"pushed_at":"2025-02-14T07:33:41.000Z","size":417,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-03T16:08:04.900Z","etag":null,"topics":["javascript","markdown","markdown-it","markdown-renderer","react","virtual-dom","vue"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruihe774.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-11-15T15:44:55.000Z","updated_at":"2025-02-14T07:33:45.000Z","dependencies_parsed_at":"2025-10-14T08:53:42.141Z","dependency_job_id":"a18e759c-6c8c-4115-91fb-c1a98d7a865b","html_url":"https://github.com/ruihe774/markdown-it-v","commit_stats":null,"previous_names":["ruihe774/markdown-it-v"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/ruihe774/markdown-it-v","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruihe774%2Fmarkdown-it-v","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruihe774%2Fmarkdown-it-v/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruihe774%2Fmarkdown-it-v/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruihe774%2Fmarkdown-it-v/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruihe774","download_url":"https://codeload.github.com/ruihe774/markdown-it-v/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruihe774%2Fmarkdown-it-v/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31430009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["javascript","markdown","markdown-it","markdown-renderer","react","virtual-dom","vue"],"created_at":"2025-10-14T08:52:59.065Z","updated_at":"2026-04-05T08:33:17.803Z","avatar_url":"https://github.com/ruihe774.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# markdown⁠-⁠it⁠-⁠v\nA custom markdown⁠-⁠it renderer that outputs virtual DOM.\n\n[![version](https://img.shields.io/npm/v/@ruihe774/markdown-it-v.svg?style=for-the-badge)](https://npmjs.com/package/@ruihe774/markdown-it-v)\n\n## Motivation\n\n### Why prefer virtual DOM to `innerHTML`?\n- Better integration with modern JavaScript frameworks like [Vue](https://vuejs.org) and [React](https://reactjs.org).\n- Better performance for real-time preview of large Markdown document. Thanks to the diff algorithm of virtual DOM, the real DOM modification can be minimized.\n\n### Why markdown⁠-⁠it⁠-⁠v\n- markdown⁠-⁠it itself has great performance.\n- markdown⁠-⁠it⁠-⁠v is a markdown⁠-⁠it plugin and can be integrated seamlessly.\n- markdown⁠-⁠it⁠-⁠v supports four schemes of output:\n\n  - Vue virtual DOM\n  - React virtual DOM\n  - Browser’s real DOM\n  - HTML string\n\n## Installation\n```console\n$ npm install markdown-it markdown-it-v@npm:@ruihe774/markdown-it-v@3 --save\n```\n\n## Usage\n\n### Setup\nmarkdown⁠-⁠it⁠-⁠v is a plugin of markdown⁠-⁠it:\n```javascript\nimport MarkdownIt from 'markdown-it'\nimport MarkdownItVPlugin from 'markdown-it-v'\n\nconst md = MarkdownIt().use(MarkdownItVPlugin)\n```\n\nIf you're using TypeScript, you can convert the enhanced markdown⁠-⁠it instance to the modified interface:\n```typescript\nimport MarkdownIt from 'markdown-it'\nimport MarkdownItVPlugin from 'markdown-it-v'\nimport type { MarkdownItV } from 'markdown-it-v'\n\nconst md = MarkdownIt().use(MarkdownItVPlugin) as unknown as MarkdownItV\n// or\nconst md = MarkdownItVPlugin(MarkdownIt())    // no type conversion needed\n```\n\n### Render\nAfter setup, the `render()` method will return a `StreamDom` object — a kind of virtual DOM implemented by markdown⁠-⁠it⁠-⁠v itself:\n```javascript\nlet sdom = md.render('The *quick* brown fox _jumps_ over the **lazy** dog.')\n```\n\n### Convert\nUnfortunately you cannot use `StreamDom` in other places and it doesn’t implement a diff algorithm. You must convert it to final output:\n```javascript\nlet vueVDom   = sdom.toVue(Vue.h)\nlet reactVDom = sdom.toReact(React.createElement)\nlet realDom   = sdom.toNative(document.createElement.bind(document))    // `.bind()` is necessary\nlet htmlStr   = sdom.toHTML()\n```\n\n### Integrate with JS Frameworks\nVue component (e.g. without JSX):\n```javascript\nVue.defineComponent({\n    // in a Vue component\n    props: ['source'],\n    computed: {\n        sDom() {\n            return md.render(this.source)\n        }\n    },\n    render() {\n        const { h } = Vue\n        return h('div', null, this.sDom.toVue(h))\n    }\n})\n```\n\nReact component (e.g. with JSX):\n```jsx\nfunction Markdown({ source }) {\n    // in a React component\n    const h = React.createElement\n    const sdom = useMemo(() =\u003e md.render(source), [source])\n    return \u003cdiv\u003e{sdom.toReact(h)}\u003c/div\u003e\n}\n```\n\nVanilla:\n```javascript\nconst container = document.createElement('div')\ncontainer.append(...sdom.toNative(document.createElement.bind(document)))\n```\n\n## Changelog\n\n- 3.1.0\n  - The entry function now returns md directly\n\n- 3.0.1\n  - Fix highlight fence\n  - Fix React refs\n\n- 3.0.0\n  - Return `(string | HTMLElement)[]` in `sdom.toNative`; do not require whole `document` object\n\n- 2.0.0\n  - Major refactor\n  - Migrate to TypeScript\n  - Upgrade all packages\n\n- 1.2.0\n  - Drop css-tree\n\n- 1.1.1\n  - Add ES6 module output\n\n- 1.1.0\n  - Adds highlightNoWrappingEls (#1) by @laosb\n\n- 1.0.0-beta.1\n  - No change\n\n- 1.0.0-alpha.2\n  - Use `_.fromPairs` in lodash\n\n- 1.0.0-alpha.1\n  - Initial release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruihe774%2Fmarkdown-it-v","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruihe774%2Fmarkdown-it-v","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruihe774%2Fmarkdown-it-v/lists"}