stream-markdown-parser
v0.0.41
Published
Pure markdown parser and renderer utilities with streaming support - framework agnostic
Maintainers
Readme
stream-markdown-parser
纯 JavaScript Markdown 解析器和渲染工具,支持流式处理 - 框架无关。
该包包含从 stream-markdown-parser 中提取的核心 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 配置等指南,请查阅上述文档。
安装
pnpm add stream-markdown-parser
# 或
npm install stream-markdown-parser
# 或
yarn add stream-markdown-parser快速 API 速览
getMarkdown(options)— 返回一个预配置的markdown-it-ts实例;支持plugin、apply、i18n等选项(内置任务列表、上下标、数学等插件)。registerMarkdownPlugin(plugin)/clearRegisteredMarkdownPlugins()— 全局注册/清除插件,在所有getMarkdown()调用中生效(适合特性开关或测试环境)。parseMarkdownToStructure(markdown, md, parseOptions)— 将 Markdown 转换为可供markstream-vue等渲染器使用的 AST。processTokens(tokens)/parseInlineTokens(children, content)— 更底层的 token → 节点工具,方便自定义管线。applyMath、applyContainers、normalizeStandaloneBackslashT、findMatchingClose等 — 用于构建自定义解析、lint 或内容清洗流程。
使用
流式解析流程
Markdown 字符串
↓ getMarkdown() → 带插件的 markdown-it-ts 实例
parseMarkdownToStructure() → AST (ParsedNode[])
↓ 交给你的渲染器(markstream-vue、自定义 UI、Worker 等)多次解析时复用同一个 md 实例可以避免重复注册插件。与 markstream-vue 一起使用时,你可以把 AST 传给 <MarkdownRender :nodes="nodes" />,或仅传入原始 content 并共享同一套解析配置。
增量 / 流式示例
处理 AI/SSE 流时,可以复用同一个 md 实例不停地对累积缓冲区解析,并把 AST 推送给 UI(例如 markstream-vue):
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 })
}在前端通过 <MarkdownRender :nodes="nodes" /> 渲染即可避免重复解析。具体串联示例见文档用法指南。
基础示例
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**.')配置数学公式选项
import { getMarkdown, setDefaultMathOptions } from 'stream-markdown-parser'
// 设置全局数学公式选项
setDefaultMathOptions({
commands: ['infty', 'perp', 'alpha'],
escapeExclamation: true
})
const md = getMarkdown()自定义国际化
import { getMarkdown } from 'stream-markdown-parser'
// 使用翻译映射
const md = getMarkdown('editor-1', {
i18n: {
'common.copy': '复制',
}
})
// 或使用翻译函数
const md = getMarkdown('editor-1', {
i18n: (key: string) => translateFunction(key)
})使用插件
import customPlugin from 'markdown-it-custom-plugin'
import { getMarkdown } from 'stream-markdown-parser'
const md = getMarkdown('editor-1', {
plugin: [
[customPlugin, { /* 选项 */ }]
]
})高级:自定义规则
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:
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 等场景统一开启功能。
API
主要函数
getMarkdown(msgId?, options?)
创建一个配置好的 markdown-it-ts 实例(与 markdown-it API 兼容)。
参数:
msgId(string, 可选): 该实例的唯一标识符。默认值:editor-${Date.now()}options(GetMarkdownOptions, 可选): 配置选项
选项:
interface GetMarkdownOptions {
// 要使用的 markdown-it / markdown-it-ts 插件数组
plugin?: Array<Plugin | [Plugin, any]>
// 修改 md 实例的函数数组
apply?: Array<(md: MarkdownIt) => void>
// 翻译函数或翻译映射
i18n?: ((key: string) => string) | Record<string, string>
}parseMarkdownToStructure(content, md?, options?)
将 Markdown 内容解析为结构化节点树。
参数:
content(string): 要解析的 Markdown 内容md(MarkdownItCore, 可选): markdown-it-ts 实例。如果未提供,则使用getMarkdown()创建options(ParseOptions, 可选): 带有钩子的解析选项
返回值: ParsedNode[] - 解析后的节点数组
processTokens(tokens)
将原始 markdown-it tokens 处理为扁平数组。
parseInlineTokens(tokens, md)
解析内联 markdown-it-ts tokens。
配置函数
setDefaultMathOptions(options)
设置全局数学公式渲染选项。
参数:
options(MathOptions): 数学公式配置选项
interface MathOptions {
commands?: readonly string[] // 要转义的 LaTeX 命令
escapeExclamation?: boolean // 转义独立的 '!' (默认: true)
}解析钩子(精细化变换)
parseMarkdownToStructure() 与 <MarkdownRender :parse-options> 可使用相同的钩子:
interface ParseOptions {
preTransformTokens?: (tokens: Token[]) => Token[]
postTransformTokens?: (tokens: Token[]) => Token[]
postTransformNodes?: (nodes: ParsedNode[]) => ParsedNode[]
}示例 —— 标记 AI “思考” 块:
const parseOptions = {
postTransformNodes(nodes) {
return nodes.map(node =>
node.type === 'html_block' && /<thinking>/.test(node.value)
? { ...node, meta: { type: 'thinking' } }
: node,
)
},
}在渲染器中读取 node.meta 即可渲染自定义 UI,而无需直接修改 Markdown 文本。
工具函数
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 组件:在解析前先把
<MyWidget>这类片段替换为占位符,渲染时再注入,避免在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 流程时,可直接使用以下导出:
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 类型都已导出:
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 - 配合
stream-markdown-parser使用 - ✅ React - 使用解析的节点进行自定义渲染
- ✅ Vanilla JS - 直接 HTML 渲染
- ✅ 任何框架 - 解析为 AST 并按需渲染
从 stream-markdown-parser 迁移
如果你正在从 stream-markdown-parser 中的 markdown 工具迁移:
import { getMarkdown } from 'stream-markdown-parser'所有 API 保持不变。详见迁移指南。
性能
- 轻量级: ~65KB 压缩后(13KB gzipped)
- 快速: 针对实时解析优化
- Tree-shakeable: 只导入你需要的部分
- 零依赖: 除了 markdown-it 及其插件
贡献
欢迎提交 Issues 和 PRs!请阅读贡献指南。
许可证
MIT © Simon He
相关项目
- stream-markdown-parser - 功能完整的 Vue 3 Markdown 渲染器
