stacks/ts-md
publicClone
Push over the same URL. A password will not work: create a token under access tokens and use it in place of one.
- .config
- .github
- .vscode
- benchmarks
- bin
- docs
- fixtures
- src
- test
- .editorconfig 147 B
- .gitattributes 12 B
- .gitignore 122 B
- build.ts 260 B
- bun.lock 61.7 KB
- bunfig.toml 106 B
- CHANGELOG.md 15.6 KB
- CLAUDE.md 1.5 KB
- deps.yaml 32 B
- LICENSE.md 1.1 KB
- markdown.config.ts 0 B
- md 39 B
- package.json 4.1 KB
- README.md 3.1 KB
- tsconfig.json 688 B
ts-md
High-performance markdown parser and sanitizer built for Bun.
Features
- GitHub Flavored Markdown (GFM) support
- Tables, task lists, strikethrough
- Header ID generation
- Syntax highlighting support
- HTML sanitization
- Frontmatter parsing (YAML, TOML, JSON)
Installation
bun add @stacksjs/ts-mdUsage
Basic Markdown Parsing
import { parseMarkdown } from '@stacksjs/ts-md'
const html = parseMarkdown('# Hello **world**')
// <h1 id="hello-world">Hello <strong>world</strong></h1>With Options
const html = parseMarkdown(markdown, {
gfm: true, // GitHub Flavored Markdown (default: true)
breaks: false, // Convert \n to <br> (default: false)
headerIds: true, // Generate header IDs (default: true)
headerPrefix: '', // Prefix for header IDs (default: '')
sanitize: false, // Sanitize HTML output (default: false)
highlight: (code, lang) => {
// Custom syntax highlighting
return highlightedCode
}
})HTML Sanitization
import { sanitizeHtml } from '@stacksjs/ts-md'
const clean = sanitizeHtml(userInput, {
allowedTags: ['p', 'strong', 'em', 'a', 'code'],
allowedAttributes: {
a: ['href', 'title']
},
allowedSchemes: ['http', 'https', 'mailto']
})Frontmatter Parsing
import { parseFrontmatter } from '@stacksjs/ts-md'
const content = `---
title: My Post
date: 2024-01-01
---
# Content here`
const { data, content: markdown } = parseFrontmatter(content)
console.log(data.title) // 'My Post'Performance
Benchmark results against popular markdown parsers:
| Document Size | @stacksjs/ts-md | markdown-it | marked | showdown |
|---|---|---|---|---|
| Small (< 1KB) | 324B ops/sec | 112B ops/sec | 26B ops/sec | 14B ops/sec |
| Medium (~3KB) | 34.7B ops/sec | 17.7B ops/sec | 2.8B ops/sec | 2.8B ops/sec |
| Large (~50KB) | 1.81B ops/sec | 1.25B ops/sec | 16M ops/sec | 135M ops/sec |
Performance vs markdown-it:
- Small documents: 2.89x faster
- Medium documents: 1.96x faster
- Large documents: 1.45x faster
The parser uses a flat token stream architecture with position-based parsing for optimal performance.
Architecture
The markdown parser is built with several key optimizations:
- Flat token stream: Avoids nested object allocations for better cache locality
- Position-based parsing: Minimizes string allocations with substring operations
- Optimized escapeHtml: Fast-path for strings without special characters
- Direct inline matching: Efficient emphasis and link parsing
- Recursive nested parsing: Proper support for nested inline elements
API
parseMarkdown(markdown: string, options?: MarkdownOptions): string
Parse markdown to HTML.
sanitizeHtml(html: string, options?: SanitizeOptions): string
Sanitize HTML to prevent XSS attacks.
parseFrontmatter(content: string): { data: any, content: string }
Extract and parse frontmatter from markdown content. Supports YAML, TOML, and JSON formats.
License
MIT