parse

import { parse } from "jsr:@ende/markdown";

function

function parse(markdown: string, options: ParseOptions = [UNSUPPORTED]): Root

Parses CommonMark into an mdast-shaped syntax tree. With the gfm option, it also parses the GitHub Flavored Markdown extensions: tables, task list items, strikethrough, extended autolinks, and footnotes, and GitHub's alerts (> [!NOTE]), which become admonition nodes.

Every heading gets an id made from its plain text, by default as GitHub makes it (see slug), and unique within the document: a second Install heading gets install-1.

Link reference definitions are resolved while parsing: reference links and images become ordinary link and image nodes carrying the definition's URL and title, and the definitions themselves don't appear in the tree. Footnote definitions do stay in the tree.

markdown: string

The Markdown source.

options: ParseOptions = [UNSUPPORTED]

Options for parsing.

Returns

The root of the syntax tree.

Example: Usage

import { parse } from "@ende/markdown/parse";
import { assertEquals } from "@ende/assert";

assertEquals(parse("# Hello *world*"), {
  type: "root",
  children: [{
    type: "heading",
    depth: 1,
    id: "hello-world",
    children: [
      { type: "text", value: "Hello " },
      { type: "emphasis", children: [{ type: "text", value: "world" }] }
    ]
  }]
});

Example: Reference links are resolved

import { parse } from "@ende/markdown/parse";
import { assertEquals } from "@ende/assert";

const root = parse("[Ende][home]\n\n[home]: https://ende.sh \"Home\"");
assertEquals(root.children, [{
  type: "paragraph",
  children: [{
    type: "link",
    url: "https://ende.sh",
    title: "Home",
    children: [{ type: "text", value: "Ende" }]
  }]
}]);

Example: GitHub Flavored Markdown

import { parse } from "@ende/markdown/parse";
import { assertEquals } from "@ende/assert";

const root = parse("- [x] ~~Write~~ docs at www.ende.sh", { gfm: true });
assertEquals(root.children, [{
  type: "list",
  ordered: false,
  start: null,
  spread: false,
  children: [{
    type: "listItem",
    spread: false,
    checked: true,
    children: [{
      type: "paragraph",
      children: [
        { type: "delete", children: [{ type: "text", value: "Write" }] },
        { type: "text", value: " docs at " },
        { type: "link", url: "http://www.ende.sh", title: null, children: [{ type: "text", value: "www.ende.sh" }] }
      ]
    }]
  }]
}]);

Example: Heading ids

import { parse } from "@ende/markdown/parse";
import type { Heading } from "@ende/markdown/types";
import { assertEquals } from "@ende/assert";

const ids = (root: ReturnType<typeof parse>) => root.children.map(node => (node as Heading).id);

assertEquals(ids(parse("# Install\n## Install `ende`\n## Install")), ["install", "install-ende", "install-1"]);
// A custom slugger replaces the algorithm; ids are still made unique.
assertEquals(ids(parse("# A B\n# A B", { slugger: text => text.replaceAll(" ", "_") })), ["A_B", "A_B-1"]);

Example: GitHub alerts

import { parse } from "@ende/markdown/parse";
import { assertEquals } from "@ende/assert";

assertEquals(parse("> [!WARNING]\n> Back up first.", { gfm: true }).children, [{
  type: "admonition",
  kind: "warning",
  children: [{ type: "paragraph", children: [{ type: "text", value: "Back up first." }] }]
}]);

Source