{"id":13430360,"url":"https://github.com/rsms/markdown-wasm","last_synced_at":"2025-10-18T17:01:29.655Z","repository":{"id":41555454,"uuid":"226783527","full_name":"rsms/markdown-wasm","owner":"rsms","description":"Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c","archived":false,"fork":false,"pushed_at":"2022-11-22T17:28:20.000Z","size":621,"stargazers_count":1584,"open_issues_count":9,"forks_count":65,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-04-14T00:59:30.699Z","etag":null,"topics":["markdown","parser","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://rsms.me/markdown-wasm/","language":"C","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/rsms.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}},"created_at":"2019-12-09T04:19:41.000Z","updated_at":"2025-04-13T21:55:24.000Z","dependencies_parsed_at":"2023-01-21T20:46:07.238Z","dependency_job_id":null,"html_url":"https://github.com/rsms/markdown-wasm","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fmarkdown-wasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fmarkdown-wasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fmarkdown-wasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fmarkdown-wasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsms","download_url":"https://codeload.github.com/rsms/markdown-wasm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804790,"owners_count":21164132,"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":["markdown","parser","wasm","webassembly"],"created_at":"2024-07-31T02:00:52.683Z","updated_at":"2025-10-18T17:01:28.411Z","avatar_url":"https://github.com/rsms.png","language":"C","readme":"# markdown-wasm\n\nVery fast Markdown parser \u0026 HTML renderer implemented in WebAssembly\n\n- Zero dependencies (31 kB gzipped)\n- Portable \u0026 safe (WASM executes in isolated memory and can run almost anywhere)\n- [Simple API](#api)\n- [Very fast](#benchmarks)\n- Based on [md4c](http://github.com/mity/md4c) — compliant to the CommonMark specification\n\n\n## Examples\n\nIn NodeJS, single file with embedded compressed WASM\n\n```js\nconst markdown = require(\"./dist/markdown.node.js\")\nconsole.log(markdown.parse(\"# hello\\n*world*\"))\n```\n\nES module with WASM loaded separately\n\n```js\nimport * as markdown from \"./dist/markdown.es.js\"\nawait markdown.ready\nconsole.log(markdown.parse(\"# hello\\n*world*\"))\n```\n\nWeb browser\n\n```html\n\u003cscript src=\"markdown.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\nwindow[\"markdown\"].ready.then(markdown =\u003e {\n  console.log(markdown.parse(\"# hello\\n*world*\"))\n})\n\u003c/script\u003e\n```\n\n\n## Install\n\n```\nnpm install markdown-wasm\n```\n\n\n\n## Benchmarks\n\nThe [`test/benchmark`](test/benchmark) directory contain a benchmark suite which you can\nrun yourself. It tests a few popular markdown parser-renderers by parsing \u0026 rendering a bunch\nof different sample markdown files.\n\nThe following results were samples on a 2.9 GHz MacBook running macOS 10.15, NodeJS v14.11.0\n\n\n#### Average ops/second\n\nOps/second represents how many times a library is able to parse markdown and render HTML\nduring a second, on average across all sample files.\n\n![](test/benchmark/results/avg-ops-per-sec.svg)\n\n\n#### Average throughput\n\nThroughput is the average amount of markdown data processed during a second while both parsing\nand rendering to HTML. The statistics does not include HTML generated but only bytes of markdown\nsource text parsed.\n\n![](test/benchmark/results/avg-throughput.svg)\n\n\n#### Min–max parse time\n\nThis graph shows the spread between the fastest and slowest parse-and-render operations\nfor each library. Lower numbers are better.\n\n![](test/benchmark/results/minmax-parse-time.svg)\n\nSee [`test/benchmark`](test/benchmark#readme) for more information.\n\n\n## API\n\n```ts\n/**\n * parse reads markdown source at s and converts it to HTML.\n * When output is a byte array, it will be a reference.\n */\nexport function parse(s :Source, o? :ParseOptions \u0026 { bytes? :never|false }) :string\nexport function parse(s :Source, o? :ParseOptions \u0026 { bytes :true }) :Uint8Array\n\n/** Markdown source code can be provided as a JavaScript string or UTF8 encoded data */\ntype Source = string | ArrayLike\u003cnumber\u003e\n\n/** Options for the parse function */\nexport interface ParseOptions {\n  /** Customize parsing. Defaults to ParseFlags.DEFAULT */\n  parseFlags? :ParseFlags\n\n  /** Select output format. Defaults to \"html\" */\n  format? : \"html\" | \"xhtml\"\n\n  /**\n   * bytes=true causes parse() to return the result as a Uint8Array instead of a string.\n   *\n   * The returned Uint8Array is only valid until the next call to parse().\n   * If you need to keep the returned data around, call Uint8Array.slice() to make a copy,\n   * as each call to parse() uses the same underlying memory.\n   *\n   * This only provides a performance benefit when you never need to convert the output\n   * to a string. In most cases you're better off leaving this unset or false.\n   */\n  bytes? :boolean\n\n  /** Allow \"javascript:\" in links */\n  allowJSURIs? :boolean\n\n  /**\n   * Optional callback which if provided is called for each code block.\n   * langname holds the \"language tag\", if any, of the block.\n   *\n   * The returned value is inserted into the resulting HTML verbatim, without HTML escaping.\n   * Thus, you should take care of properly escaping any special HTML characters.\n   *\n   * If the function returns null or undefined, or an exception occurs, the body will be\n   * included as-is after going through HTML escaping.\n   *\n   * Note that use of this callback has an adverse impact on performance as it casues\n   * calls and data to be bridged between WASM and JS on every invocation.\n   */\n  onCodeBlock? :(langname :string, body :UTF8Bytes) =\u003e Uint8Array|string|null|undefined\n\n  /** @depreceated use \"bytes\" instead (v1.1.1) */\n  asMemoryView? :boolean\n}\n\n/** UTF8Bytes is a Uint8Array representing UTF8 text  */\nexport interface UTF8Bytes extends Uint8Array {\n  /** toString returns a UTF8 decoded string (lazily decoded and cached) */\n  toString() :string\n}\n\n/** Flags that customize Markdown parsing */\nexport enum ParseFlags {\n  /** In TEXT, collapse non-trivial whitespace into single ' ' */ COLLAPSE_WHITESPACE,\n  /** Enable $ and $$ containing LaTeX equations. */              LATEX_MATH_SPANS,\n  /** Disable raw HTML blocks. */                                 NO_HTML_BLOCKS,\n  /** Disable raw HTML (inline). */                               NO_HTML_SPANS,\n  /** Disable indented code blocks. (Only fenced code works.) */  NO_INDENTED_CODE_BLOCKS,\n  /** Do not require space in ATX headers ( ###header ) */        PERMISSIVE_ATX_HEADERS,\n  /** Recognize e-mails as links even without \u003c...\u003e */            PERMISSIVE_EMAIL_AUTO_LINKS,\n  /** Recognize URLs as links even without \u003c...\u003e */               PERMISSIVE_URL_AUTO_LINKS,\n  /** Enable WWW autolinks (without proto; just 'www.') */        PERMISSIVE_WWW_AUTOLINKS,\n  /** Enable strikethrough extension. */                          STRIKETHROUGH,\n  /** Enable tables extension. */                                 TABLES,\n  /** Enable task list extension. */                              TASK_LISTS,\n  /** Enable wiki links extension. */                             WIKI_LINKS,\n  /** Enable underline extension (disables '_' for emphasis) */   UNDERLINE,\n\n  /** Default flags are:\n   *    COLLAPSE_WHITESPACE |\n   *    PERMISSIVE_ATX_HEADERS |\n   *    PERMISSIVE_URL_AUTO_LINKS |\n   *    STRIKETHROUGH |\n   *    TABLES |\n   *    TASK_LISTS\n   */\n  DEFAULT,\n\n  /** Shorthand for NO_HTML_BLOCKS | NO_HTML_SPANS */\n  NO_HTML,\n}\n```\n\nSee [`markdown.d.ts`](markdown.d.ts)\n\n\n## Building from source\n\n```\nnpm install\nnpx wasmc\n```\n\nBuild debug version of markdown into ./build/debug and watch source files:\n\n```\nnpx wasmc -g -w\n```\n\nIf you need special builds, like for example an ES module with embedded WASM,\nedit the `wasmc.js` file and add `module({...})` directives.\n\nExample:\n\n```js\nmodule({ ...m,\n  name:   \"markdown-custom\",\n  out:    outdir + \"/markdown.custom.js\",\n  embed:  true,\n  format: \"es\",\n})\n```\n","funding_links":[],"categories":["C","打包工具"],"sub_categories":["非 JavaScript 编译工具"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Fmarkdown-wasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsms%2Fmarkdown-wasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Fmarkdown-wasm/lists"}