Peisar parses CommonMark Markdown with GitHub Flavored Markdown (GFM),
Kramdown block attributes, YAML front matter, source spans, AST visitors, and
custom parser hooks. The static-site tooling built on Peisar now lives in the
separate peisar-ssg package.
Features
- CommonMark blocks and inlines, including HTML and reference links
- GFM tables, strikethrough, task lists, and autolinks
- Kramdown block attributes such as
{:#intro .lead key="value"} - YAML front matter, returned separately from rendered Markdown
- Source spans on every AST node
- AST visitors and during-parse extension hooks
- A native N-API Node.js addon with generated TypeScript declarations
- A Rust library (
rlib) with public module paths for the parser, renderer, and high-level document APIs
Node.js
Install the package:
Create a Peisar document, then read its AST, rendered HTML, front matter, or
serialized AST:
const = require;
const document = ;
console.log; // <h1>Hello <strong>world</strong></h1>\n
console.log; // { nodeType: "root", children: [...], ... }
console.log; // JSON string
console.log; // object, or null
ast and astJson serialize the same tree differently: ast (the real
JavaScript object) uses PascalCase type values (Heading, Paragraph,
Link) and a nodeType: "root" root, while astJson mirrors the Rust
serialization with snake_case types (heading, paragraph, link) and a
type: "root" root.
Options
All options are optional. GFM and Kramdown are enabled by default; html
returns a complete document unless fragment is true.
const document = ;
charset, viewport, title, bodyClass, and style affect full-document
output only.
Front matter
Leading YAML front matter is removed before Markdown parsing and exposed as a JavaScript object:
const document = ;
console.log; // { title: "Hello", tags: ["docs"] }
console.log; // <h1>Hello</h1>\n
AST visitors
Register visitors with useVisitor. Each callback receives a one-item tuple,
may mutate the supplied node, and can return a control object. Return
{ recurse: true } to visit children; replacements are not visited again.
An omitted return value keeps the node without recursing.
const document = ;
document.;
console.log; // <h2>Hello</h2>\n
The control fields are insertBefore, insertAfter, replaceWith, remove,
and recurse. The same shape applies to visitInline.
Custom parser hooks
Use useParser for syntax that must be recognized while parsing. Block hooks
receive { line, lineIndex, lines }; inline hooks receive { rest, index }.
Hooks run before built-in matchers, in registration order. Return undefined
to decline a position.
const document = ;
const zero = ;
document.;
console.log; // <p>See <a href="/wiki/Some_Page">Some Page</a>.</p>\n
parseBlock must consume at least one line. parseInline must consume at
least one character; a missing or zero consumed value declines the result.
Peisar recomputes the source span of a hook-returned node, so a complete
placeholder pos is sufficient.
Rust
Add the crate to a Rust project:
[]
= "0.2.0"
The public Rust API is module-based. Import the parser from
peisar::markdown::ast, the renderer from peisar::markdown::html, and the
high-level document wrapper from peisar::markdown::peisar.
Parse and render
use ;
use Block;
use ;
let document = parse;
assert!;
let html = render_document_html;
assert_eq!;
For the Node-like parse-and-render wrapper:
use PeisarOptions;
use Peisar;
let mut document = new;
assert_eq!;
Front matter and visitors
use parse_markdown_frontmatter;
let parsed = parse_markdown_frontmatter?;
assert_eq!;
assert_eq!;
parse_markdown_frontmatter returns a ParseResult with yaml_data(),
pure_markdown_content(), and into_parts(). A front-matter block must open
with --- on the first non-whitespace line and close with a line starting
---; an unterminated block is treated as ordinary Markdown body.
For post-parse traversal, implement
peisar::markdown::ast::AstVisitor and call
peisar::markdown::ast::visitor::visit_document_mut. The visitor controls
are VisitControl and InlineVisitControl from that same visitor module.
AstParser and ParseHooks are publicly exported from
peisar::markdown::ast for integration with Peisar internals, but the
hook-enabled parser entry point is not yet public to external Rust consumers.
Use useParser from Node.js for registered custom syntax today.
Development
Run npm run build:local after changing N-API-annotated Rust code; it
regenerates the package loader and TypeScript declarations before the Node.js
tests run.
More detail in CONTRIBUTING
AI integration
Peisar supplies Agent Skills for AI coding tools:
- peisar-parse-markdown: consume the Node.js and Rust Markdown APIs
- peisar-ast-visitors: make post-parse AST transformations
- peisar-parser-hooks: add syntax recognized during parsing
- peisar-development: modify and validate the codebase
Project structure
src/
├── frontmatter/ YAML front-matter parser
├── markdown/
│ ├── ast/ AST nodes, parsers, visitors, and hooks
│ ├── config/ combined parser and renderer options
│ ├── html/ HTML renderer
│ └── peisar/ high-level N-API `Peisar` class
└── lib.rs public module declarations
LICENSE
Security policy: SECURITY.md