@ox-content/napi
Node.js bindings for Ox Content's Rust core.
Installation
pnpm add @ox-content/napi
Usage
Parse Markdown to AST
import { parseMarkdown } from '@ox-content/napi';
const markdown = '# Hello World\n\nThis is **bold** text.';
const ast = parseMarkdown(markdown, { gfm: true });
console.log(JSON.stringify(ast, null, 2));
Parse and Render
import { parseAndRender } from '@ox-content/napi';
const markdown = `
# Welcome
- Item 1
- Item 2
- Item 3
| Column A | Column B |
|----------|----------|
| Value 1 | Value 2 |
`;
const result = parseAndRender(markdown, {
gfm: true,
footnotes: true,
tables: true,
});
console.log(result.html);
API
parseMarkdown(content, options?)
Parses Markdown content and returns the AST.
Parameters
content:string- Markdown content to parseoptions:ParseOptions(optional)
Returns
MarkdownAst - The parsed AST
parseAndRender(content, options?)
Parses and renders Markdown to HTML in a single call.
Parameters
content:string- Markdown content to parseoptions:ParseOptions(optional)
Returns
interface RenderResult {
html: string;
frontmatter?: Record<string, unknown>;
toc?: TocEntry[];
}
Options
interface ParseOptions {
/** Enable GitHub Flavored Markdown */
gfm?: boolean;
/** Enable footnotes */
footnotes?: boolean;
/** Enable tables */
tables?: boolean;
/** Enable task lists */
taskLists?: boolean;
/** Enable strikethrough */
strikethrough?: boolean;
}
AST Types
The AST follows the mdast specification:
interface MarkdownNode {
type: string;
children?: MarkdownNode[];
value?: string;
// Additional properties based on node type
}
// Block nodes
type BlockNode =
| 'root'
| 'paragraph'
| 'heading'
| 'codeBlock'
| 'blockquote'
| 'list'
| 'listItem'
| 'table'
| 'tableRow'
| 'tableCell'
| 'thematicBreak'
| 'html';
// Inline nodes
type InlineNode =
| 'text'
| 'emphasis'
| 'strong'
| 'inlineCode'
| 'link'
| 'image'
| 'break'
| 'delete'
| 'footnoteReference';
Search API
The NAPI bindings include a full-text search engine.
buildSearchIndex(documents)
Builds a search index from an array of documents.
import { buildSearchIndex } from '@ox-content/napi';
const documents = [
{
id: 'getting-started',
title: 'Getting Started',
url: '/getting-started',
body: 'Welcome to the documentation...',
headings: ['Installation', 'Quick Start'],
code: ['npm install package'],
},
];
const indexJson = buildSearchIndex(documents);
searchIndex(indexJson, query, options?)
Searches a serialized index.
import { searchIndex } from '@ox-content/napi';
const results = searchIndex(indexJson, 'getting started', {
limit: 10,
prefix: true,
});
// results: Array<{
// id: string;
// title: string;
// url: string;
// score: number;
// matches: string[];
// snippet: string;
// }>
extractSearchContent(source, id, url, options?)
Extracts searchable content from Markdown source.
import { extractSearchContent } from '@ox-content/napi';
const markdown = '# Hello World\n\nThis is content.';
const doc = extractSearchContent(markdown, 'hello', '/hello', { gfm: true });
// doc: {
// id: 'hello',
// title: 'Hello World',
// url: '/hello',
// body: 'This is content.',
// headings: ['Hello World'],
// code: [],
// }
Performance
The NAPI bindings provide near-native performance:
| Operation | Time |
|---|---|
| Parse 1KB | ~50μs |
| Parse 10KB | ~200μs |
| Parse 100KB | ~1.5ms |
| Parse + Render 10KB | ~300μs |
Benchmarks run on Apple M1 Pro.