Parse API
String Parsing
parse(source: string): ComarkTree
Parses Comark content from a string and returns the complete parsed structure.
Parameters:
source- The markdown/Comark content as a stringoptions?- Parser options including plugins
Returns: ComarkTree object containing:
nodes- The parsed Comark AST nodesfrontmatter- Frontmatter data parsed from YAMLmeta- Additional metadata from plugins (e.g.,toc,summary)
Example:
import { parse } from 'comark'
const content = `---
title: Hello World
description: A simple example
---
# Hello World
This is a **markdown** document with *Comark* components.
::alert{type="info"}
This is an alert component
::
`
const result = await parse(content)
console.log(result.frontmatter)
{ "title": "Hello World", "description": "A simple example" }
Reusable Parser
createParse(options?): (source: string) => Promise<ComarkTree>
Creates a reusable parser function with pre-configured options. Unlike parse() which creates a new parser instance on each call, createParse() returns a parser function that can be called multiple times with the same configuration.
Benefits:
- Performance: Parser and plugins are initialized once, not on every parse
- Consistency: All documents parsed with the same configuration
- Memory efficiency: Single parser instance handles multiple documents
- Ideal for batch processing: Perfect when parsing many files
Parameters:
options?- Parser options (same asparse())
Returns: An async parser function (source: string) => Promise<ComarkTree>
Example:
import { createParse } from 'comark'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
import emoji from 'comark/plugins/emoji'
import toc from 'comark/plugins/toc'
// Create a parser with specific configuration
const parse = createParse({
autoUnwrap: true,
autoClose: true,
plugins: [
highlight({
themes: { light: githubLight, dark: githubDark }
}),
emoji(),
toc()
]
})
// Reuse the parser for multiple documents
const doc1 = await parse('# Document 1\n\nContent...')
const doc2 = await parse('# Document 2\n\nMore content...')
const doc3 = await parse('# Document 3\n\nEven more...')
Use Case: Static Site Generator
import { createParse } from 'comark'
import { readdir, readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { renderHTML } from 'comark/string'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
import toc from 'comark/plugins/toc'
import emoji from 'comark/plugins/emoji'
async function buildSite(contentDir: string, outDir: string) {
// Create parser once with all desired plugins
const parse = createParse({
plugins: [
highlight({
themes: { light: githubLight, dark: githubDark }
}),
toc({ depth: 3 }),
emoji()
]
})
const files = await readdir(contentDir)
const mdFiles = files.filter(f => f.endsWith('.md'))
// Parse all files with the same parse instance
for (const file of mdFiles) {
const content = await readFile(join(contentDir, file), 'utf-8')
const tree = await parse(content)
const html = renderHTML(tree)
await writeFile(
join(outDir, file.replace('.md', '.html')),
html
)
}
console.log(`Built ${mdFiles.length} pages`)
}
await buildSite('./content', './dist')
Use Case: API Server
import { createParse } from 'comark'
import security from 'comark/plugins/security'
// Create parser once when server starts
const parse = createParse({
plugins: [
security() // Sanitize user-generated content
]
})
// Reuse parser for every request
app.post('/api/markdown', async (req, res) => {
try {
const tree = await parse(req.body.content)
res.json({ success: true, tree })
} catch (error) {
res.status(400).json({ error: 'Invalid markdown' })
}
})
Performance Comparison
import { parse, createParse } from 'comark'
import highlight from 'comark/plugins/highlight'
const content = '```js\nconsole.log("hello")\n```'
// ❌ Slow: Creates new parser + highlighter for each parse
console.time('parse x1000')
for (let i = 0; i < 1000; i++) {
await parse(content, {
plugins: [highlight()]
})
}
console.timeEnd('parse x1000')
// → ~8000ms (parser + highlighter recreated 1000 times)
// ✅ Fast: Reuses same parser + highlighter instance
console.time('createParse x1000')
const parse = createParse({
plugins: [highlight()]
})
for (let i = 0; i < 1000; i++) {
await parse(content)
}
console.timeEnd('createParse x1000')
// → ~800ms (10x faster! parser + highlighter created once)
Types
ComarkTree
The main return type for all parse functions.
interface ComarkTree {
nodes: ComarkNode[] // The parsed AST nodes
frontmatter: Record<string, any> // YAML frontmatter data
meta: {
toc?: any // Table of contents (from toc plugin)
summary?: ComarkNode[] // Summary content (from summary plugin)
[key: string]: any // Other plugin metadata
}
}
ComarkNode
type ComarkNode = ComarkElement | ComarkText
type ComarkText = string
type ComarkElement = [string, ComarkElementAttributes, ...ComarkNode[]]
type ComarkElementAttributes = {
[key: string]: unknown
}
Processing Multiple Files
For better performance when processing multiple files, use createParse() instead of parse():
import { readdir, readFile } from 'node:fs/promises'
import { join } from 'node:path'
import { createParse } from 'comark'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
async function processMarkdownDirectory(dir: string) {
const files = await readdir(dir)
const mdFiles = files.filter(f => f.endsWith('.md'))
// Create parser once
const parse = createParse({
plugins: [
highlight({
themes: { light: githubLight, dark: githubDark }
})
]
})
// Reuse parser for all files
const results = await Promise.all(
mdFiles.map(async (file) => {
const content = await readFile(join(dir, file), 'utf-8')
const result = await parse(content)
return { file, result }
})
)
return results
}
// Usage
const results = await processMarkdownDirectory('./content')
console.log(`Processed ${results.length} files`)
Frontmatter Parsing
The parse functions automatically extract and parse YAML frontmatter:
const content = `---
title: My Document
tags:
- javascript
- markdown
author:
name: John Doe
email: john@example.com
---
# Content here
`
const result = await parse(content)
console.log(result.frontmatter)
{
"title": "My Document",
"tags": ["javascript", "markdown"],
"author": { "name": "John Doe", "email": "john@example.com" }
}
Table of Contents
The parse functions automatically generate a table of contents based on headings:
const content = `# Main Title
## Section 1
Some content here.
### Subsection 1.1
More content.
## Section 2
Final content.
`
const result = await parse(content)
console.log(result.meta.toc)
{
"title": "Main Title",
"depth": 2,
"searchDepth": 2,
"links": [
{ "id": "section-1", "text": "Section 1", "depth": 2, "children": [
{ "id": "subsection-11", "text": "Subsection 1.1", "depth": 3 }
]},
{ "id": "section-2", "text": "Section 2", "depth": 2 }
]
}
Summary Extraction
Content before the <!-- more --> comment is extracted as a summary when using the summary plugin:
import { parse } from 'comark'
import summary from 'comark/plugins/summary'
const content = `# Article Title
This is the introduction paragraph that will be used as a summary.
<!-- more -->
This is the full article content that won't appear in the summary.
`
const result = await parse(content, {
plugins: [summary()]
})
console.log(result.meta.summary)
// ComarkNode[] with only the content before <!-- more -->
HTML Parsing
HTML tags embedded in Comark content are parsed into AST nodes by default and can be mixed freely with Comark components and markdown syntax.
const content = `
<div class="note">
::alert{type="info"}
Hello <strong class="text-red-500">world</strong>
::
</div>
`
const result = await parse(content)
console.log(result.nodes)
[
["div", { "class": "note" },
["alert", { "type": "info" },
"Hello ",
["strong", { "class": "text-red-500" }, "world"]
]
]
]
To disable HTML parsing and treat tags as plain text, set html: false:
const result = await parse(content, { html: false })
Error Handling
import { parse } from 'comark'
import { readFile } from 'node:fs/promises'
try {
const content = await readFile('content.md', 'utf-8')
const result = await parse(content)
console.log('Parsed successfully:', result.nodes)
}
catch (error) {
console.error('Parse error:', error)
}
See Also
- Auto-Close API - Handling incomplete syntax
- API Reference - Quick reference for all exports
- Vue Renderer - Rendering parsed content in Vue
- React Renderer - Rendering parsed content in React