Skip to content

@lanexio/parser-grammar-markdown

This page documents @lanexio/parser-grammar-markdown, the Markdown grammar package implementing CommonMark 0.31.2 with GitHub Flavored Markdown (GFM) extensions: tables, task lists, strikethrough, autolinks, and more.

  • Version: Stable
  • Module name: parser-grammar-markdown
  • Package: @lanexio/parser-grammar-markdown
  • Import path: @lanexio/parser-grammar-markdown
  • Layer: 2 (Grammar)
  • Runtime: Universal (browser, server, edge worker)
  • Module format: ESM
  • Stability: Stable
  • Primary use case: Parse CommonMark and GFM Markdown documents into a flat AST.
  • You need to parse Markdown documents (CommonMark or GFM) into a traversable AST.
  • You need to serialize a parsed Markdown tree back to Markdown source (roundtrip).
  • You want to extract text content or render Markdown to HTML.
BoundaryDescription
InputsUint8Array (source bytes) + optional ParseMarkdownOptions
OutputsLexTree (flat AST rooted at MdKind.Document)
Side effectsSide-effect import ./embed.js registers fenced-code-block embeddings for CSS, JSON, HTML guest languages
DeterminismYes (same bytes + same options produce identical tree)
External dependencies@lanexio/parser-core
Never-throw guaranteeYes for all parse entry points
Security surfaceSerializer output emits raw Markdown source. renderMarkdownHtml emits raw HTML.
  1. Install the package.

    Terminal window
    pnpm add @lanexio/parser-grammar-markdown
  2. Import the named export.

    import { parseMarkdown } from '@lanexio/parser-grammar-markdown';
RequirementRequiredLayerNotes
@lanexio/parser-coreYes1^1.0.0
import { parseMarkdown } from '@lanexio/parser-grammar-markdown';
const encoder = new TextEncoder();
const bytes = encoder.encode('# Hello\n\nA paragraph with **bold** text.');
const tree = parseMarkdown(bytes);
console.log(tree.nodeCount); // total nodes in the flat AST
console.log(tree.root.kind); // MdKind.Document
import { parseMarkdown } from '@lanexio/parser-grammar-markdown';
const encoder = new TextEncoder();
const tree = parseMarkdown(
encoder.encode('# CommonMark only'),
{ gfm: false }
);
import { parseMarkdown, serializeMarkdown } from '@lanexio/parser-grammar-markdown';
const encoder = new TextEncoder();
const tree = parseMarkdown(encoder.encode('# Hello\n\nA paragraph.'));
const markdown = serializeMarkdown(tree);
// "# Hello\n\nA paragraph.\n"
ExportTypeDescription
parseMarkdown(source: Uint8Array, options?: ParseMarkdownOptions) => LexTreeParse Markdown. Never throws.
parseMarkdownWithScan(source: Uint8Array, options?: ParseMarkdownOptions) => Promise<LexTree>Parse Markdown with pre-computed structural scan. Async.
serializeMarkdown(input: LexTree | LexNode) => stringSerialize tree back to Markdown source (roundtrip).
renderMarkdownHtml(tree: LexTree, options?: RenderMarkdownHtmlOptions) => stringRender Markdown tree to HTML string.
textContent(node: LexNode) => stringExtract plain text from a Markdown tree.
MdKindconst objectNumeric kind IDs for all Markdown node types.
MdFieldconst objectNumeric field IDs for Markdown element slots.
MD_FIELD_NAMES_BY_IDreadonly string[]Field name lookup by numeric field ID.
MdParseErrorCodeconst objectParse error code constants.
MD_FLAG_HEADING_LEVEL_MASKnumberBitmask for heading level in node flags.
MD_FLAG_HEADING_LEVEL_SHIFTnumberBit shift for heading level in node flags.
MD_FLAG_LIST_LOOSEnumberFlag for loose list items.
mdEncodeHeadingLevel(level: number) => numberEncode heading level into node flags.
mdHeadingLevel(flags: number) => numberDecode heading level from node flags.
mdListIsLoose(flags: number) => booleanCheck if a list node is loose.
markdownGrammarLanexioParserPureGrammarGrammar descriptor for use with parser-pure.
markdownRegistrationGrammarRegistrationRegistration for the unified grammar registry.
FieldTypeRequiredDefaultDescription
gfmbooleanNotrueEnable GFM extensions (tables, task lists, strikethrough, autolinks).
extendedAutolinkbooleanNotrue (when gfm: true)Enable GFM extended autolink detection (bare URLs, www. hosts, email).
useSimdScanbooleanNofalseUse SIMD or scalar pre-scan for delimiter bytes during inline parsing.
FieldTypeRequiredDefaultDescription
(reserved)---Reserved for future extension.
PropertyTypeDescription
rootLexNodeRoot node (MdKind.Document).
nodeCountnumberTotal nodes in the tree.
sourceUint8ArrayOriginal parsed bytes.
TypePurposeNotes
ParseMarkdownOptionsOptions for parseMarkdownSee options table above.
RenderMarkdownHtmlOptionsOptions for renderMarkdownHtmlReserved for future extension.
MdParseErrorParse error descriptorReturned via error codes.

GFM extensions are enabled by default. This includes tables, task list items, strikethrough, autolinks, and extended autolinks. Pass { gfm: false } to restrict to strict CommonMark 0.31.2 only.

Side-effect import ./embed.js registers known guest languages (CSS, JSON, HTML) for fenced code block embedding. When a fenced code block has an info string matching a registered language, the block content can be parsed as the guest language.

The Markdown parser preserves the document outline (headings, lists) in the AST structure. Serialization output preserves semantic Markdown syntax. renderMarkdownHtml produces HTML that preserves semantic structure.

ConcernStatus
Generated output semanticsPreserves document structure (headings, lists, emphasis)
ARIA attributes in serialized outputNot applicable (Markdown source output)
Semantic element round-tripYes (parse.serialize.parse is structurally identical)
  • parseMarkdown never throws on any byte sequence.
  • renderMarkdownHtml emits raw HTML — callers must sanitize before browser insertion.
  • serializeMarkdown emits raw Markdown source, not HTML.
ThreatMitigationStatus
Malformed input byte sequencePanic-free guarantee: all inputs accepted, errors produce LexError AST nodesImplemented
XSS via HTML renderer outputrenderMarkdownHtml emits raw HTML — caller is responsible for safe insertionDocumented
PackageRelationshipLayerNotes
@lanexio/parser-coreRequires1Provides LexTree, LexNode, LexCursor
@lanexio/parser-grammar-htmlDev dependency2Used for HTML embedding in fenced code blocks
@lanexio/parser-pureConsumes4Wraps parseMarkdown in a unified bridge
import { parseMarkdown, MdKind } from '@lanexio/parser-grammar-markdown';
import { LexQuery } from '@lanexio/parser-query';
const encoder = new TextEncoder();
const tree = parseMarkdown(encoder.encode('# Title\n\nA paragraph.\n\n- item one\n- item two'));
const resolver = (name: string) => (MdKind as Record<string, number | undefined>)[name];
const query = LexQuery.compile('Item', resolver);
for (const node of query.matches(tree)) {
console.log(node.kind, node.range);
}
VersionDateStatusNotable changes
1.0.02026-05-29CurrentInitial stable release. Apache-2.0.
  • None.