@hypertext-md/parser
v0.2.0
Published
Parser for Hypertext Markdown (HTMD) — Markdown with layout block syntax
Readme
@hypertext-md/parser
Parser for Hypertext Markdown (HTMD) — Markdown extended with layout block syntax. You write plain text, the parser turns it into a typed AST of layout blocks — heroes, grids, pricing tables, forms, and 30+ more.
Install
npm install @hypertext-md/parserQuick start
An .htmd document is Markdown plus ::: keyword blocks:
::: hero center
# Write websites. Don't click them together.
## Markdown with layout syntax.
[Open playground](/playground) [Read the syntax](/syntax)
:::parse turns it into a typed AST:
import { parse } from '@hypertext-md/parser';
const { frontmatter, blocks, errors } = parse(source);// blocks[0]
{
type: 'hero',
attrs: { align: 'center' },
heading: "Write websites. Don't click them together.",
subheading: 'Markdown with layout syntax.',
body: [],
ctas: [
{ label: 'Open playground', href: '/playground', variant: 'primary' },
{ label: 'Read the syntax', href: '/syntax', variant: 'secondary' },
],
}The parser is a pure function from string to AST — synchronous, no
I/O, no DOM, no dependencies. To turn the AST into HTML, pair it
with @hypertext-md/renderer
(or write your own renderer against the AST types):
import { parse, parseInline } from '@hypertext-md/parser';
import { defaultRenderer } from '@hypertext-md/renderer';
const { blocks } = parse(source);
const html = blocks
.map(b => defaultRenderer.renderBlock(b, { parseInline }))
.join('\n');Result (formatted for readability):
<section class="htmd-hero center">
<h1>Write websites. Don't click them together.</h1>
<h2>Markdown with layout syntax.</h2>
<div class="ctas">
<a href="/playground" class="btn-primary">Open playground</a>
<a href="/syntax" class="btn-secondary">Read the syntax</a>
</div>
</section>Full syntax reference and live playground: hypertext-md.com
What's here
Pure TypeScript source, no runtime dependencies. Distributed two ways:
- npm package
@hypertext-md/parser— for Node tooling, build plugins, the CLI, the VS Code extension, etc. - Browser bundle
htmd-parser.browser.js— a dependency-free IIFE bundle, published as a generic package.hypertext-md.comloads this artifact at build time instead of maintaining its own copy of the parser.
This two-way distribution resolves the technical debt described in
the main docs (CLAUDE.md in the hypertext-md.com repo, chapter
6.1): there's now only one parser implementation, compiled for two
targets.
Development
npm install
npm test # run the test suite (141 tests)
npm run typecheck
npm run build # → dist/index.js (npm distribution)
npm run build:browser # → dist/htmd-parser.browser.js (IIFE)API
import { parse } from '@hypertext-md/parser';
const { frontmatter, blocks, errors } = parse(htmdSource);frontmatter— key/value pairs from the optional---headerblocks— array of typed block nodes (seesrc/types.tsfor the full AST)errors— recoverable syntax problems; parsing never throws, unknown block keywords becomeunknownnodes
Each error carries line, message and raw. line is 1-based and
counted in the document you passed in, frontmatter included, so it can
be shown to a user or handed to an editor without adjustment. It points
at the block's ::: header.
Also exported: parseInline (inline markdown → HTML, used by
renderers) and the lower-level helpers extractFrontmatter,
parseAttrs, parseLinks, parseImage, parseHeading.
Versioning
Tags in the format vX.Y.Z trigger the npm release
(publish:npm job). Every push to the default branch also updates
the browser bundle in the package registry (latest tag and a
SHA-tagged version for reproducibility).
