Pure markdown parser and renderer utilities with streaming support - framework agnostic
npm install stream-markdown-parser




纯 JavaScript Markdown 解析器和渲染工具,支持流式处理 - 框架无关。
该包包含从 markstream-vue 中提取的核心 Markdown 解析逻辑,使其可以在任何 JavaScript/TypeScript 项目中使用,无需 Vue 依赖。
- 🚀 纯 JavaScript - 无框架依赖
- 📦 轻量级 - 最小打包体积
- 🔧 可扩展 - 基于插件的架构
- 🎯 类型安全 - 完整的 TypeScript 支持
- ⚡ 高性能 - 性能优化
- 🌊 流式友好 - 支持渐进式解析
> ℹ️ 自当前版本起我们基于 markdown-it-ts(一个 TypeScript 优先的 markdown-it 发行版)进行构建。API 与 markdown-it 保持一致,但内部仅依赖其解析流程,并提供更丰富的 token 类型定义。
完整的使用说明与集成教程见 markstream-vue 文档站:
- English: https://markstream-vue-docs.simonhe.me/guide/api
- 中文: https://markstream-vue-docs.simonhe.me/zh/guide/api
本 README 聚焦解析器 API;如需 VitePress/Vite/Nuxt 集成、Worker 流式解析、Tailwind/UnoCSS 配置等指南,请查阅上述文档。
``bash`
pnpm add stream-markdown-parser或
npm install stream-markdown-parser或
yarn add stream-markdown-parser
- getMarkdown(msgId?, options?) — 返回一个预配置的 markdown-it-ts 实例;支持 plugin、apply、i18n 等选项(内置任务列表、上下标、数学等插件)。registerMarkdownPlugin(plugin)
- / clearRegisteredMarkdownPlugins() — 全局注册/清除插件,在所有 getMarkdown() 调用中生效(适合特性开关或测试环境)。parseMarkdownToStructure(markdown, md, parseOptions)
- — 将 Markdown 转换为可供 markstream-vue 等渲染器使用的 AST。processTokens(tokens)
- / parseInlineTokens(children, content?, preToken?, options?) — 更底层的 token → 节点工具,方便自定义管线。applyMath
- 、applyContainers、normalizeStandaloneBackslashT、findMatchingClose 等 — 用于构建自定义解析、lint 或内容清洗流程。
``
Markdown 字符串
↓ getMarkdown() → 带插件的 markdown-it-ts 实例
parseMarkdownToStructure(markdown, md) → AST (ParsedNode[])
↓ 交给你的渲染器(markstream-vue、自定义 UI、Worker 等)
多次解析时复用同一个 md 实例可以避免重复注册插件。与 markstream-vue 一起使用时,你可以把 AST 传给 ,或仅传入原始 content 并共享同一套解析配置。
处理 AI/SSE 流时,可以复用同一个 md 实例不停地对累积缓冲区解析,并把 AST 推送给 UI(例如 markstream-vue):
`ts
import { getMarkdown, parseMarkdownToStructure } from 'stream-markdown-parser'
const md = getMarkdown()
let buffer = ''
async function handleChunk(chunk: string) {
buffer += chunk
const nodes = parseMarkdownToStructure(buffer, md)
postMessage({ type: 'markdown:update', nodes })
}
`
在前端通过 渲染即可避免重复解析。具体串联示例见文档用法指南。
`typescript
import { getMarkdown, parseMarkdownToStructure } from 'stream-markdown-parser'
// 创建一个带有默认插件的 markdown-it-ts 实例
const md = getMarkdown()
// 将 Markdown 解析为流式友好的 AST 结构
const nodes = parseMarkdownToStructure('# Hello World', md)
console.log(nodes)
// [{ type: 'heading', level: 1, children: [...] }]
// 如果仍需 HTML 输出,markdown-it-ts 依旧提供 render()
const html = md.render?.('# Hello World\n\nThis is bold.')
`
`typescript
import { getMarkdown, setDefaultMathOptions } from 'stream-markdown-parser'
// 设置全局数学公式选项
setDefaultMathOptions({
commands: ['infty', 'perp', 'alpha'],
escapeExclamation: true
})
const md = getMarkdown()
`
`typescript
import { getMarkdown } from 'stream-markdown-parser'
// 使用翻译映射
const md = getMarkdown('editor-1', {
i18n: {
'common.copy': '复制',
}
})
// 或使用翻译函数
const md = getMarkdown('editor-1', {
i18n: (key: string) => translateFunction(key)
})
`
`typescript
import customPlugin from 'markdown-it-custom-plugin'
import { getMarkdown } from 'stream-markdown-parser'
const md = getMarkdown('editor-1', {
plugin: [
[customPlugin, { / 选项 / }]
]
})
`
`typescript
import { getMarkdown } from 'stream-markdown-parser'
const md = getMarkdown('editor-1', {
apply: [
(md) => {
// 添加自定义内联规则
md.inline.ruler.before('emphasis', 'custom', (state, silent) => {
// 你的自定义逻辑
return false
})
}
]
})
`
想在所有 getMarkdown() 实例上启用同一个插件,而无需修改调用点?可使用内置 helper:
`ts
import {
clearRegisteredMarkdownPlugins,
registerMarkdownPlugin,
} from 'stream-markdown-parser'
registerMarkdownPlugin(myPlugin)
const md = getMarkdown()
// 现在 md 会自动包含 myPlugin
// 测试或清理阶段:
clearRegisteredMarkdownPlugins()
`
- plugin 选项 → 针对单次 getMarkdown 调用传入 md.use(...)。apply
- 选项 → 直接操作实例(如 md.inline.ruler.before(...))。如果需要严格模式,可自行包裹 try/catch;默认会打印错误保持兼容。registerMarkdownPlugin
- → 全局注册表,适用于 SSR / Worker 等场景统一开启功能。
#### getMarkdown(msgId?, options?)
创建一个配置好的 markdown-it-ts 实例(与 markdown-it API 兼容)。
参数:
- msgId (string, 可选): 该实例的唯一标识符。默认值:editor-${Date.now()}options
- (GetMarkdownOptions, 可选): 配置选项
选项:
`typescript
interface GetMarkdownOptions {
// 要使用的 markdown-it / markdown-it-ts 插件数组
plugin?: Array
// 修改 md 实例的函数数组
apply?: Array<(md: MarkdownIt) => void>
// 翻译函数或翻译映射
i18n?: ((key: string) => string) | Record
}
`
#### parseMarkdownToStructure(content, md, options?)
将 Markdown 内容解析为结构化节点树。
参数:
- content (string): 要解析的 Markdown 内容md
- (MarkdownItCore): 由 getMarkdown() 创建的 markdown-it-ts 实例options
- (ParseOptions, 可选): 带有钩子的解析选项
返回值: ParsedNode[] - 解析后的节点数组
#### processTokens(tokens)
将原始 markdown-it tokens 处理为扁平数组。
#### parseInlineTokens(tokens, content?, preToken?, options?)
解析内联 markdown-it-ts tokens 并产出节点。可传入原始 content(来自父 token)、可选的前一个 token,以及 inline 解析选项(requireClosingStrong、customHtmlTags)。
#### setDefaultMathOptions(options)
设置全局数学公式渲染选项。
参数:
- options (MathOptions): 数学公式配置选项
`typescript`
interface MathOptions {
commands?: readonly string[] // 要转义的 LaTeX 命令
escapeExclamation?: boolean // 转义独立的 '!' (默认: true)
}
ParseOptions 支持以下钩子与标志:
`ts**
interface ParseOptions {
preTransformTokens?: (tokens: Token[]) => Token[]
postTransformTokens?: (tokens: Token[]) => Token[]
// 自定义 HTML 类标签,作为自定义节点输出(如 ['thinking'])
customHtmlTags?: string[]
// true 表示输入已结束(end-of-stream)
final?: boolean
// 解析 strong 时要求闭合 (默认 false)`
requireClosingStrong?: boolean
}
示例 —— 标记 AI "思考" 块:
`ts
const parseOptions = {
customHtmlTags: ['thinking'],
}
const nodes = parseMarkdownToStructure(markdown, md, parseOptions)
const tagged = nodes.map(node =>
node.type === 'html_block' && /
? { ...node, meta: { type: 'thinking' } }
: node,
)
`
在渲染器中读取 node.meta 即可渲染自定义 UI,而无需直接修改 Markdown 文本。
默认情况下,非标准的 HTML 类标签(例如 )在完整闭合时会按原生 HTML 渲染(作为自定义元素输出);流式场景下未闭合的片段会先按纯文本处理以避免闪烁。若希望它们作为自定义节点输出(type: 'question',携带 attrs/content),需要在 customHtmlTags 中显式声明。
#### isMathLike(content)
启发式函数,用于检测内容是否类似数学符号。
参数:
- content (string): 要检查的内容
返回值: boolean
#### findMatchingClose(src, startIdx, open, close)
在字符串中查找匹配的闭合分隔符,处理嵌套对。
参数:
- src (string): 源字符串startIdx
- (number): 开始搜索的索引open
- (string): 开启分隔符close
- (string): 闭合分隔符
返回值: number - 匹配闭合的索引,如果未找到则返回 -1
- 复用解析实例:缓存 getMarkdown() 的结果,避免重复注册插件。parseMarkdownToStructure
- 服务端解析:在服务端运行 后把 AST 下发给客户端,配合 markstream-vue 实现确定性输出。
- 自定义 HTML 组件:在解析前先把 这类片段替换为占位符,渲染时再注入,避免在 html_block 上进行脆弱的字符串操作。markstream-vue
- 样式提示:如果将节点交给 ,务必按照文档的 CSS 排查清单 调整 reset / layer,防止 Tailwind/UnoCSS 覆盖样式。apply
- 错误处理: 钩子内部默认捕获异常后打印日志,如需在 CI/生产中抛出错误,可在传入前自行封装并 rethrow。
#### parseFenceToken(token)
将代码围栏 token 解析为 CodeBlockNode。
参数:
- token (MarkdownToken): markdown-it token
返回值: CodeBlockNode
#### normalizeStandaloneBackslashT(content, options?)
规范化数学内容中的反斜杠-t 序列。
参数:
- content (string): 要规范化的内容options
- (MathOptions, 可选): 数学选项
返回值: string
需要更细粒度地控制 token → AST 流程时,可直接使用以下导出:
`ts
import type { MarkdownToken } from 'stream-markdown-parser'
import {
parseInlineTokens,
processTokens
} from 'stream-markdown-parser'
const tokens: MarkdownToken[] = md.parse(markdown, {})
const nodes = processTokens(tokens)
// 或仅解析内联内容:
const inlineNodes = parseInlineTokens(tokens[0].children ?? [], tokens[0].content ?? '')
`
processTokens 即 parseMarkdownToStructure 内部使用的同一个转换器,可在自定义管线中复用,避免重复实现 Markdown-it 遍历。
#### applyMath(md, options?)
将数学插件应用到 markdown-it 实例。
参数:
- md (MarkdownIt): markdown-it 实例options
- (MathOptions, 可选): 数学渲染选项
#### applyContainers(md)
将容器插件应用到 markdown-it 实例。
参数:
- md (MarkdownIt): markdown-it 实例
#### KATEX_COMMANDS
用于转义的常用 KaTeX 命令数组。
#### TEX_BRACE_COMMANDS
使用大括号的 TeX 命令数组。
#### ESCAPED_TEX_BRACE_COMMANDS
用于正则表达式的 TEX_BRACE_COMMANDS 转义版本。
所有 TypeScript 类型都已导出:
`typescript`
import type {
// 节点类型
CodeBlockNode,
GetMarkdownOptions,
HeadingNode,
ListItemNode,
ListNode,
MathOptions,
ParagraphNode,
ParsedNode,
ParseOptions,
// ... 更多
} from 'stream-markdown-parser'
解析器导出各种表示不同 Markdown 元素的节点类型:
- TextNode, HeadingNode, ParagraphNodeListNode
- , ListItemNodeCodeBlockNode
- , InlineCodeNodeLinkNode
- , ImageNodeBlockquoteNode
- , TableNodeMathBlockNode
- , MathInlineNode
- 以及更多...
该包预配置了以下 markdown-it 插件:
- markdown-it-sub - 下标支持(H~2~O)markdown-it-sup
- - 上标支持(x^2^)markdown-it-mark
- - 高亮/标记支持(==highlighted==)markdown-it-task-checkbox
- - 任务列表支持(- [ ] Todo)markdown-it-ins
- - 插入标签支持(++inserted++)markdown-it-footnote
- - 脚注支持markdown-it-container
- - 自定义容器支持(::: warning, ::: tip 等)$...$
- 数学公式支持 - 使用 和 $$...$$ 渲染 LaTeX 数学公式
虽然该包与框架无关,但它被设计为可以无缝配合以下框架使用:
- ✅ Node.js - 服务器端渲染
- ✅ Vue 3 - 配合 markstream-vue(或你的自定义渲染层)使用
- ✅ React - 使用解析的节点进行自定义渲染
- ✅ Vanilla JS - 直接 HTML 渲染
- ✅ 任何框架 - 解析为 AST 并按需渲染
迁移(解析器导出)如果你当前是从 markstream-vue 引入解析器相关 helper,可以切换为使用独立包:
`typescript
// 之前
import { getMarkdown } from 'markstream-vue'
// 现在
import { getMarkdown } from 'stream-markdown-parser'
`
所有 API 保持不变。详见迁移指南。
- 轻量级: ~65KB 压缩后(13KB gzipped)
- 快速: 针对实时解析优化
- Tree-shakeable: 只导入你需要的部分
- 依赖很少: markdown-it-ts` + 少量 markdown-it 插件
欢迎提交 Issues 和 PRs!请阅读贡献指南。
MIT © Simon He
- markstream-vue - 功能完整的 Vue 3 Markdown 渲染器