パッケージの詳細

@logue/markdown-wasm

logue131MIT1.5.3

Markdown parser and html generator implemented in WebAssembly

readme

@logue/markdown-wasm

jsdelivr CDN NPM Downloads Open in unpkg npm version Open in Gitpod Twitter Follow

Very fast Markdown parser & HTML renderer implemented in WebAssembly

  • Zero dependencies (87.83 kB gzipped without minify.)
  • Portable & safe (WASM executes in isolated memory and can run almost anywhere)
  • Simple API
  • Very fast
  • Based on md4c — compliant to the CommonMark specification

Install

yarn add markdown-wasm

Examples

ES module with WASM loaded separately

import { ready, parse } from './dist/markdown.es.js';
await ready();
console.log(parse('# hello\n*world*'));

Web browser

<script
  src="https://cdn.jsdelivr.net/npm/@logue/markdown-wasm@latest/dist/markdown.umd.js"
  crossorigin="anonymous"
></script>
<script>
  const markdown = await window['markdown'].ready()
  console.log(markdown.parse('# hello\n*world*'));
</script>

API

/** Options for the parse function */
export interface ParseOptions {
  /** Customize parsing. Defaults to ParseFlags.DEFAULT */
  parseFlags?: ParseFlagsType | number;

  /** Enable Debug log. Default is false */
  debug?: boolean;

  /** Use xhtml format. Default is true. */
  xhtml?: boolean;

  /** Output special characters as entity reference characters */
  verbatimEntities: boolean;

  /** Allow "javascript:" in links */
  allowJSURIs?: boolean;

  /** Disable anchor tag in headlines. Defaults to `false` */
  disableHeadlineAnchors?: boolean;

  /**
   * bytes=true causes parse() to return the result as a Uint8Array instead of a string.
   *
   * The returned Uint8Array is only valid until the next call to parse().
   * If you need to keep the returned data around, call Uint8Array.slice() to make a copy,
   * as each call to parse() uses the same underlying memory.
   *
   * This only provides a performance benefit when you never need to convert the output
   * to a string. In most cases you're better off leaving this unset or false.
   */
  bytes?: boolean;

  /**
   * Optional callback which if provided is called for each code block.
   * langname holds the "language tag", if any, of the block.
   *
   * The returned value is inserted into the resulting HTML verbatim, without HTML escaping.
   * Thus, you should take care of properly escaping any special HTML characters.
   *
   * If the function returns null or undefined, or an exception occurs, the body will be
   * included as-is after going through HTML escaping.
   *
   * Note that use of this callback has an adverse impact on performance as it casues
   * calls and data to be bridged between WASM and JS on every invocation.
   */
  onCodeBlock?: (
    langname: string,
    body: Uint8Array
  ) => Uint8Array | string | null;
}

/** ParseFlags */
export declare const ParseFlags: {
  /** In TEXT, collapse non-trivial whitespace into single ' ' */
  readonly COLLAPSE_WHITESPACE: 0x0001;
  /** Do not require space in ATX headers ( ###header ) */
  readonly PERMISSIVE_ATX_HEADERS: 0x0002;
  /** Recognize URLs as links even without <...> */
  readonly PERMISSIVE_URL_AUTO_LINKS: 0x0004;
  /** Recognize e-mails as links even without <...> */
  readonly PERMISSIVE_EMAIL_AUTO_LINKS: 0x0008;
  /** Disable indented code blocks. (Only fenced code works) */
  readonly NO_INDENTED_CODE_BLOCKS: 0x0010;
  /** Disable raw HTML blocks. */
  readonly NO_HTML_BLOCKS: 0x0020;
  /** Disable raw HTML (inline). */
  readonly NO_HTML_SPANS: 0x0040;
  /** Enable tables extension. */
  readonly TABLES: 0x0100;
  /** Enable strikethrough extension. */
  readonly STRIKETHROUGH: 0x0200;
  /** Enable WWW autolinks (without proto; just 'www.') */
  readonly PERMISSIVE_WWW_AUTOLINKS: 0x0400;
  /** Enable task list extension. */
  readonly TASK_LISTS: 0x0800;
  /** Enable $ and $$ containing LaTeX equations. */
  readonly LATEX_MATH_SPANS: 0x1000;
  /** Enable wiki links extension. */
  readonly WIKI_LINKS: 0x2000;
  /** Enable underline extension (disables '_' for emphasis) */
  readonly UNDERLINE: 0x4000;

  readonly PERMISSIVE_AUTOLINKS: 0x0008 | 0x0004 | 0x400; // PERMISSIVE_EMAIL_AUTO_LINKS | PERMISSIVE_URL_AUTO_LINKS | PERMISSIVE_WWW_AUTOLINKS
  readonly NO_HTML: 0x0020 | 0x0040; // NO_HTML_BLOCKS | NO_HTML_SPANS

  /** Default flags */
  readonly DEFAULT: 0x0001 | 0x0002 | 0x0004 | 0x0200 | 0x0100 | 0x0800; //  COLLAPSE_WHITESPACE | PERMISSIVE_ATX_HEADERS | PERMISSIVE_URL_AUTO_LINKS | STRIKETHROUGH | TABLES | TASK_LISTS

  /* Convenient sets of flags corresponding to well-known Markdown dialects.
   *
   * Note we may only support subset of features of the referred dialect.
   * The constant just enables those extensions which bring us as close as
   * possible given what features we implement.
   *
   * ABI compatibility note: Meaning of these can change in time as new
   * extensions, bringing the dialect closer to the original, are implemented.
   */
  readonly DIALECT_COMMONMARK: 0;
  /** Github Style */
  readonly DIALECT_GITHUB: 0x0008 | 0x0004 | 0x400 | 0x0100 | 0x0200 | 0x0800; // PERMISSIVE_AUTO_LINKS | TABLES | STRIKETHROUGH | TASK_LISTS

See markdown.d.ts

Building from source

Install latest emscripten to your environment.

pnpm install
pnpm build-wasm
pnpm build-bundle

Benchmarks

The test/benchmark directory contain a benchmark suite which you can run yourself. It tests a few popular markdown parser-renderers by parsing & rendering a bunch of different sample markdown files.

Test Environments

Core i7 13700K 4.75 GHz running on Windows 11 22H2, NodeJS v19.3.0

Name Version
commonmark 0.31.2
markdown-it 14.1.0
marked 15.0.7
micromark 4.0.2
remarkable 2.0.1
showdown 2.1.0

Average ops/second

Ops/second represents how many times a library is able to parse markdown and render HTML during a second, on average across all sample files.

Average ops/second

Average throughput

Throughput is the average amount of markdown data processed during a second while both parsing and rendering to HTML. The statistics does not include HTML generated but only bytes of markdown source text parsed.

Average throughput

Min–max parse time

This graph shows the spread between the fastest and slowest parse-and-render operations for each library. Lower numbers are better.

Min–max parse time

See test/benchmark for more information.

See Also

License

LICENSE

(c) 2019-2020 Rasmus Andersson https://rsms.me/

(c) 2023-2025 Masashi Yoshikawa https://logue.dev/

更新履歴

Changelog

All notable changes to this project will be documented in this file. Dates are displayed in UTC.

Generated by auto-changelog.

1.5.1

1.5.0

19 December 2024

1.4.8

6 April 2023

1.4.6

1 March 2023

  • chore(CODEOWNERS): CODEOWNERS.com Bot, at your service! #1
  • Update dependencies. 0686ddf
  • chore(CODEOWNERS): Update CODEOWNERS 50e9bf0

1.4.5

4 February 2023

  • Add Commonmark spec test. 3a72e07
  • Update dependencies. f8b347d
  • Execute commonmark spec test for each category. d6c0d7e

1.4.4

31 January 2023

  • Some tests were rewritten in vitest. f6bc54e
  • Fixed task list checkbox missing class. 2972311
  • Removed unused code. 548704c

1.4.3

27 January 2023

  • Fixed unable to grow wasm table error. 289c306

1.4.2

27 January 2023

  • Benchmark code to module, and re-calculate. 395fdf2
  • Update Benchmark Code and Result. 533d406
  • Dropped wasmc. Use emscripten directly. 78169ba

v1.2.0

30 June 2021

  • Disallow "javascript:" URIs in links. Adds option allowJSURIs to explicitly allow it. Closes #14 #14
  • adds onCodeBlock callback re #11 2938af6
  • upgrade wasmc to 2.2.1 da6fc41
  • improve example benchmark 571f5ce

v1.1.2

18 October 2020

  • md4c: bring in patch mity/md4c#131 and rsms/md4c@strengthen-build Closes #4 #4
  • release v1.1.2 b290af5

v1.1.1

16 October 2020

  • update example cce8d5c
  • rename "ParseOptions.asMemoryView" to "ParseOptions.bytes" b407df0
  • release v1.1.1 cb877fc

v1.1.0

16 October 2020

  • fixes a bug in md4c where indentation would include nul bytes. Closes #5 #5
  • adds benchmarks 3e65f82
  • adds test/spec 96d9547
  • initial commit 46892d1