@incremark/core
v1.0.2
Published
High-performance incremental markdown parser specifically designed for AI streaming output scenarios.
Downloads
12,681
Maintainers
Readme
@incremark/core
增量式 Markdown 解析器核心库。
🇨🇳 中文 | 🇺🇸 English
特性
- 🚀 增量解析 - 只解析新增内容,已完成的块不再重复处理
- 🔄 流式友好 - 专为 AI 流式输出场景设计
- ⌨️ 打字机效果 - 内置 BlockTransformer 实现逐字符显示
- 🎯 智能边界检测 - 准确识别 Markdown 块边界
- 📦 框架无关 - 可与任何前端框架配合使用
安装
pnpm add @incremark/core快速开始
import { createIncremarkParser } from '@incremark/core'
const parser = createIncremarkParser({ gfm: true })
// 模拟流式输入
parser.append('# Hello\n')
parser.append('\nWorld')
parser.finalize()
// 获取结果
console.log(parser.getCompletedBlocks())
console.log(parser.getAst())API
createIncremarkParser(options)
创建解析器实例。
interface ParserOptions {
gfm?: boolean // 启用 GFM
containers?: boolean // 启用 ::: 容器
extensions?: Extension[] // micromark 扩展
mdastExtensions?: Extension[] // mdast 扩展
}parser.append(chunk)
追加内容,返回增量更新。
parser.finalize()
完成解析。
parser.reset()
重置状态。
parser.render(content)
一次性渲染完整 Markdown(reset + append + finalize)。
const update = parser.render('# Hello World')
console.log(update.completed) // 已完成的块parser.getBuffer()
获取当前缓冲区内容。
parser.getCompletedBlocks()
获取已完成的块。
parser.getPendingBlocks()
获取待处理的块。
parser.getAst()
获取完整 AST。
与框架集成
对于日常使用,建议直接使用框架集成包,它们已内置增量解析和打字机效果支持:
<!-- Vue -->
<script setup>
import { ref } from 'vue'
import { IncremarkContent } from '@incremark/vue'
const content = ref('')
const isFinished = ref(false)
async function simulateStream() {
content.value = ''
isFinished.value = false
const text = '# Hello\n\nThis is **Incremark**!'
for (const chunk of text.match(/[\s\S]{1,5}/g) || []) {
content.value += chunk // 增量追加
await new Promise(r => setTimeout(r, 50))
}
isFinished.value = true
}
</script>
<template>
<IncremarkContent
:content="content"
:is-finished="isFinished"
:incremark-options="{ typewriter: { enabled: true } }"
/>
</template>// React
import { useState } from 'react'
import { IncremarkContent } from '@incremark/react'
function App() {
const [content, setContent] = useState('')
const [isFinished, setIsFinished] = useState(false)
async function simulateStream() {
setContent('')
setIsFinished(false)
const text = '# Hello\n\nThis is **Incremark**!'
const chunks = text.match(/[\s\S]{1,5}/g) || []
for (const chunk of chunks) {
setContent(prev => prev + chunk) // 增量追加
await new Promise(r => setTimeout(r, 50))
}
setIsFinished(true)
}
return (
<IncremarkContent
content={content}
isFinished={isFinished}
incremarkOptions={{ typewriter: { enabled: true } } }
/>
)
}高级用法:BlockTransformer
BlockTransformer 是打字机效果控制器,作为解析器和渲染器之间的中间层。仅在需要自定义渲染逻辑时使用。
import { createBlockTransformer, defaultPlugins } from '@incremark/core'
const transformer = createBlockTransformer({
charsPerTick: 2, // 每次显示 2 个字符
tickInterval: 50, // 每 50ms 显示一次
plugins: defaultPlugins,
onChange: (displayBlocks) => {
// 更新 UI
render(displayBlocks)
}
})
// 推送源 blocks
transformer.push(sourceBlocks)
// 跳过动画
transformer.skip()
// 重置
transformer.reset()
// 销毁
transformer.destroy()配置选项
interface TransformerOptions {
charsPerTick?: number // 每次显示的字符数(默认:2)
tickInterval?: number // 显示间隔 ms(默认:50)
plugins?: TransformerPlugin[] // 插件列表
onChange?: (blocks: DisplayBlock[]) => void
}插件系统
import {
defaultPlugins, // 默认插件(图片、分隔线立即显示)
allPlugins, // 完整插件(代码块等整体显示)
codeBlockPlugin,
mermaidPlugin,
imagePlugin,
mathPlugin,
thematicBreakPlugin,
createPlugin
} from '@incremark/core'
// 自定义插件
const myPlugin = createPlugin('my-plugin',
(node) => node.type === 'myType',
{ countChars: () => 1 }
)类型定义
interface ParsedBlock {
id: string
status: 'pending' | 'stable' | 'completed'
node: RootContent
startOffset: number
endOffset: number
rawText: string
}
interface SourceBlock {
id: string
node: RootContent
status: 'pending' | 'stable' | 'completed'
meta?: unknown
}
interface DisplayBlock {
id: string
sourceNode: RootContent
displayNode: RootContent
displayedChars: number
totalChars: number
isDisplayComplete: boolean
meta?: unknown
}License
MIT
