@incremark/core 0.0.5 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/detector/index.d.ts +1 -1
- package/dist/detector/index.js +37 -14
- package/dist/detector/index.js.map +1 -1
- package/dist/{index-i_qABRHQ.d.ts → index-ChNeZ1wr.d.ts} +11 -1
- package/dist/index.d.ts +72 -10
- package/dist/index.js +341 -53
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/detector/index.ts +46 -17
- package/src/index.ts +4 -1
- package/src/parser/IncremarkParser.ts +9 -17
- package/src/transformer/BlockTransformer.ts +182 -14
- package/src/transformer/index.ts +1 -0
- package/src/transformer/types.ts +5 -3
- package/src/transformer/utils.ts +309 -30
- package/src/types/index.ts +11 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/detector/index.ts","../src/parser/IncremarkParser.ts","../src/utils/index.ts","../src/transformer/utils.ts","../src/transformer/BlockTransformer.ts","../src/transformer/plugins.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 块类型检测与边界判断\n *\n * Markdown 块级元素的识别规则\n */\n\nimport type { BlockContext, ContainerConfig, ContainerMatch } from '../types'\n\n// ============ 代码块检测 ============\n\n/**\n * 检测行是否是代码块 fence 开始\n */\nexport function detectFenceStart(line: string): { char: string; length: number } | null {\n const match = line.match(/^(\\s*)((`{3,})|(~{3,}))/)\n if (match) {\n const fence = match[2]\n const char = fence[0]\n return { char, length: fence.length }\n }\n return null\n}\n\n/**\n * 检测行是否是代码块 fence 结束\n */\nexport function detectFenceEnd(line: string, context: BlockContext): boolean {\n if (!context.inFencedCode || !context.fenceChar || !context.fenceLength) {\n return false\n }\n\n const pattern = new RegExp(`^\\\\s{0,3}${context.fenceChar}{${context.fenceLength},}\\\\s*$`)\n return pattern.test(line)\n}\n\n// ============ 行类型检测 ============\n\n/**\n * 检测是否是空行或仅包含空白字符\n */\nexport function isEmptyLine(line: string): boolean {\n return /^\\s*$/.test(line)\n}\n\n/**\n * 检测是否是标题行\n */\nexport function isHeading(line: string): boolean {\n return /^#{1,6}\\s/.test(line)\n}\n\n/**\n * 检测是否是 thematic break(水平线)\n */\nexport function isThematicBreak(line: string): boolean {\n return /^(\\*{3,}|-{3,}|_{3,})\\s*$/.test(line.trim())\n}\n\n/**\n * 检测是否是列表项开始\n */\nexport function isListItemStart(line: string): { ordered: boolean; indent: number } | null {\n // 无序列表: - * +\n const unordered = line.match(/^(\\s*)([-*+])\\s/)\n if (unordered) {\n return { ordered: false, indent: unordered[1].length }\n }\n\n // 有序列表: 1. 2) 等\n const ordered = line.match(/^(\\s*)(\\d{1,9})[.)]\\s/)\n if (ordered) {\n return { ordered: true, indent: ordered[1].length }\n }\n\n return null\n}\n\n/**\n * 检测是否是引用块开始\n */\nexport function isBlockquoteStart(line: string): boolean {\n return /^\\s{0,3}>/.test(line)\n}\n\n/**\n * 检测是否是 HTML 块\n */\nexport function isHtmlBlock(line: string): boolean {\n return (\n /^\\s{0,3}<(script|pre|style|textarea|!--|!DOCTYPE|\\?|!\\[CDATA\\[)/i.test(line) ||\n /^\\s{0,3}<\\/?[a-zA-Z][a-zA-Z0-9-]*(\\s|>|$)/.test(line)\n )\n}\n\n/**\n * 检测表格分隔行\n */\nexport function isTableDelimiter(line: string): boolean {\n return /^\\|?\\s*:?-{3,}:?\\s*(\\|\\s*:?-{3,}:?\\s*)*\\|?$/.test(line.trim())\n}\n\n// ============ 容器检测 ============\n\n/**\n * 检测容器开始或结束\n *\n * 支持格式:\n * - ::: name 开始\n * - ::: name attr 开始(带属性)\n * - ::: 结束\n * - :::::: name 开始(更长的标记,用于嵌套)\n */\nexport function detectContainer(line: string, config?: ContainerConfig): ContainerMatch | null {\n const marker = config?.marker || ':'\n const minLength = config?.minMarkerLength || 3\n\n const escapedMarker = marker.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const pattern = new RegExp(\n `^(\\\\s*)(${escapedMarker}{${minLength},})(?:\\\\s+(\\\\w[\\\\w-]*))?(?:\\\\s+(.*))?\\\\s*$`\n )\n\n const match = line.match(pattern)\n if (!match) {\n return null\n }\n\n const markerLength = match[2].length\n const name = match[3] || ''\n const isEnd = !name && !match[4]\n\n if (!isEnd && config?.allowedNames && config.allowedNames.length > 0) {\n if (!config.allowedNames.includes(name)) {\n return null\n }\n }\n\n return { name, markerLength, isEnd }\n}\n\n/**\n * 检测容器结束\n */\nexport function detectContainerEnd(\n line: string,\n context: BlockContext,\n config?: ContainerConfig\n): boolean {\n if (!context.inContainer || !context.containerMarkerLength) {\n return false\n }\n\n const result = detectContainer(line, config)\n if (!result) {\n return false\n }\n\n return result.isEnd && result.markerLength >= context.containerMarkerLength\n}\n\n// ============ 边界检测 ============\n\n/**\n * 判断两行之间是否构成块边界\n */\nexport function isBlockBoundary(\n prevLine: string,\n currentLine: string,\n context: BlockContext\n): boolean {\n if (context.inFencedCode) {\n return detectFenceEnd(currentLine, context)\n }\n\n if (isEmptyLine(prevLine) && !isEmptyLine(currentLine)) {\n return true\n }\n\n if (isHeading(currentLine) && !isEmptyLine(prevLine)) {\n return true\n }\n\n if (isThematicBreak(currentLine)) {\n return true\n }\n\n if (detectFenceStart(currentLine)) {\n return true\n }\n\n return false\n}\n\n// ============ 上下文管理 ============\n\n/**\n * 创建初始上下文\n */\nexport function createInitialContext(): BlockContext {\n return {\n inFencedCode: false,\n listDepth: 0,\n blockquoteDepth: 0,\n inContainer: false,\n containerDepth: 0\n }\n}\n\n/**\n * 更新上下文(处理一行后)\n */\nexport function updateContext(\n line: string,\n context: BlockContext,\n containerConfig?: ContainerConfig | boolean\n): BlockContext {\n const newContext = { ...context }\n\n const containerCfg =\n containerConfig === true ? {} : containerConfig === false ? undefined : containerConfig\n\n // 代码块优先级最高\n if (context.inFencedCode) {\n if (detectFenceEnd(line, context)) {\n newContext.inFencedCode = false\n newContext.fenceChar = undefined\n newContext.fenceLength = undefined\n }\n return newContext\n }\n\n const fence = detectFenceStart(line)\n if (fence) {\n newContext.inFencedCode = true\n newContext.fenceChar = fence.char\n newContext.fenceLength = fence.length\n return newContext\n }\n\n // 容器处理\n if (containerCfg !== undefined) {\n if (context.inContainer) {\n if (detectContainerEnd(line, context, containerCfg)) {\n newContext.containerDepth = context.containerDepth - 1\n if (newContext.containerDepth === 0) {\n newContext.inContainer = false\n newContext.containerMarkerLength = undefined\n newContext.containerName = undefined\n }\n return newContext\n }\n\n const nested = detectContainer(line, containerCfg)\n if (nested && !nested.isEnd) {\n newContext.containerDepth = context.containerDepth + 1\n return newContext\n }\n } else {\n const container = detectContainer(line, containerCfg)\n if (container && !container.isEnd) {\n newContext.inContainer = true\n newContext.containerMarkerLength = container.markerLength\n newContext.containerName = container.name\n newContext.containerDepth = 1\n return newContext\n }\n }\n }\n\n return newContext\n}\n\n","/**\n * 增量 Markdown 解析器\n *\n * 设计思路:\n * 1. 维护一个文本缓冲区,接收流式输入\n * 2. 识别\"稳定边界\"(如空行、标题等),将已完成的块标记为 completed\n * 3. 对于正在接收的块,每次重新解析,但只解析该块的内容\n * 4. 复杂嵌套节点(如列表、引用)作为整体处理,直到确认完成\n */\n\nimport { fromMarkdown } from 'mdast-util-from-markdown'\nimport { gfmFromMarkdown } from 'mdast-util-gfm'\nimport { gfm } from 'micromark-extension-gfm'\nimport type { Extension as MicromarkExtension } from 'micromark-util-types'\nimport type { Extension as MdastExtension } from 'mdast-util-from-markdown'\n\nimport type {\n Root,\n RootContent,\n ParsedBlock,\n IncrementalUpdate,\n ParserOptions,\n BlockStatus,\n BlockContext,\n ContainerConfig\n} from '../types'\n\nimport {\n createInitialContext,\n updateContext,\n isEmptyLine,\n detectFenceStart,\n isHeading,\n isThematicBreak,\n isBlockquoteStart,\n isListItemStart,\n detectContainer\n} from '../detector'\n\n// ============ 解析器类 ============\n\nexport class IncremarkParser {\n private buffer = ''\n private lines: string[] = []\n /** 行偏移量前缀和:lineOffsets[i] = 第i行起始位置的偏移量 */\n private lineOffsets: number[] = [0]\n private completedBlocks: ParsedBlock[] = []\n private pendingStartLine = 0\n private blockIdCounter = 0\n private context: BlockContext\n private options: ParserOptions\n /** 缓存的容器配置,避免重复计算 */\n private cachedContainerConfig: ContainerConfig | undefined | null = null\n /** 上次 append 返回的 pending blocks,用于 getAst 复用 */\n private lastPendingBlocks: ParsedBlock[] = []\n\n constructor(options: ParserOptions = {}) {\n this.options = {\n gfm: true,\n ...options\n }\n this.context = createInitialContext()\n // 初始化容器配置缓存\n this.cachedContainerConfig = this.computeContainerConfig()\n }\n\n private generateBlockId(): string {\n return `block-${++this.blockIdCounter}`\n }\n\n private computeContainerConfig(): ContainerConfig | undefined {\n const containers = this.options.containers\n if (!containers) return undefined\n return containers === true ? {} : containers\n }\n\n private getContainerConfig(): ContainerConfig | undefined {\n return this.cachedContainerConfig ?? undefined\n }\n\n private parse(text: string): Root {\n const extensions: MicromarkExtension[] = []\n const mdastExtensions: MdastExtension[] = []\n\n if (this.options.gfm) {\n extensions.push(gfm())\n mdastExtensions.push(...gfmFromMarkdown())\n }\n\n // 如果用户传入了自定义扩展,添加它们\n if (this.options.extensions) {\n extensions.push(...this.options.extensions)\n }\n if (this.options.mdastExtensions) {\n mdastExtensions.push(...this.options.mdastExtensions)\n }\n\n return fromMarkdown(text, { extensions, mdastExtensions })\n }\n\n /**\n * 增量更新 lines 和 lineOffsets\n * 只处理新增的内容,避免全量 split\n */\n private updateLines(): void {\n const prevLineCount = this.lines.length\n\n if (prevLineCount === 0) {\n // 首次输入,直接 split\n this.lines = this.buffer.split('\\n')\n this.lineOffsets = [0]\n for (let i = 0; i < this.lines.length; i++) {\n this.lineOffsets.push(this.lineOffsets[i] + this.lines[i].length + 1)\n }\n return\n }\n\n // 找到最后一个不完整的行(可能被新 chunk 续上)\n const lastLineStart = this.lineOffsets[prevLineCount - 1]\n const textFromLastLine = this.buffer.slice(lastLineStart)\n\n // 重新 split 最后一行及之后的内容\n const newLines = textFromLastLine.split('\\n')\n\n // 替换最后一行并追加新行\n this.lines.length = prevLineCount - 1\n this.lineOffsets.length = prevLineCount\n\n for (let i = 0; i < newLines.length; i++) {\n this.lines.push(newLines[i])\n const prevOffset = this.lineOffsets[this.lineOffsets.length - 1]\n this.lineOffsets.push(prevOffset + newLines[i].length + 1)\n }\n }\n\n /**\n * O(1) 获取行偏移量\n */\n private getLineOffset(lineIndex: number): number {\n return this.lineOffsets[lineIndex] ?? 0\n }\n\n /**\n * 查找稳定边界\n * 返回稳定边界行号和该行对应的上下文(用于后续更新,避免重复计算)\n */\n private findStableBoundary(): { line: number; contextAtLine: BlockContext } {\n let stableLine = -1\n let stableContext: BlockContext = this.context\n let tempContext = { ...this.context }\n const containerConfig = this.getContainerConfig()\n\n for (let i = this.pendingStartLine; i < this.lines.length; i++) {\n const line = this.lines[i]\n const wasInFencedCode = tempContext.inFencedCode\n const wasInContainer = tempContext.inContainer\n const wasContainerDepth = tempContext.containerDepth\n\n tempContext = updateContext(line, tempContext, containerConfig)\n\n if (wasInFencedCode && !tempContext.inFencedCode) {\n if (i < this.lines.length - 1) {\n stableLine = i\n stableContext = { ...tempContext }\n }\n continue\n }\n\n if (tempContext.inFencedCode) {\n continue\n }\n\n if (wasInContainer && wasContainerDepth === 1 && !tempContext.inContainer) {\n if (i < this.lines.length - 1) {\n stableLine = i\n stableContext = { ...tempContext }\n }\n continue\n }\n\n if (tempContext.inContainer) {\n continue\n }\n\n const stablePoint = this.checkStability(i, containerConfig)\n if (stablePoint >= 0) {\n stableLine = stablePoint\n stableContext = { ...tempContext }\n }\n }\n\n return { line: stableLine, contextAtLine: stableContext }\n }\n\n private checkStability(\n lineIndex: number,\n containerConfig: ContainerConfig | undefined\n ): number {\n // 第一行永远不稳定\n if (lineIndex === 0) {\n return -1\n }\n\n const line = this.lines[lineIndex]\n const prevLine = this.lines[lineIndex - 1]\n\n // 前一行是独立块(标题、分割线),该块已完成\n if (isHeading(prevLine) || isThematicBreak(prevLine)) {\n return lineIndex - 1\n }\n\n // 最后一行不稳定(可能还有更多内容)\n if (lineIndex >= this.lines.length - 1) {\n return -1\n }\n\n // 前一行非空时,如果当前行是新块开始,则前一块已完成\n if (!isEmptyLine(prevLine)) {\n // 新标题开始\n if (isHeading(line)) {\n return lineIndex - 1\n }\n\n // 新代码块开始\n if (detectFenceStart(line)) {\n return lineIndex - 1\n }\n\n // 新引用块开始(排除连续引用)\n if (isBlockquoteStart(line) && !isBlockquoteStart(prevLine)) {\n return lineIndex - 1\n }\n\n // 新列表开始(排除连续列表项)\n if (isListItemStart(line) && !isListItemStart(prevLine)) {\n return lineIndex - 1\n }\n\n // 新容器开始\n if (containerConfig !== undefined) {\n const container = detectContainer(line, containerConfig)\n if (container && !container.isEnd) {\n const prevContainer = detectContainer(prevLine, containerConfig)\n if (!prevContainer || prevContainer.isEnd) {\n return lineIndex - 1\n }\n }\n }\n }\n\n // 空行标志段落结束\n if (isEmptyLine(line) && !isEmptyLine(prevLine)) {\n return lineIndex\n }\n\n return -1\n }\n\n private nodesToBlocks(\n nodes: RootContent[],\n startOffset: number,\n rawText: string,\n status: BlockStatus\n ): ParsedBlock[] {\n const blocks: ParsedBlock[] = []\n let currentOffset = startOffset\n\n for (const node of nodes) {\n const nodeStart = node.position?.start?.offset ?? currentOffset\n const nodeEnd = node.position?.end?.offset ?? currentOffset + 1\n const nodeText = rawText.substring(nodeStart - startOffset, nodeEnd - startOffset)\n\n blocks.push({\n id: this.generateBlockId(),\n status,\n node,\n startOffset: nodeStart,\n endOffset: nodeEnd,\n rawText: nodeText\n })\n\n currentOffset = nodeEnd\n }\n\n return blocks\n }\n\n /**\n * 追加新的 chunk 并返回增量更新\n */\n append(chunk: string): IncrementalUpdate {\n this.buffer += chunk\n this.updateLines()\n\n const { line: stableBoundary, contextAtLine } = this.findStableBoundary()\n\n const update: IncrementalUpdate = {\n completed: [],\n updated: [],\n pending: [],\n ast: { type: 'root', children: [] }\n }\n\n if (stableBoundary >= this.pendingStartLine && stableBoundary >= 0) {\n const stableText = this.lines.slice(this.pendingStartLine, stableBoundary + 1).join('\\n')\n const stableOffset = this.getLineOffset(this.pendingStartLine)\n\n const ast = this.parse(stableText)\n const newBlocks = this.nodesToBlocks(ast.children, stableOffset, stableText, 'completed')\n\n this.completedBlocks.push(...newBlocks)\n update.completed = newBlocks\n\n // 直接使用 findStableBoundary 计算好的上下文,避免重复遍历\n this.context = contextAtLine\n this.pendingStartLine = stableBoundary + 1\n }\n\n if (this.pendingStartLine < this.lines.length) {\n const pendingText = this.lines.slice(this.pendingStartLine).join('\\n')\n\n if (pendingText.trim()) {\n const pendingOffset = this.getLineOffset(this.pendingStartLine)\n const ast = this.parse(pendingText)\n\n update.pending = this.nodesToBlocks(ast.children, pendingOffset, pendingText, 'pending')\n }\n }\n\n // 缓存 pending blocks 供 getAst 使用\n this.lastPendingBlocks = update.pending\n\n update.ast = {\n type: 'root',\n children: [...this.completedBlocks.map((b) => b.node), ...update.pending.map((b) => b.node)]\n }\n\n // 触发状态变化回调\n this.emitChange(update.pending)\n\n return update\n }\n\n /**\n * 触发状态变化回调\n */\n private emitChange(pendingBlocks: ParsedBlock[] = []): void {\n if (this.options.onChange) {\n this.options.onChange({\n completedBlocks: this.completedBlocks,\n pendingBlocks,\n markdown: this.buffer,\n ast: {\n type: 'root',\n children: [\n ...this.completedBlocks.map((b) => b.node),\n ...pendingBlocks.map((b) => b.node)\n ]\n }\n })\n }\n }\n\n /**\n * 标记解析完成,处理剩余内容\n * 也可用于强制中断时(如用户点击停止),将 pending 内容标记为 completed\n */\n finalize(): IncrementalUpdate {\n const update: IncrementalUpdate = {\n completed: [],\n updated: [],\n pending: [],\n ast: { type: 'root', children: [] }\n }\n\n if (this.pendingStartLine < this.lines.length) {\n const remainingText = this.lines.slice(this.pendingStartLine).join('\\n')\n\n if (remainingText.trim()) {\n const remainingOffset = this.getLineOffset(this.pendingStartLine)\n const ast = this.parse(remainingText)\n\n const finalBlocks = this.nodesToBlocks(\n ast.children,\n remainingOffset,\n remainingText,\n 'completed'\n )\n\n this.completedBlocks.push(...finalBlocks)\n update.completed = finalBlocks\n }\n }\n\n // 清空 pending 缓存\n this.lastPendingBlocks = []\n this.pendingStartLine = this.lines.length\n\n update.ast = {\n type: 'root',\n children: this.completedBlocks.map((b) => b.node)\n }\n\n // 触发状态变化回调\n this.emitChange([])\n\n return update\n }\n\n /**\n * 强制中断解析,将所有待处理内容标记为完成\n * 语义上等同于 finalize(),但名称更清晰\n */\n abort(): IncrementalUpdate {\n return this.finalize()\n }\n\n /**\n * 获取当前完整的 AST\n * 复用上次 append 的 pending 结果,避免重复解析\n */\n getAst(): Root {\n return {\n type: 'root',\n children: [\n ...this.completedBlocks.map((b) => b.node),\n ...this.lastPendingBlocks.map((b) => b.node)\n ]\n }\n }\n\n /**\n * 获取所有已完成的块\n */\n getCompletedBlocks(): ParsedBlock[] {\n return [...this.completedBlocks]\n }\n\n /**\n * 获取当前缓冲区内容\n */\n getBuffer(): string {\n return this.buffer\n }\n\n /**\n * 设置状态变化回调(用于 DevTools 等)\n */\n setOnChange(callback: ((state: import('../types').ParserState) => void) | undefined): void {\n this.options.onChange = callback\n }\n\n /**\n * 重置解析器状态\n */\n reset(): void {\n this.buffer = ''\n this.lines = []\n this.lineOffsets = [0]\n this.completedBlocks = []\n this.pendingStartLine = 0\n this.blockIdCounter = 0\n this.context = createInitialContext()\n this.lastPendingBlocks = []\n\n // 触发状态变化回调\n this.emitChange([])\n }\n\n /**\n * 一次性渲染完整 Markdown(reset + append + finalize)\n * @param content 完整的 Markdown 内容\n * @returns 解析结果\n */\n render(content: string): IncrementalUpdate {\n this.reset()\n this.append(content)\n return this.finalize()\n }\n}\n\n/**\n * 创建 Incremark 解析器实例\n */\nexport function createIncremarkParser(options?: ParserOptions): IncremarkParser {\n return new IncremarkParser(options)\n}\n","/**\n * 工具函数\n */\n\n/**\n * 生成唯一 ID\n */\nlet idCounter = 0\nexport function generateId(prefix = 'block'): string {\n return `${prefix}-${++idCounter}`\n}\n\n/**\n * 重置 ID 计数器(用于测试)\n */\nexport function resetIdCounter(): void {\n idCounter = 0\n}\n\n/**\n * 计算行的偏移量\n */\nexport function calculateLineOffset(lines: string[], lineIndex: number): number {\n let offset = 0\n for (let i = 0; i < lineIndex && i < lines.length; i++) {\n offset += lines[i].length + 1 // +1 for newline\n }\n return offset\n}\n\n/**\n * 将文本按行分割\n */\nexport function splitLines(text: string): string[] {\n return text.split('\\n')\n}\n\n/**\n * 合并行为文本\n */\nexport function joinLines(lines: string[], start: number, end: number): string {\n return lines.slice(start, end + 1).join('\\n')\n}\n\n","import type { RootContent } from 'mdast'\n\n/**\n * 计算 AST 节点的总字符数\n */\nexport function countChars(node: RootContent): number {\n let count = 0\n\n function traverse(n: any): void {\n // 文本类节点\n if (n.value && typeof n.value === 'string') {\n count += n.value.length\n return\n }\n\n // 容器节点,递归处理子节点\n if (n.children && Array.isArray(n.children)) {\n for (const child of n.children) {\n traverse(child)\n }\n }\n }\n\n traverse(node)\n return count\n}\n\n/**\n * 截断 AST 节点,只保留前 maxChars 个字符\n * \n * @param node 原始节点\n * @param maxChars 最大字符数\n * @returns 截断后的节点,如果 maxChars <= 0 返回 null\n */\nexport function sliceAst(node: RootContent, maxChars: number): RootContent | null {\n if (maxChars <= 0) return null\n\n let remaining = maxChars\n\n function process(n: any): any {\n if (remaining <= 0) return null\n\n // 文本类节点:截断 value\n if (n.value && typeof n.value === 'string') {\n const take = Math.min(n.value.length, remaining)\n remaining -= take\n if (take === 0) return null\n return { ...n, value: n.value.slice(0, take) }\n }\n\n // 容器节点:递归处理 children\n if (n.children && Array.isArray(n.children)) {\n const newChildren: any[] = []\n for (const child of n.children) {\n if (remaining <= 0) break\n const processed = process(child)\n if (processed) {\n newChildren.push(processed)\n }\n }\n // 如果没有 children 了,根据节点类型决定是否保留\n if (newChildren.length === 0) {\n // 对于某些容器节点,即使没有内容也应该保留结构\n // 例如 list 节点如果没有 children 就不应该渲染\n return null\n }\n return { ...n, children: newChildren }\n }\n\n // 其他节点(如 thematicBreak, image):整体处理\n // 算作 1 个字符的消耗\n remaining -= 1\n return { ...n }\n }\n\n return process(node)\n}\n\n/**\n * 深拷贝 AST 节点\n */\nexport function cloneNode<T extends RootContent>(node: T): T {\n return JSON.parse(JSON.stringify(node))\n}\n\n","import type { RootContent } from 'mdast'\nimport type {\n SourceBlock,\n DisplayBlock,\n TransformerOptions,\n TransformerState,\n TransformerPlugin,\n AnimationEffect\n} from './types'\nimport { countChars as defaultCountChars, sliceAst as defaultSliceAst } from './utils'\n\n/**\n * Block Transformer\n *\n * 用于控制 blocks 的逐步显示(打字机效果)\n * 作为解析器和渲染器之间的中间层\n *\n * 特性:\n * - 使用 requestAnimationFrame 实现流畅动画\n * - 支持随机步长,模拟真实打字效果\n * - 支持 typing 动画效果\n * - 页面不可见时自动暂停,节省资源\n * - 插件系统支持自定义节点处理\n *\n * @example\n * ```typescript\n * const transformer = new BlockTransformer({\n * charsPerTick: [1, 3], // 随机 1-3 个字符\n * tickInterval: 30,\n * effect: 'typing',\n * onChange: (displayBlocks) => {\n * // 更新 UI\n * }\n * })\n *\n * // 推入新 blocks\n * transformer.push(blocks)\n *\n * // 获取当前显示状态\n * const displayBlocks = transformer.getDisplayBlocks()\n * ```\n */\nexport class BlockTransformer<T = unknown> {\n private state: TransformerState<T>\n private options: {\n charsPerTick: number | [number, number]\n tickInterval: number\n effect: AnimationEffect\n plugins: TransformerPlugin[]\n onChange: (displayBlocks: DisplayBlock<T>[]) => void\n pauseOnHidden: boolean\n }\n private rafId: number | null = null\n private lastTickTime = 0\n private isRunning = false\n private isPaused = false\n private visibilityHandler: (() => void) | null = null\n\n constructor(options: TransformerOptions = {}) {\n this.options = {\n charsPerTick: options.charsPerTick ?? 1,\n tickInterval: options.tickInterval ?? 20,\n effect: options.effect ?? 'none',\n plugins: options.plugins ?? [],\n onChange: options.onChange ?? (() => {}),\n pauseOnHidden: options.pauseOnHidden ?? true\n }\n\n this.state = {\n completedBlocks: [],\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n\n // 设置页面可见性监听\n if (this.options.pauseOnHidden && typeof document !== 'undefined') {\n this.setupVisibilityHandler()\n }\n }\n\n /**\n * 推入新的 blocks\n * 会自动过滤已存在的 blocks\n */\n push(blocks: SourceBlock<T>[]): void {\n const existingIds = this.getAllBlockIds()\n\n // 找出新增的 blocks\n const newBlocks = blocks.filter((b) => !existingIds.has(b.id))\n\n if (newBlocks.length > 0) {\n this.state.pendingBlocks.push(...newBlocks)\n this.startIfNeeded()\n }\n\n // 如果当前正在显示的 block 内容更新了(pending block 变化)\n if (this.state.currentBlock) {\n const updated = blocks.find((b) => b.id === this.state.currentBlock!.id)\n if (updated && updated.node !== this.state.currentBlock.node) {\n // 内容增加了,更新引用\n this.state.currentBlock = updated\n // 如果之前暂停了(因为到达末尾),重新开始\n if (!this.rafId && !this.isPaused) {\n const total = this.countChars(updated.node)\n if (this.state.currentProgress < total) {\n this.startIfNeeded()\n }\n }\n }\n }\n }\n\n /**\n * 更新指定 block(用于 pending block 内容增加时)\n */\n update(block: SourceBlock<T>): void {\n if (this.state.currentBlock?.id === block.id) {\n const oldTotal = this.countChars(this.state.currentBlock.node)\n const newTotal = this.countChars(block.node)\n\n this.state.currentBlock = block\n\n // 如果内容增加了且之前暂停了,继续\n if (newTotal > oldTotal && !this.rafId && !this.isPaused && this.state.currentProgress >= oldTotal) {\n this.startIfNeeded()\n }\n }\n }\n\n /**\n * 跳过所有动画,直接显示全部内容\n */\n skip(): void {\n this.stop()\n\n const allBlocks = [\n ...this.state.completedBlocks,\n ...(this.state.currentBlock ? [this.state.currentBlock] : []),\n ...this.state.pendingBlocks\n ]\n\n this.state = {\n completedBlocks: allBlocks,\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n\n this.emit()\n }\n\n /**\n * 重置状态\n */\n reset(): void {\n this.stop()\n this.state = {\n completedBlocks: [],\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n this.emit()\n }\n\n /**\n * 暂停动画\n */\n pause(): void {\n this.isPaused = true\n this.cancelRaf()\n }\n\n /**\n * 恢复动画\n */\n resume(): void {\n if (this.isPaused) {\n this.isPaused = false\n this.startIfNeeded()\n }\n }\n\n /**\n * 获取用于渲染的 display blocks\n */\n getDisplayBlocks(): DisplayBlock<T>[] {\n const result: DisplayBlock<T>[] = []\n\n // 已完成的 blocks\n for (const block of this.state.completedBlocks) {\n result.push({\n ...block,\n displayNode: block.node,\n progress: 1,\n isDisplayComplete: true\n })\n }\n\n // 当前正在显示的 block\n if (this.state.currentBlock) {\n const total = this.countChars(this.state.currentBlock.node)\n const displayNode = this.sliceNode(this.state.currentBlock.node, this.state.currentProgress)\n\n result.push({\n ...this.state.currentBlock,\n displayNode: displayNode || { type: 'paragraph', children: [] },\n progress: total > 0 ? this.state.currentProgress / total : 1,\n isDisplayComplete: false\n })\n }\n\n return result\n }\n\n /**\n * 是否正在处理中\n */\n isProcessing(): boolean {\n return this.isRunning || this.state.currentBlock !== null || this.state.pendingBlocks.length > 0\n }\n\n /**\n * 是否已暂停\n */\n isPausedState(): boolean {\n return this.isPaused\n }\n\n /**\n * 获取内部状态(用于调试)\n */\n getState(): Readonly<TransformerState<T>> {\n return { ...this.state }\n }\n\n /**\n * 动态更新配置\n */\n setOptions(options: Partial<Pick<TransformerOptions, 'charsPerTick' | 'tickInterval' | 'effect' | 'pauseOnHidden'>>): void {\n if (options.charsPerTick !== undefined) {\n this.options.charsPerTick = options.charsPerTick\n }\n if (options.tickInterval !== undefined) {\n this.options.tickInterval = options.tickInterval\n }\n if (options.effect !== undefined) {\n this.options.effect = options.effect\n }\n if (options.pauseOnHidden !== undefined) {\n this.options.pauseOnHidden = options.pauseOnHidden\n if (options.pauseOnHidden && typeof document !== 'undefined') {\n this.setupVisibilityHandler()\n } else {\n this.removeVisibilityHandler()\n }\n }\n }\n\n /**\n * 获取当前配置\n */\n getOptions(): { \n charsPerTick: number | [number, number]\n tickInterval: number\n effect: AnimationEffect\n } {\n return {\n charsPerTick: this.options.charsPerTick,\n tickInterval: this.options.tickInterval,\n effect: this.options.effect\n }\n }\n\n /**\n * 获取当前动画效果\n */\n getEffect(): AnimationEffect {\n return this.options.effect\n }\n\n /**\n * 销毁,清理资源\n */\n destroy(): void {\n this.stop()\n this.removeVisibilityHandler()\n }\n\n // ============ 私有方法 ============\n\n private getAllBlockIds(): Set<string> {\n return new Set([\n ...this.state.completedBlocks.map((b) => b.id),\n this.state.currentBlock?.id,\n ...this.state.pendingBlocks.map((b) => b.id)\n ].filter((id): id is string => id !== undefined))\n }\n\n private setupVisibilityHandler(): void {\n if (this.visibilityHandler) return\n\n this.visibilityHandler = () => {\n if (document.hidden) {\n this.pause()\n } else {\n this.resume()\n }\n }\n\n document.addEventListener('visibilitychange', this.visibilityHandler)\n }\n\n private removeVisibilityHandler(): void {\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler)\n this.visibilityHandler = null\n }\n }\n\n private startIfNeeded(): void {\n if (this.rafId || this.isPaused) return\n\n if (!this.state.currentBlock && this.state.pendingBlocks.length > 0) {\n this.state.currentBlock = this.state.pendingBlocks.shift()!\n this.state.currentProgress = 0\n }\n\n if (this.state.currentBlock) {\n this.isRunning = true\n this.lastTickTime = 0\n this.scheduleNextFrame()\n }\n }\n\n private scheduleNextFrame(): void {\n this.rafId = requestAnimationFrame((time) => this.animationFrame(time))\n }\n\n private animationFrame(time: number): void {\n this.rafId = null\n\n // 计算是否应该执行 tick\n if (this.lastTickTime === 0) {\n this.lastTickTime = time\n }\n\n const elapsed = time - this.lastTickTime\n\n if (elapsed >= this.options.tickInterval) {\n this.lastTickTime = time\n this.tick()\n }\n\n // 如果还在运行,继续调度\n if (this.isRunning && !this.isPaused) {\n this.scheduleNextFrame()\n }\n }\n\n private tick(): void {\n const block = this.state.currentBlock\n if (!block) {\n this.processNext()\n return\n }\n\n const total = this.countChars(block.node)\n const step = this.getStep()\n \n this.state.currentProgress = Math.min(this.state.currentProgress + step, total)\n\n this.emit()\n\n if (this.state.currentProgress >= total) {\n // 当前 block 完成\n this.notifyComplete(block.node)\n this.state.completedBlocks.push(block)\n this.state.currentBlock = null\n this.state.currentProgress = 0\n this.processNext()\n }\n }\n\n private getStep(): number {\n const { charsPerTick } = this.options\n if (typeof charsPerTick === 'number') {\n return charsPerTick\n }\n // 随机步长\n const [min, max] = charsPerTick\n return Math.floor(Math.random() * (max - min + 1)) + min\n }\n\n private processNext(): void {\n if (this.state.pendingBlocks.length > 0) {\n this.state.currentBlock = this.state.pendingBlocks.shift()!\n this.state.currentProgress = 0\n this.emit()\n // 继续运行(rAF 已经在调度中)\n } else {\n this.isRunning = false\n this.cancelRaf()\n this.emit()\n }\n }\n\n private cancelRaf(): void {\n if (this.rafId) {\n cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n }\n\n private stop(): void {\n this.cancelRaf()\n this.isRunning = false\n this.isPaused = false\n }\n\n private emit(): void {\n this.options.onChange(this.getDisplayBlocks())\n }\n\n // ============ 插件调用 ============\n\n private countChars(node: RootContent): number {\n // 先找匹配的插件\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.countChars) {\n const result = plugin.countChars(node)\n if (result !== undefined) return result\n }\n }\n // 默认计算\n return defaultCountChars(node)\n }\n\n private sliceNode(node: RootContent, chars: number): RootContent | null {\n // 先找匹配的插件\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.sliceNode) {\n const total = this.countChars(node)\n const result = plugin.sliceNode(node, chars, total)\n if (result !== null) return result\n }\n }\n // 默认截断\n return defaultSliceAst(node, chars)\n }\n\n private notifyComplete(node: RootContent): void {\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.onComplete) {\n plugin.onComplete(node)\n }\n }\n }\n}\n\n/**\n * 创建 BlockTransformer 实例的工厂函数\n */\nexport function createBlockTransformer<T = unknown>(\n options?: TransformerOptions\n): BlockTransformer<T> {\n return new BlockTransformer<T>(options)\n}\n\n\n\n","import type { RootContent, Code } from 'mdast'\nimport type { TransformerPlugin } from './types'\n\n/**\n * 代码块插件:整体出现,不逐字符显示\n * \n * 注意:默认不启用,代码块默认参与打字机效果\n * 如需整体显示代码块,可手动添加此插件\n */\nexport const codeBlockPlugin: TransformerPlugin = {\n name: 'code-block',\n match: (node: RootContent) => node.type === 'code',\n countChars: () => 1, // 算作 1 个字符,整体出现\n sliceNode: (node, displayedChars, totalChars) => {\n // 要么全部显示,要么不显示\n return displayedChars >= totalChars ? node : null\n }\n}\n\n/**\n * Mermaid 图表插件:整体出现\n * \n * 注意:默认不启用,mermaid 默认参与打字机效果\n * 如需整体显示 mermaid,可手动添加此插件\n */\nexport const mermaidPlugin: TransformerPlugin = {\n name: 'mermaid',\n match: (node: RootContent) => {\n if (node.type !== 'code') return false\n const codeNode = node as Code\n return codeNode.lang === 'mermaid'\n },\n countChars: () => 1,\n sliceNode: (node, displayedChars) => (displayedChars > 0 ? node : null)\n}\n\n/**\n * 图片插件:立即显示(不参与打字机效果)\n * 图片没有文本内容,应立即显示\n */\nexport const imagePlugin: TransformerPlugin = {\n name: 'image',\n match: (node: RootContent) => node.type === 'image',\n countChars: () => 0 // 0 字符,立即显示\n}\n\n/**\n * 数学公式插件:整体出现\n * \n * 注意:默认不启用,数学公式默认参与打字机效果\n * 如需整体显示公式,可手动添加此插件\n */\nexport const mathPlugin: TransformerPlugin = {\n name: 'math',\n match: (node: RootContent) => {\n const type = node.type as string\n return type === 'math' || type === 'inlineMath'\n },\n countChars: () => 1,\n sliceNode: (node, displayedChars) => (displayedChars > 0 ? node : null)\n}\n\n/**\n * 分割线插件:立即显示\n * 分隔线没有文本内容,应立即显示\n */\nexport const thematicBreakPlugin: TransformerPlugin = {\n name: 'thematic-break',\n match: (node: RootContent) => node.type === 'thematicBreak',\n countChars: () => 0\n}\n\n/**\n * 默认插件集合\n * \n * 只包含确实需要特殊处理的节点:\n * - 图片:无文本内容,立即显示\n * - 分隔线:无文本内容,立即显示\n * \n * 代码块、mermaid、数学公式默认参与打字机效果\n * 如需整体显示,可手动添加对应插件\n */\nexport const defaultPlugins: TransformerPlugin[] = [\n imagePlugin,\n thematicBreakPlugin\n]\n\n/**\n * 完整插件集合(所有特殊节点整体显示)\n * 包含代码块、mermaid、数学公式等的整体显示\n */\nexport const allPlugins: TransformerPlugin[] = [\n mermaidPlugin, // mermaid 优先于普通 code block\n codeBlockPlugin,\n imagePlugin,\n mathPlugin,\n thematicBreakPlugin\n]\n\n/**\n * 创建自定义插件的辅助函数\n */\nexport function createPlugin(\n name: string,\n matcher: (node: RootContent) => boolean,\n options: Partial<Omit<TransformerPlugin, 'name' | 'match'>> = {}\n): TransformerPlugin {\n return {\n name,\n match: matcher,\n ...options\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/detector/index.ts","../src/parser/IncremarkParser.ts","../src/utils/index.ts","../src/transformer/utils.ts","../src/transformer/BlockTransformer.ts","../src/transformer/plugins.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 块类型检测与边界判断\n *\n * Markdown 块级元素的识别规则\n */\n\nimport type { BlockContext, ContainerConfig, ContainerMatch } from '../types'\n\n// ============ 预编译正则表达式(性能优化) ============\n\nconst RE_FENCE_START = /^(\\s*)((`{3,})|(~{3,}))/\nconst RE_EMPTY_LINE = /^\\s*$/\nconst RE_HEADING = /^#{1,6}\\s/\nconst RE_THEMATIC_BREAK = /^(\\*{3,}|-{3,}|_{3,})\\s*$/\nconst RE_UNORDERED_LIST = /^(\\s*)([-*+])\\s/\nconst RE_ORDERED_LIST = /^(\\s*)(\\d{1,9})[.)]\\s/\nconst RE_BLOCKQUOTE = /^\\s{0,3}>/\nconst RE_HTML_BLOCK_1 = /^\\s{0,3}<(script|pre|style|textarea|!--|!DOCTYPE|\\?|!\\[CDATA\\[)/i\nconst RE_HTML_BLOCK_2 = /^\\s{0,3}<\\/?[a-zA-Z][a-zA-Z0-9-]*(\\s|>|$)/\nconst RE_TABLE_DELIMITER = /^\\|?\\s*:?-{3,}:?\\s*(\\|\\s*:?-{3,}:?\\s*)*\\|?$/\nconst RE_ESCAPE_SPECIAL = /[.*+?^${}()|[\\]\\\\]/g\n\n/** fence 结束模式缓存 */\nconst fenceEndPatternCache = new Map<string, RegExp>()\n\n/** 容器模式缓存 */\nconst containerPatternCache = new Map<string, RegExp>()\n\n// ============ 代码块检测 ============\n\n/**\n * 检测行是否是代码块 fence 开始\n */\nexport function detectFenceStart(line: string): { char: string; length: number } | null {\n const match = line.match(RE_FENCE_START)\n if (match) {\n const fence = match[2]\n const char = fence[0]\n return { char, length: fence.length }\n }\n return null\n}\n\n/**\n * 检测行是否是代码块 fence 结束\n */\nexport function detectFenceEnd(line: string, context: BlockContext): boolean {\n if (!context.inFencedCode || !context.fenceChar || !context.fenceLength) {\n return false\n }\n\n // 使用缓存的正则表达式\n const cacheKey = `${context.fenceChar}-${context.fenceLength}`\n let pattern = fenceEndPatternCache.get(cacheKey)\n if (!pattern) {\n pattern = new RegExp(`^\\\\s{0,3}${context.fenceChar}{${context.fenceLength},}\\\\s*$`)\n fenceEndPatternCache.set(cacheKey, pattern)\n }\n return pattern.test(line)\n}\n\n// ============ 行类型检测 ============\n\n/**\n * 检测是否是空行或仅包含空白字符\n */\nexport function isEmptyLine(line: string): boolean {\n return RE_EMPTY_LINE.test(line)\n}\n\n/**\n * 检测是否是标题行\n */\nexport function isHeading(line: string): boolean {\n return RE_HEADING.test(line)\n}\n\n/**\n * 检测是否是 thematic break(水平线)\n */\nexport function isThematicBreak(line: string): boolean {\n return RE_THEMATIC_BREAK.test(line.trim())\n}\n\n/**\n * 检测是否是列表项开始\n */\nexport function isListItemStart(line: string): { ordered: boolean; indent: number } | null {\n // 无序列表: - * +\n const unordered = line.match(RE_UNORDERED_LIST)\n if (unordered) {\n return { ordered: false, indent: unordered[1].length }\n }\n\n // 有序列表: 1. 2) 等\n const ordered = line.match(RE_ORDERED_LIST)\n if (ordered) {\n return { ordered: true, indent: ordered[1].length }\n }\n\n return null\n}\n\n/**\n * 检测是否是引用块开始\n */\nexport function isBlockquoteStart(line: string): boolean {\n return RE_BLOCKQUOTE.test(line)\n}\n\n/**\n * 检测是否是 HTML 块\n */\nexport function isHtmlBlock(line: string): boolean {\n return RE_HTML_BLOCK_1.test(line) || RE_HTML_BLOCK_2.test(line)\n}\n\n/**\n * 检测表格分隔行\n */\nexport function isTableDelimiter(line: string): boolean {\n return RE_TABLE_DELIMITER.test(line.trim())\n}\n\n// ============ 容器检测 ============\n\n/**\n * 检测容器开始或结束\n *\n * 支持格式:\n * - ::: name 开始\n * - ::: name attr 开始(带属性)\n * - ::: 结束\n * - :::::: name 开始(更长的标记,用于嵌套)\n */\nexport function detectContainer(line: string, config?: ContainerConfig): ContainerMatch | null {\n const marker = config?.marker || ':'\n const minLength = config?.minMarkerLength || 3\n\n // 使用缓存的正则表达式\n const cacheKey = `${marker}-${minLength}`\n let pattern = containerPatternCache.get(cacheKey)\n if (!pattern) {\n const escapedMarker = marker.replace(RE_ESCAPE_SPECIAL, '\\\\$&')\n pattern = new RegExp(\n `^(\\\\s*)(${escapedMarker}{${minLength},})(?:\\\\s+(\\\\w[\\\\w-]*))?(?:\\\\s+(.*))?\\\\s*$`\n )\n containerPatternCache.set(cacheKey, pattern)\n }\n\n const match = line.match(pattern)\n if (!match) {\n return null\n }\n\n const markerLength = match[2].length\n const name = match[3] || ''\n const isEnd = !name && !match[4]\n\n if (!isEnd && config?.allowedNames && config.allowedNames.length > 0) {\n if (!config.allowedNames.includes(name)) {\n return null\n }\n }\n\n return { name, markerLength, isEnd }\n}\n\n/**\n * 检测容器结束\n */\nexport function detectContainerEnd(\n line: string,\n context: BlockContext,\n config?: ContainerConfig\n): boolean {\n if (!context.inContainer || !context.containerMarkerLength) {\n return false\n }\n\n const result = detectContainer(line, config)\n if (!result) {\n return false\n }\n\n return result.isEnd && result.markerLength >= context.containerMarkerLength\n}\n\n// ============ 边界检测 ============\n\n/**\n * 判断两行之间是否构成块边界\n */\nexport function isBlockBoundary(\n prevLine: string,\n currentLine: string,\n context: BlockContext\n): boolean {\n if (context.inFencedCode) {\n return detectFenceEnd(currentLine, context)\n }\n\n if (isEmptyLine(prevLine) && !isEmptyLine(currentLine)) {\n return true\n }\n\n if (isHeading(currentLine) && !isEmptyLine(prevLine)) {\n return true\n }\n\n if (isThematicBreak(currentLine)) {\n return true\n }\n\n if (detectFenceStart(currentLine)) {\n return true\n }\n\n return false\n}\n\n// ============ 上下文管理 ============\n\n/**\n * 创建初始上下文\n */\nexport function createInitialContext(): BlockContext {\n return {\n inFencedCode: false,\n listDepth: 0,\n blockquoteDepth: 0,\n inContainer: false,\n containerDepth: 0\n }\n}\n\n/**\n * 更新上下文(处理一行后)\n */\nexport function updateContext(\n line: string,\n context: BlockContext,\n containerConfig?: ContainerConfig | boolean\n): BlockContext {\n const newContext = { ...context }\n\n const containerCfg =\n containerConfig === true ? {} : containerConfig === false ? undefined : containerConfig\n\n // 代码块优先级最高\n if (context.inFencedCode) {\n if (detectFenceEnd(line, context)) {\n newContext.inFencedCode = false\n newContext.fenceChar = undefined\n newContext.fenceLength = undefined\n }\n return newContext\n }\n\n const fence = detectFenceStart(line)\n if (fence) {\n newContext.inFencedCode = true\n newContext.fenceChar = fence.char\n newContext.fenceLength = fence.length\n return newContext\n }\n\n // 容器处理\n if (containerCfg !== undefined) {\n if (context.inContainer) {\n if (detectContainerEnd(line, context, containerCfg)) {\n newContext.containerDepth = context.containerDepth - 1\n if (newContext.containerDepth === 0) {\n newContext.inContainer = false\n newContext.containerMarkerLength = undefined\n newContext.containerName = undefined\n }\n return newContext\n }\n\n const nested = detectContainer(line, containerCfg)\n if (nested && !nested.isEnd) {\n newContext.containerDepth = context.containerDepth + 1\n return newContext\n }\n } else {\n const container = detectContainer(line, containerCfg)\n if (container && !container.isEnd) {\n newContext.inContainer = true\n newContext.containerMarkerLength = container.markerLength\n newContext.containerName = container.name\n newContext.containerDepth = 1\n return newContext\n }\n }\n }\n\n return newContext\n}\n\n","/**\n * 增量 Markdown 解析器\n *\n * 设计思路:\n * 1. 维护一个文本缓冲区,接收流式输入\n * 2. 识别\"稳定边界\"(如空行、标题等),将已完成的块标记为 completed\n * 3. 对于正在接收的块,每次重新解析,但只解析该块的内容\n * 4. 复杂嵌套节点(如列表、引用)作为整体处理,直到确认完成\n */\n\nimport { fromMarkdown } from 'mdast-util-from-markdown'\nimport { gfmFromMarkdown } from 'mdast-util-gfm'\nimport { gfm } from 'micromark-extension-gfm'\nimport type { Extension as MicromarkExtension } from 'micromark-util-types'\nimport type { Extension as MdastExtension } from 'mdast-util-from-markdown'\n\nimport type {\n Root,\n RootContent,\n ParsedBlock,\n IncrementalUpdate,\n ParserOptions,\n BlockStatus,\n BlockContext,\n ContainerConfig\n} from '../types'\n\nimport {\n createInitialContext,\n updateContext,\n isEmptyLine,\n detectFenceStart,\n isHeading,\n isThematicBreak,\n isBlockquoteStart,\n isListItemStart,\n detectContainer\n} from '../detector'\n\n// ============ 解析器类 ============\n\nexport class IncremarkParser {\n private buffer = ''\n private lines: string[] = []\n /** 行偏移量前缀和:lineOffsets[i] = 第i行起始位置的偏移量 */\n private lineOffsets: number[] = [0]\n private completedBlocks: ParsedBlock[] = []\n private pendingStartLine = 0\n private blockIdCounter = 0\n private context: BlockContext\n private options: ParserOptions\n /** 缓存的容器配置,避免重复计算 */\n private readonly containerConfig: ContainerConfig | undefined\n /** 上次 append 返回的 pending blocks,用于 getAst 复用 */\n private lastPendingBlocks: ParsedBlock[] = []\n\n constructor(options: ParserOptions = {}) {\n this.options = {\n gfm: true,\n ...options\n }\n this.context = createInitialContext()\n // 初始化容器配置(构造时计算一次)\n this.containerConfig = this.computeContainerConfig()\n }\n\n private generateBlockId(): string {\n return `block-${++this.blockIdCounter}`\n }\n\n private computeContainerConfig(): ContainerConfig | undefined {\n const containers = this.options.containers\n if (!containers) return undefined\n return containers === true ? {} : containers\n }\n\n private parse(text: string): Root {\n const extensions: MicromarkExtension[] = []\n const mdastExtensions: MdastExtension[] = []\n\n if (this.options.gfm) {\n extensions.push(gfm())\n mdastExtensions.push(...gfmFromMarkdown())\n }\n\n // 如果用户传入了自定义扩展,添加它们\n if (this.options.extensions) {\n extensions.push(...this.options.extensions)\n }\n if (this.options.mdastExtensions) {\n mdastExtensions.push(...this.options.mdastExtensions)\n }\n\n return fromMarkdown(text, { extensions, mdastExtensions })\n }\n\n /**\n * 增量更新 lines 和 lineOffsets\n * 只处理新增的内容,避免全量 split\n */\n private updateLines(): void {\n const prevLineCount = this.lines.length\n\n if (prevLineCount === 0) {\n // 首次输入,直接 split\n this.lines = this.buffer.split('\\n')\n this.lineOffsets = [0]\n for (let i = 0; i < this.lines.length; i++) {\n this.lineOffsets.push(this.lineOffsets[i] + this.lines[i].length + 1)\n }\n return\n }\n\n // 找到最后一个不完整的行(可能被新 chunk 续上)\n const lastLineStart = this.lineOffsets[prevLineCount - 1]\n const textFromLastLine = this.buffer.slice(lastLineStart)\n\n // 重新 split 最后一行及之后的内容\n const newLines = textFromLastLine.split('\\n')\n\n // 替换最后一行并追加新行\n this.lines.length = prevLineCount - 1\n this.lineOffsets.length = prevLineCount\n\n for (let i = 0; i < newLines.length; i++) {\n this.lines.push(newLines[i])\n const prevOffset = this.lineOffsets[this.lineOffsets.length - 1]\n this.lineOffsets.push(prevOffset + newLines[i].length + 1)\n }\n }\n\n /**\n * O(1) 获取行偏移量\n */\n private getLineOffset(lineIndex: number): number {\n return this.lineOffsets[lineIndex] ?? 0\n }\n\n /**\n * 查找稳定边界\n * 返回稳定边界行号和该行对应的上下文(用于后续更新,避免重复计算)\n */\n private findStableBoundary(): { line: number; contextAtLine: BlockContext } {\n let stableLine = -1\n let stableContext: BlockContext = this.context\n let tempContext = { ...this.context }\n\n for (let i = this.pendingStartLine; i < this.lines.length; i++) {\n const line = this.lines[i]\n const wasInFencedCode = tempContext.inFencedCode\n const wasInContainer = tempContext.inContainer\n const wasContainerDepth = tempContext.containerDepth\n\n tempContext = updateContext(line, tempContext, this.containerConfig)\n\n if (wasInFencedCode && !tempContext.inFencedCode) {\n if (i < this.lines.length - 1) {\n stableLine = i\n stableContext = { ...tempContext }\n }\n continue\n }\n\n if (tempContext.inFencedCode) {\n continue\n }\n\n if (wasInContainer && wasContainerDepth === 1 && !tempContext.inContainer) {\n if (i < this.lines.length - 1) {\n stableLine = i\n stableContext = { ...tempContext }\n }\n continue\n }\n\n if (tempContext.inContainer) {\n continue\n }\n\n const stablePoint = this.checkStability(i)\n if (stablePoint >= 0) {\n stableLine = stablePoint\n stableContext = { ...tempContext }\n }\n }\n\n return { line: stableLine, contextAtLine: stableContext }\n }\n\n private checkStability(lineIndex: number): number {\n // 第一行永远不稳定\n if (lineIndex === 0) {\n return -1\n }\n\n const line = this.lines[lineIndex]\n const prevLine = this.lines[lineIndex - 1]\n\n // 前一行是独立块(标题、分割线),该块已完成\n if (isHeading(prevLine) || isThematicBreak(prevLine)) {\n return lineIndex - 1\n }\n\n // 最后一行不稳定(可能还有更多内容)\n if (lineIndex >= this.lines.length - 1) {\n return -1\n }\n\n // 前一行非空时,如果当前行是新块开始,则前一块已完成\n if (!isEmptyLine(prevLine)) {\n // 新标题开始\n if (isHeading(line)) {\n return lineIndex - 1\n }\n\n // 新代码块开始\n if (detectFenceStart(line)) {\n return lineIndex - 1\n }\n\n // 新引用块开始(排除连续引用)\n if (isBlockquoteStart(line) && !isBlockquoteStart(prevLine)) {\n return lineIndex - 1\n }\n\n // 新列表开始(排除连续列表项)\n if (isListItemStart(line) && !isListItemStart(prevLine)) {\n return lineIndex - 1\n }\n\n // 新容器开始\n if (this.containerConfig !== undefined) {\n const container = detectContainer(line, this.containerConfig)\n if (container && !container.isEnd) {\n const prevContainer = detectContainer(prevLine, this.containerConfig)\n if (!prevContainer || prevContainer.isEnd) {\n return lineIndex - 1\n }\n }\n }\n }\n\n // 空行标志段落结束\n if (isEmptyLine(line) && !isEmptyLine(prevLine)) {\n return lineIndex\n }\n\n return -1\n }\n\n private nodesToBlocks(\n nodes: RootContent[],\n startOffset: number,\n rawText: string,\n status: BlockStatus\n ): ParsedBlock[] {\n const blocks: ParsedBlock[] = []\n let currentOffset = startOffset\n\n for (const node of nodes) {\n const nodeStart = node.position?.start?.offset ?? currentOffset\n const nodeEnd = node.position?.end?.offset ?? currentOffset + 1\n const nodeText = rawText.substring(nodeStart - startOffset, nodeEnd - startOffset)\n\n blocks.push({\n id: this.generateBlockId(),\n status,\n node,\n startOffset: nodeStart,\n endOffset: nodeEnd,\n rawText: nodeText\n })\n\n currentOffset = nodeEnd\n }\n\n return blocks\n }\n\n /**\n * 追加新的 chunk 并返回增量更新\n */\n append(chunk: string): IncrementalUpdate {\n this.buffer += chunk\n this.updateLines()\n\n const { line: stableBoundary, contextAtLine } = this.findStableBoundary()\n\n const update: IncrementalUpdate = {\n completed: [],\n updated: [],\n pending: [],\n ast: { type: 'root', children: [] }\n }\n\n if (stableBoundary >= this.pendingStartLine && stableBoundary >= 0) {\n const stableText = this.lines.slice(this.pendingStartLine, stableBoundary + 1).join('\\n')\n const stableOffset = this.getLineOffset(this.pendingStartLine)\n\n const ast = this.parse(stableText)\n const newBlocks = this.nodesToBlocks(ast.children, stableOffset, stableText, 'completed')\n\n this.completedBlocks.push(...newBlocks)\n update.completed = newBlocks\n\n // 直接使用 findStableBoundary 计算好的上下文,避免重复遍历\n this.context = contextAtLine\n this.pendingStartLine = stableBoundary + 1\n }\n\n if (this.pendingStartLine < this.lines.length) {\n const pendingText = this.lines.slice(this.pendingStartLine).join('\\n')\n\n if (pendingText.trim()) {\n const pendingOffset = this.getLineOffset(this.pendingStartLine)\n const ast = this.parse(pendingText)\n\n update.pending = this.nodesToBlocks(ast.children, pendingOffset, pendingText, 'pending')\n }\n }\n\n // 缓存 pending blocks 供 getAst 使用\n this.lastPendingBlocks = update.pending\n\n update.ast = {\n type: 'root',\n children: [...this.completedBlocks.map((b) => b.node), ...update.pending.map((b) => b.node)]\n }\n\n // 触发状态变化回调\n this.emitChange(update.pending)\n\n return update\n }\n\n /**\n * 触发状态变化回调\n */\n private emitChange(pendingBlocks: ParsedBlock[] = []): void {\n if (this.options.onChange) {\n this.options.onChange({\n completedBlocks: this.completedBlocks,\n pendingBlocks,\n markdown: this.buffer,\n ast: {\n type: 'root',\n children: [\n ...this.completedBlocks.map((b) => b.node),\n ...pendingBlocks.map((b) => b.node)\n ]\n }\n })\n }\n }\n\n /**\n * 标记解析完成,处理剩余内容\n * 也可用于强制中断时(如用户点击停止),将 pending 内容标记为 completed\n */\n finalize(): IncrementalUpdate {\n const update: IncrementalUpdate = {\n completed: [],\n updated: [],\n pending: [],\n ast: { type: 'root', children: [] }\n }\n\n if (this.pendingStartLine < this.lines.length) {\n const remainingText = this.lines.slice(this.pendingStartLine).join('\\n')\n\n if (remainingText.trim()) {\n const remainingOffset = this.getLineOffset(this.pendingStartLine)\n const ast = this.parse(remainingText)\n\n const finalBlocks = this.nodesToBlocks(\n ast.children,\n remainingOffset,\n remainingText,\n 'completed'\n )\n\n this.completedBlocks.push(...finalBlocks)\n update.completed = finalBlocks\n }\n }\n\n // 清空 pending 缓存\n this.lastPendingBlocks = []\n this.pendingStartLine = this.lines.length\n\n update.ast = {\n type: 'root',\n children: this.completedBlocks.map((b) => b.node)\n }\n\n // 触发状态变化回调\n this.emitChange([])\n\n return update\n }\n\n /**\n * 强制中断解析,将所有待处理内容标记为完成\n * 语义上等同于 finalize(),但名称更清晰\n */\n abort(): IncrementalUpdate {\n return this.finalize()\n }\n\n /**\n * 获取当前完整的 AST\n * 复用上次 append 的 pending 结果,避免重复解析\n */\n getAst(): Root {\n return {\n type: 'root',\n children: [\n ...this.completedBlocks.map((b) => b.node),\n ...this.lastPendingBlocks.map((b) => b.node)\n ]\n }\n }\n\n /**\n * 获取所有已完成的块\n */\n getCompletedBlocks(): ParsedBlock[] {\n return [...this.completedBlocks]\n }\n\n /**\n * 获取当前缓冲区内容\n */\n getBuffer(): string {\n return this.buffer\n }\n\n /**\n * 设置状态变化回调(用于 DevTools 等)\n */\n setOnChange(callback: ((state: import('../types').ParserState) => void) | undefined): void {\n this.options.onChange = callback\n }\n\n /**\n * 重置解析器状态\n */\n reset(): void {\n this.buffer = ''\n this.lines = []\n this.lineOffsets = [0]\n this.completedBlocks = []\n this.pendingStartLine = 0\n this.blockIdCounter = 0\n this.context = createInitialContext()\n this.lastPendingBlocks = []\n\n // 触发状态变化回调\n this.emitChange([])\n }\n\n /**\n * 一次性渲染完整 Markdown(reset + append + finalize)\n * @param content 完整的 Markdown 内容\n * @returns 解析结果\n */\n render(content: string): IncrementalUpdate {\n this.reset()\n this.append(content)\n return this.finalize()\n }\n}\n\n/**\n * 创建 Incremark 解析器实例\n */\nexport function createIncremarkParser(options?: ParserOptions): IncremarkParser {\n return new IncremarkParser(options)\n}\n","/**\n * 工具函数\n */\n\n/**\n * 生成唯一 ID\n */\nlet idCounter = 0\nexport function generateId(prefix = 'block'): string {\n return `${prefix}-${++idCounter}`\n}\n\n/**\n * 重置 ID 计数器(用于测试)\n */\nexport function resetIdCounter(): void {\n idCounter = 0\n}\n\n/**\n * 计算行的偏移量\n */\nexport function calculateLineOffset(lines: string[], lineIndex: number): number {\n let offset = 0\n for (let i = 0; i < lineIndex && i < lines.length; i++) {\n offset += lines[i].length + 1 // +1 for newline\n }\n return offset\n}\n\n/**\n * 将文本按行分割\n */\nexport function splitLines(text: string): string[] {\n return text.split('\\n')\n}\n\n/**\n * 合并行为文本\n */\nexport function joinLines(lines: string[], start: number, end: number): string {\n return lines.slice(start, end + 1).join('\\n')\n}\n\n","import type { RootContent, Text } from 'mdast'\nimport type { AstNode } from '../types'\n\n/**\n * 文本块片段(用于渐入动画)\n */\nexport interface TextChunk {\n /** 文本内容 */\n text: string\n /** 创建时间戳 */\n createdAt: number\n}\n\n/**\n * 扩展的文本节点(支持 chunks)\n */\nexport interface TextNodeWithChunks extends Text {\n /** 稳定部分的长度(不需要动画) */\n stableLength?: number\n /** 临时的文本片段,用于渐入动画 */\n chunks?: TextChunk[]\n}\n\n/**\n * 计算 AST 节点的总字符数\n */\nexport function countChars(node: RootContent): number {\n return countCharsInNode(node as AstNode)\n}\n\n/**\n * 计算单个 AST 节点的字符数(内部辅助函数)\n */\nfunction countCharsInNode(n: AstNode): number {\n if (n.value && typeof n.value === 'string') {\n return n.value.length\n }\n if (n.children && Array.isArray(n.children)) {\n let count = 0\n for (const child of n.children) {\n count += countCharsInNode(child)\n }\n return count\n }\n // 其他节点(如 thematicBreak, image)算作 1 个字符\n return 1\n}\n\n/**\n * 累积的 chunks 信息\n */\nexport interface AccumulatedChunks {\n /** 已经稳定显示的字符数(不需要动画) */\n stableChars: number\n /** 累积的 chunk 列表 */\n chunks: TextChunk[]\n}\n\n/** chunk 范围信息 */\ninterface ChunkRange {\n start: number\n end: number\n chunk: TextChunk\n}\n\n/**\n * 截断 AST 节点,只保留前 maxChars 个字符\n * 支持 chunks(用于渐入动画)\n * 支持增量模式:跳过已处理的字符,只处理新增部分\n * \n * @param node 原始节点\n * @param maxChars 最大字符数\n * @param accumulatedChunks 累积的 chunks 信息(用于渐入动画)\n * @param skipChars 跳过前 N 个字符(已处理的部分,用于增量追加)\n * @returns 截断后的节点,如果 maxChars <= 0 返回 null\n */\nexport function sliceAst(\n node: RootContent, \n maxChars: number,\n accumulatedChunks?: AccumulatedChunks,\n skipChars: number = 0\n): RootContent | null {\n if (maxChars <= 0) return null\n if (skipChars >= maxChars) return null\n\n let remaining = maxChars - skipChars // 只处理新增部分\n let charIndex = 0\n \n // 计算 chunks 在文本中的范围\n const chunkRanges: ChunkRange[] = []\n if (accumulatedChunks && accumulatedChunks.chunks.length > 0) {\n let chunkStart = accumulatedChunks.stableChars\n for (const chunk of accumulatedChunks.chunks) {\n chunkRanges.push({\n start: chunkStart,\n end: chunkStart + chunk.text.length,\n chunk\n })\n chunkStart += chunk.text.length\n }\n }\n\n function process(n: AstNode): AstNode | null {\n if (remaining <= 0) return null\n\n // 文本类节点:截断 value,可能添加 chunks\n if (n.value && typeof n.value === 'string') {\n const nodeStart = charIndex\n const nodeEnd = charIndex + n.value.length\n \n // 如果整个节点都在 skipChars 之前,跳过\n if (nodeEnd <= skipChars) {\n charIndex = nodeEnd\n return null\n }\n \n // 如果节点跨越 skipChars,需要从 skipChars 位置开始取\n const skipInNode = Math.max(0, skipChars - nodeStart)\n const take = Math.min(n.value.length - skipInNode, remaining)\n remaining -= take\n if (take === 0) return null\n\n const slicedValue = n.value.slice(skipInNode, skipInNode + take)\n charIndex = nodeEnd\n \n const result: AstNode & { stableLength?: number; chunks?: TextChunk[] } = { \n ...n, \n value: slicedValue \n }\n \n // 检查是否有 chunks 落在这个节点范围内\n if (chunkRanges.length > 0 && accumulatedChunks) {\n const nodeChunks: TextChunk[] = []\n let firstChunkLocalStart = take // 第一个 chunk 在节点中的起始位置\n \n for (const range of chunkRanges) {\n // 计算 chunk 与当前节点的交集(考虑 skipChars)\n const overlapStart = Math.max(range.start, nodeStart + skipInNode)\n const overlapEnd = Math.min(range.end, nodeStart + skipInNode + take)\n \n if (overlapStart < overlapEnd) {\n // 有交集,提取对应的文本(相对于 slicedValue)\n const localStart = overlapStart - (nodeStart + skipInNode)\n const localEnd = overlapEnd - (nodeStart + skipInNode)\n const chunkText = slicedValue.slice(localStart, localEnd)\n \n if (chunkText.length > 0) {\n // 记录第一个 chunk 的起始位置\n if (nodeChunks.length === 0) {\n firstChunkLocalStart = localStart\n }\n nodeChunks.push({\n text: chunkText,\n createdAt: range.chunk.createdAt\n })\n }\n }\n }\n \n if (nodeChunks.length > 0) {\n result.stableLength = firstChunkLocalStart\n result.chunks = nodeChunks\n }\n }\n \n return result\n }\n\n // 容器节点:递归处理 children\n if (n.children && Array.isArray(n.children)) {\n const newChildren: AstNode[] = []\n let childCharIndex = charIndex\n \n for (const child of n.children) {\n if (remaining <= 0) break\n \n // 计算子节点的字符范围\n const childChars = countCharsInNode(child as AstNode)\n const childStart = childCharIndex\n const childEnd = childCharIndex + childChars\n \n // 如果子节点完全在 skipChars 之前,跳过\n if (childEnd <= skipChars) {\n childCharIndex = childEnd\n continue\n }\n \n // 如果子节点跨越 skipChars,需要处理\n // 临时更新 charIndex 以便子节点正确处理 skipChars\n const savedCharIndex = charIndex\n charIndex = childStart\n const processed = process(child)\n charIndex = savedCharIndex\n \n if (processed) {\n newChildren.push(processed)\n }\n \n childCharIndex = childEnd\n }\n \n if (newChildren.length === 0) {\n return null\n }\n return { ...n, children: newChildren }\n }\n\n // 其他节点(如 thematicBreak, image)\n remaining -= 1\n charIndex += 1\n return { ...n }\n }\n\n return process(node as AstNode) as RootContent | null\n}\n\n/**\n * 增量追加:将新增的字符范围追加到现有的 displayNode\n * 这是真正的增量追加实现,只处理新增部分,不重复遍历已稳定的节点\n * \n * @param baseNode 已截断的基础节点(稳定的部分)\n * @param sourceNode 原始完整节点\n * @param startChars 起始字符位置(已处理的字符数)\n * @param endChars 结束字符位置(新的进度)\n * @param accumulatedChunks 累积的 chunks 信息(用于渐入动画)\n * @returns 追加后的完整节点\n */\nexport function appendToAst(\n baseNode: RootContent,\n sourceNode: RootContent,\n startChars: number,\n endChars: number,\n accumulatedChunks?: AccumulatedChunks\n): RootContent {\n // 如果新增字符数为 0,直接返回 baseNode\n if (endChars <= startChars) {\n return baseNode\n }\n\n // 从 sourceNode 中提取新增的字符范围(跳过已处理的部分)\n const newChars = endChars - startChars\n const newPart = sliceAst(sourceNode, endChars, accumulatedChunks, startChars)\n \n // 如果提取失败,返回 baseNode\n if (!newPart) {\n return baseNode\n }\n\n // 将新增部分合并到 baseNode\n return mergeAstNodes(baseNode, newPart)\n}\n\n/**\n * 合并两个 AST 节点\n * 将 newPart 追加到 baseNode 的最后一个可追加节点中\n */\nfunction mergeAstNodes(baseNode: RootContent, newPart: RootContent): RootContent {\n // 如果两个节点类型不同,无法合并,返回 baseNode\n if (baseNode.type !== newPart.type) {\n return baseNode\n }\n\n const base = baseNode as AstNode\n const part = newPart as AstNode\n\n // 如果是文本节点,合并文本和 chunks\n if (base.value && typeof base.value === 'string' && part.value && typeof part.value === 'string') {\n const baseChunks = (base as TextNodeWithChunks).chunks || []\n const partChunks = (part as TextNodeWithChunks).chunks || []\n \n // 合并所有 chunks:累积所有读取的 chunks\n // chunks 数组包含每次读取的新文本片段,它们 join 到一起就是 value\n const mergedChunks = [...baseChunks, ...partChunks]\n \n // 根据设计:value = stableText + chunks[0].text + chunks[1].text + ... + chunks[n].text\n // base.value = baseStableText + baseChunks[0].text + ... + baseChunks[n].text\n // part.value = partStableText + partChunks[0].text + ... + partChunks[m].text\n // 合并后:value = base.value + part.value(完整文本)\n const mergedValue = base.value + part.value\n \n // stableLength 是稳定部分的长度(不需要动画的部分)\n // base 的稳定部分保持不变,base 的 chunks 和 part 的 chunks 都需要动画\n const baseStableLength = (base as TextNodeWithChunks).stableLength ?? 0\n \n // 验证:mergedValue 应该等于 baseStableText + 所有 chunks 的文本\n // baseStableText = base.value.slice(0, baseStableLength)\n // 所有 chunks 的文本 = baseChunks + partChunks 的文本\n const result = {\n ...base,\n value: mergedValue,\n stableLength: mergedChunks.length > 0 ? baseStableLength : undefined,\n chunks: mergedChunks.length > 0 ? mergedChunks : undefined\n } as TextNodeWithChunks\n \n return result as RootContent\n }\n\n // 如果是容器节点,合并 children\n if (base.children && Array.isArray(base.children) && part.children && Array.isArray(part.children)) {\n // 如果 base 的最后一个子节点和 part 的第一个子节点类型相同,尝试合并\n if (base.children.length > 0 && part.children.length > 0) {\n const lastBaseChild = base.children[base.children.length - 1]\n const firstPartChild = part.children[0]\n \n if (lastBaseChild.type === firstPartChild.type) {\n // 尝试合并最后一个和第一个子节点\n const merged = mergeAstNodes(lastBaseChild as RootContent, firstPartChild as RootContent)\n return {\n ...base,\n children: [\n ...base.children.slice(0, -1),\n merged as AstNode,\n ...part.children.slice(1)\n ]\n } as RootContent\n }\n }\n\n // 否则直接追加所有子节点\n return {\n ...base,\n children: [...base.children, ...part.children]\n } as RootContent\n }\n\n // 其他情况,返回 baseNode(无法合并)\n return baseNode\n}\n\n/**\n * 深拷贝 AST 节点\n * 使用递归浅拷贝实现,比 JSON.parse/stringify 更高效\n * 且保持对象结构完整性\n */\nexport function cloneNode<T extends RootContent>(node: T): T {\n // 优先使用 structuredClone(Node 17+ / 现代浏览器)\n if (typeof structuredClone === 'function') {\n return structuredClone(node)\n }\n \n // 回退到递归拷贝\n return deepClone(node) as T\n}\n\n/**\n * 递归深拷贝对象\n */\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => deepClone(item)) as T\n }\n\n const cloned = {} as T\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n cloned[key] = deepClone(obj[key])\n }\n }\n return cloned\n}\n","import type { RootContent } from 'mdast'\nimport type { AstNode } from '../types'\nimport type {\n SourceBlock,\n DisplayBlock,\n TransformerOptions,\n TransformerState,\n TransformerPlugin,\n AnimationEffect\n} from './types'\nimport { countChars as defaultCountChars, sliceAst as defaultSliceAst, appendToAst, type TextChunk, type AccumulatedChunks } from './utils'\n\n/**\n * Block Transformer\n *\n * 用于控制 blocks 的逐步显示(打字机效果)\n * 作为解析器和渲染器之间的中间层\n *\n * 特性:\n * - 使用 requestAnimationFrame 实现流畅动画\n * - 支持随机步长,模拟真实打字效果\n * - 支持 typing 动画效果\n * - 页面不可见时自动暂停,节省资源\n * - 插件系统支持自定义节点处理\n *\n * @example\n * ```typescript\n * const transformer = new BlockTransformer({\n * charsPerTick: [1, 3], // 随机 1-3 个字符\n * tickInterval: 30,\n * effect: 'typing',\n * onChange: (displayBlocks) => {\n * // 更新 UI\n * }\n * })\n *\n * // 推入新 blocks\n * transformer.push(blocks)\n *\n * // 获取当前显示状态\n * const displayBlocks = transformer.getDisplayBlocks()\n * ```\n */\nexport class BlockTransformer<T = unknown> {\n private state: TransformerState<T>\n private options: {\n charsPerTick: number | [number, number]\n tickInterval: number\n effect: AnimationEffect\n plugins: TransformerPlugin[]\n onChange: (displayBlocks: DisplayBlock<T>[]) => void\n pauseOnHidden: boolean\n }\n private rafId: number | null = null\n private lastTickTime = 0\n private isRunning = false\n private isPaused = false\n private chunks: TextChunk[] = [] // 累积的 chunks(用于 fade-in 动画)\n private visibilityHandler: (() => void) | null = null\n \n // ============ 性能优化:缓存机制 ============\n /** 缓存的已截断 displayNode(稳定的部分,避免重复遍历) */\n private cachedDisplayNode: RootContent | null = null\n /** 缓存的字符数(避免重复计算) */\n private cachedTotalChars: number | null = null\n /** 当前缓存的进度(对应 cachedDisplayNode) */\n private cachedProgress: number = 0\n\n constructor(options: TransformerOptions = {}) {\n this.options = {\n charsPerTick: options.charsPerTick ?? 1,\n tickInterval: options.tickInterval ?? 20,\n effect: options.effect ?? 'none',\n plugins: options.plugins ?? [],\n onChange: options.onChange ?? (() => {}),\n pauseOnHidden: options.pauseOnHidden ?? true\n }\n\n this.state = {\n completedBlocks: [],\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n\n // 设置页面可见性监听\n if (this.options.pauseOnHidden && typeof document !== 'undefined') {\n this.setupVisibilityHandler()\n }\n }\n\n /**\n * 推入新的 blocks\n * 会自动过滤已存在的 blocks\n */\n push(blocks: SourceBlock<T>[]): void {\n const existingIds = this.getAllBlockIds()\n\n // 找出新增的 blocks\n const newBlocks = blocks.filter((b) => !existingIds.has(b.id))\n\n if (newBlocks.length > 0) {\n this.state.pendingBlocks.push(...newBlocks)\n this.startIfNeeded()\n }\n\n // 如果当前正在显示的 block 内容更新了(pending block 变化)\n if (this.state.currentBlock) {\n const updated = blocks.find((b) => b.id === this.state.currentBlock!.id)\n if (updated && updated.node !== this.state.currentBlock.node) {\n // 内容更新,清除缓存\n this.clearCache()\n \n const oldTotal = this.cachedTotalChars ?? this.countChars(this.state.currentBlock.node)\n const newTotal = this.countChars(updated.node)\n \n // 如果字符数减少了(AST 结构变化,如 **xxx 变成 **xxx**)\n // 重新计算进度,保持相对位置\n if (newTotal < oldTotal || newTotal < this.state.currentProgress) {\n this.state.currentProgress = Math.min(this.state.currentProgress, newTotal)\n }\n \n // 内容更新,更新引用\n this.state.currentBlock = updated\n // 如果之前暂停了(因为到达末尾),重新开始\n if (!this.rafId && !this.isPaused) {\n if (this.state.currentProgress < newTotal) {\n this.startIfNeeded()\n }\n }\n }\n }\n }\n\n /**\n * 更新指定 block(用于 pending block 内容增加时)\n */\n update(block: SourceBlock<T>): void {\n if (this.state.currentBlock?.id === block.id) {\n const oldTotal = this.cachedTotalChars ?? this.countChars(this.state.currentBlock.node)\n const newTotal = this.countChars(block.node)\n\n this.state.currentBlock = block\n\n // 如果内容增加了且之前暂停了,继续\n if (newTotal > oldTotal && !this.rafId && !this.isPaused && this.state.currentProgress >= oldTotal) {\n // 内容变化,清除缓存\n this.clearCache()\n this.startIfNeeded()\n }\n }\n }\n\n /**\n * 跳过所有动画,直接显示全部内容\n */\n skip(): void {\n this.stop()\n\n const allBlocks = [\n ...this.state.completedBlocks,\n ...(this.state.currentBlock ? [this.state.currentBlock] : []),\n ...this.state.pendingBlocks\n ]\n\n this.state = {\n completedBlocks: allBlocks,\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n this.chunks = []\n this.clearCache()\n\n this.emit()\n }\n\n /**\n * 重置状态\n */\n reset(): void {\n this.stop()\n this.state = {\n completedBlocks: [],\n currentBlock: null,\n currentProgress: 0,\n pendingBlocks: []\n }\n this.chunks = []\n this.clearCache()\n this.emit()\n }\n\n /**\n * 暂停动画\n */\n pause(): void {\n this.isPaused = true\n this.cancelRaf()\n }\n\n /**\n * 恢复动画\n */\n resume(): void {\n if (this.isPaused) {\n this.isPaused = false\n this.startIfNeeded()\n }\n }\n\n /**\n * 获取用于渲染的 display blocks\n * 优化:使用缓存的 displayNode,避免重复遍历已稳定的节点\n */\n getDisplayBlocks(): DisplayBlock<T>[] {\n const result: DisplayBlock<T>[] = []\n\n // 已完成的 blocks\n for (const block of this.state.completedBlocks) {\n result.push({\n ...block,\n displayNode: block.node,\n progress: 1,\n isDisplayComplete: true\n })\n }\n\n // 当前正在显示的 block\n if (this.state.currentBlock) {\n // 使用缓存的字符数\n const total = this.getTotalChars()\n \n // 如果进度变化了或缓存无效,更新缓存的 displayNode\n if (this.state.currentProgress !== this.cachedProgress || !this.cachedDisplayNode) {\n this.updateCachedDisplayNode()\n }\n\n result.push({\n ...this.state.currentBlock,\n displayNode: this.cachedDisplayNode || { type: 'paragraph', children: [] },\n progress: total > 0 ? this.state.currentProgress / total : 1,\n isDisplayComplete: false\n })\n }\n\n return result\n }\n\n /**\n * 是否正在处理中\n */\n isProcessing(): boolean {\n return this.isRunning || this.state.currentBlock !== null || this.state.pendingBlocks.length > 0\n }\n\n /**\n * 是否已暂停\n */\n isPausedState(): boolean {\n return this.isPaused\n }\n\n /**\n * 获取内部状态(用于调试)\n */\n getState(): Readonly<TransformerState<T>> {\n return { ...this.state }\n }\n\n /**\n * 动态更新配置\n */\n setOptions(options: Partial<Pick<TransformerOptions, 'charsPerTick' | 'tickInterval' | 'effect' | 'pauseOnHidden'>>): void {\n if (options.charsPerTick !== undefined) {\n this.options.charsPerTick = options.charsPerTick\n }\n if (options.tickInterval !== undefined) {\n this.options.tickInterval = options.tickInterval\n }\n if (options.effect !== undefined) {\n this.options.effect = options.effect\n }\n if (options.pauseOnHidden !== undefined) {\n this.options.pauseOnHidden = options.pauseOnHidden\n if (options.pauseOnHidden && typeof document !== 'undefined') {\n this.setupVisibilityHandler()\n } else {\n this.removeVisibilityHandler()\n }\n }\n }\n\n /**\n * 获取当前配置\n */\n getOptions(): { \n charsPerTick: number | [number, number]\n tickInterval: number\n effect: AnimationEffect\n } {\n return {\n charsPerTick: this.options.charsPerTick,\n tickInterval: this.options.tickInterval,\n effect: this.options.effect\n }\n }\n\n /**\n * 获取当前动画效果\n */\n getEffect(): AnimationEffect {\n return this.options.effect\n }\n\n /**\n * 销毁,清理资源\n */\n destroy(): void {\n this.stop()\n this.removeVisibilityHandler()\n }\n\n // ============ 私有方法 ============\n\n private getAllBlockIds(): Set<string> {\n return new Set([\n ...this.state.completedBlocks.map((b) => b.id),\n this.state.currentBlock?.id,\n ...this.state.pendingBlocks.map((b) => b.id)\n ].filter((id): id is string => id !== undefined))\n }\n\n private setupVisibilityHandler(): void {\n if (this.visibilityHandler) return\n\n this.visibilityHandler = () => {\n if (document.hidden) {\n this.pause()\n } else {\n this.resume()\n }\n }\n\n document.addEventListener('visibilitychange', this.visibilityHandler)\n }\n\n private removeVisibilityHandler(): void {\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler)\n this.visibilityHandler = null\n }\n }\n\n private startIfNeeded(): void {\n if (this.rafId || this.isPaused) return\n\n if (!this.state.currentBlock && this.state.pendingBlocks.length > 0) {\n this.state.currentBlock = this.state.pendingBlocks.shift()!\n this.state.currentProgress = 0\n this.clearCache() // 新 block,清除缓存\n }\n\n if (this.state.currentBlock) {\n this.isRunning = true\n this.lastTickTime = 0\n this.scheduleNextFrame()\n }\n }\n\n private scheduleNextFrame(): void {\n this.rafId = requestAnimationFrame((time) => this.animationFrame(time))\n }\n\n private animationFrame(time: number): void {\n this.rafId = null\n\n // 计算是否应该执行 tick\n if (this.lastTickTime === 0) {\n this.lastTickTime = time\n }\n\n const elapsed = time - this.lastTickTime\n\n if (elapsed >= this.options.tickInterval) {\n this.lastTickTime = time\n this.tick()\n }\n\n // 如果还在运行,继续调度\n if (this.isRunning && !this.isPaused) {\n this.scheduleNextFrame()\n }\n }\n\n private tick(): void {\n const block = this.state.currentBlock\n if (!block) {\n this.processNext()\n return\n }\n\n // 使用缓存的字符数,避免重复计算\n const total = this.getTotalChars()\n const step = this.getStep()\n const prevProgress = this.state.currentProgress\n \n this.state.currentProgress = Math.min(prevProgress + step, total)\n\n // 如果是 fade-in 效果,添加新的 chunk\n if (this.options.effect === 'fade-in' && this.state.currentProgress > prevProgress) {\n // 从 block.node 中提取新增的字符\n const newText = this.extractText(block.node, prevProgress, this.state.currentProgress)\n if (newText.length > 0) {\n this.chunks.push({\n text: newText,\n createdAt: Date.now()\n })\n }\n }\n\n this.emit()\n\n if (this.state.currentProgress >= total) {\n // 当前 block 完成,清空 chunks 和缓存\n this.notifyComplete(block.node)\n this.state.completedBlocks.push(block)\n this.state.currentBlock = null\n this.state.currentProgress = 0\n this.chunks = []\n this.clearCache()\n this.processNext()\n }\n }\n\n /**\n * 从 AST 节点中提取指定范围的文本\n */\n private extractText(node: RootContent, start: number, end: number): string {\n let result = ''\n let charIndex = 0\n\n function traverse(n: AstNode): boolean {\n if (charIndex >= end) return false\n\n if (n.value && typeof n.value === 'string') {\n const nodeStart = charIndex\n const nodeEnd = charIndex + n.value.length\n charIndex = nodeEnd\n\n // 计算交集\n const overlapStart = Math.max(start, nodeStart)\n const overlapEnd = Math.min(end, nodeEnd)\n\n if (overlapStart < overlapEnd) {\n result += n.value.slice(overlapStart - nodeStart, overlapEnd - nodeStart)\n }\n return charIndex < end\n }\n\n if (n.children && Array.isArray(n.children)) {\n for (const child of n.children) {\n if (!traverse(child)) return false\n }\n }\n\n return true\n }\n\n traverse(node as AstNode)\n return result\n }\n\n private getStep(): number {\n const { charsPerTick } = this.options\n if (typeof charsPerTick === 'number') {\n return charsPerTick\n }\n // 随机步长\n const [min, max] = charsPerTick\n return Math.floor(Math.random() * (max - min + 1)) + min\n }\n\n private processNext(): void {\n if (this.state.pendingBlocks.length > 0) {\n this.state.currentBlock = this.state.pendingBlocks.shift()!\n this.state.currentProgress = 0\n this.chunks = []\n this.clearCache() // 新 block,清除缓存\n this.emit()\n // 继续运行(rAF 已经在调度中)\n } else {\n this.isRunning = false\n this.cancelRaf()\n this.emit()\n }\n }\n\n private cancelRaf(): void {\n if (this.rafId) {\n cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n }\n\n private stop(): void {\n this.cancelRaf()\n this.isRunning = false\n this.isPaused = false\n }\n\n private emit(): void {\n this.options.onChange(this.getDisplayBlocks())\n }\n\n // ============ 插件调用 ============\n\n private countChars(node: RootContent): number {\n // 先找匹配的插件\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.countChars) {\n const result = plugin.countChars(node)\n if (result !== undefined) return result\n }\n }\n // 默认计算\n return defaultCountChars(node)\n }\n\n private sliceNode(node: RootContent, chars: number, accumulatedChunks?: AccumulatedChunks): RootContent | null {\n // 先找匹配的插件\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.sliceNode) {\n const total = this.countChars(node)\n const result = plugin.sliceNode(node, chars, total)\n if (result !== null) return result\n }\n }\n // 默认截断,传入累积的 chunks\n return defaultSliceAst(node, chars, accumulatedChunks)\n }\n\n private notifyComplete(node: RootContent): void {\n for (const plugin of this.options.plugins) {\n if (plugin.match?.(node) && plugin.onComplete) {\n plugin.onComplete(node)\n }\n }\n }\n\n // ============ 缓存管理方法 ============\n\n /**\n * 更新缓存的 displayNode\n * 使用真正的增量追加模式:只处理新增部分,不重复遍历已稳定的节点\n */\n private updateCachedDisplayNode(): void {\n const block = this.state.currentBlock\n if (!block) {\n this.cachedDisplayNode = null\n this.cachedProgress = 0\n return\n }\n\n const currentProgress = this.state.currentProgress\n\n // 如果进度减少了(内容更新导致),需要重新截断\n if (currentProgress < this.cachedProgress) {\n this.cachedDisplayNode = this.sliceNode(\n block.node,\n currentProgress,\n this.getAccumulatedChunks()\n )\n this.cachedProgress = currentProgress\n return\n }\n\n // 如果进度增加了,使用增量追加模式\n if (currentProgress > this.cachedProgress && this.cachedDisplayNode) {\n // 真正的增量追加:只处理新增部分,不重复遍历已稳定的节点\n this.cachedDisplayNode = appendToAst(\n this.cachedDisplayNode,\n block.node,\n this.cachedProgress,\n currentProgress,\n this.getAccumulatedChunks()\n )\n this.cachedProgress = currentProgress\n } else if (!this.cachedDisplayNode) {\n // 首次截断\n this.cachedDisplayNode = this.sliceNode(\n block.node,\n currentProgress,\n this.getAccumulatedChunks()\n )\n this.cachedProgress = currentProgress\n }\n }\n\n /**\n * 获取总字符数(带缓存)\n */\n private getTotalChars(): number {\n if (this.cachedTotalChars === null && this.state.currentBlock) {\n this.cachedTotalChars = this.countChars(this.state.currentBlock.node)\n }\n return this.cachedTotalChars ?? 0\n }\n\n /**\n * 清除缓存(当 block 切换或内容更新时)\n */\n private clearCache(): void {\n this.cachedDisplayNode = null\n this.cachedTotalChars = null\n this.cachedProgress = 0\n }\n\n /**\n * 获取累积的 chunks(用于 fade-in 效果)\n */\n private getAccumulatedChunks(): AccumulatedChunks | undefined {\n if (this.options.effect === 'fade-in' && this.chunks.length > 0) {\n return { stableChars: 0, chunks: this.chunks }\n }\n return undefined\n }\n}\n\n/**\n * 创建 BlockTransformer 实例的工厂函数\n */\nexport function createBlockTransformer<T = unknown>(\n options?: TransformerOptions\n): BlockTransformer<T> {\n return new BlockTransformer<T>(options)\n}\n\n\n\n","import type { RootContent, Code } from 'mdast'\nimport type { TransformerPlugin } from './types'\n\n/**\n * 代码块插件:整体出现,不逐字符显示\n * \n * 注意:默认不启用,代码块默认参与打字机效果\n * 如需整体显示代码块,可手动添加此插件\n */\nexport const codeBlockPlugin: TransformerPlugin = {\n name: 'code-block',\n match: (node: RootContent) => node.type === 'code',\n countChars: () => 1, // 算作 1 个字符,整体出现\n sliceNode: (node, displayedChars, totalChars) => {\n // 要么全部显示,要么不显示\n return displayedChars >= totalChars ? node : null\n }\n}\n\n/**\n * Mermaid 图表插件:整体出现\n * \n * 注意:默认不启用,mermaid 默认参与打字机效果\n * 如需整体显示 mermaid,可手动添加此插件\n */\nexport const mermaidPlugin: TransformerPlugin = {\n name: 'mermaid',\n match: (node: RootContent) => {\n if (node.type !== 'code') return false\n const codeNode = node as Code\n return codeNode.lang === 'mermaid'\n },\n countChars: () => 1,\n sliceNode: (node, displayedChars) => (displayedChars > 0 ? node : null)\n}\n\n/**\n * 图片插件:立即显示(不参与打字机效果)\n * 图片没有文本内容,应立即显示\n */\nexport const imagePlugin: TransformerPlugin = {\n name: 'image',\n match: (node: RootContent) => node.type === 'image',\n countChars: () => 0 // 0 字符,立即显示\n}\n\n/**\n * 数学公式插件:整体出现\n * \n * 注意:默认不启用,数学公式默认参与打字机效果\n * 如需整体显示公式,可手动添加此插件\n */\nexport const mathPlugin: TransformerPlugin = {\n name: 'math',\n match: (node: RootContent) => {\n const type = node.type as string\n return type === 'math' || type === 'inlineMath'\n },\n countChars: () => 1,\n sliceNode: (node, displayedChars) => (displayedChars > 0 ? node : null)\n}\n\n/**\n * 分割线插件:立即显示\n * 分隔线没有文本内容,应立即显示\n */\nexport const thematicBreakPlugin: TransformerPlugin = {\n name: 'thematic-break',\n match: (node: RootContent) => node.type === 'thematicBreak',\n countChars: () => 0\n}\n\n/**\n * 默认插件集合\n * \n * 只包含确实需要特殊处理的节点:\n * - 图片:无文本内容,立即显示\n * - 分隔线:无文本内容,立即显示\n * \n * 代码块、mermaid、数学公式默认参与打字机效果\n * 如需整体显示,可手动添加对应插件\n */\nexport const defaultPlugins: TransformerPlugin[] = [\n imagePlugin,\n thematicBreakPlugin\n]\n\n/**\n * 完整插件集合(所有特殊节点整体显示)\n * 包含代码块、mermaid、数学公式等的整体显示\n */\nexport const allPlugins: TransformerPlugin[] = [\n mermaidPlugin, // mermaid 优先于普通 code block\n codeBlockPlugin,\n imagePlugin,\n mathPlugin,\n thematicBreakPlugin\n]\n\n/**\n * 创建自定义插件的辅助函数\n */\nexport function createPlugin(\n name: string,\n matcher: (node: RootContent) => boolean,\n options: Partial<Omit<TransformerPlugin, 'name' | 'match'>> = {}\n): TransformerPlugin {\n return {\n name,\n match: matcher,\n ...options\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@incremark/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "增量式 Markdown 解析器核心库",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"url": "https://github.com/kingshuaishuai/incremark.git",
|
|
52
52
|
"directory": "packages/core"
|
|
53
53
|
},
|
|
54
|
-
"homepage": "https://incremark
|
|
54
|
+
"homepage": "https://www.incremark.com/",
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsup",
|
|
57
57
|
"dev": "tsup --watch",
|
package/src/detector/index.ts
CHANGED
|
@@ -6,13 +6,33 @@
|
|
|
6
6
|
|
|
7
7
|
import type { BlockContext, ContainerConfig, ContainerMatch } from '../types'
|
|
8
8
|
|
|
9
|
+
// ============ 预编译正则表达式(性能优化) ============
|
|
10
|
+
|
|
11
|
+
const RE_FENCE_START = /^(\s*)((`{3,})|(~{3,}))/
|
|
12
|
+
const RE_EMPTY_LINE = /^\s*$/
|
|
13
|
+
const RE_HEADING = /^#{1,6}\s/
|
|
14
|
+
const RE_THEMATIC_BREAK = /^(\*{3,}|-{3,}|_{3,})\s*$/
|
|
15
|
+
const RE_UNORDERED_LIST = /^(\s*)([-*+])\s/
|
|
16
|
+
const RE_ORDERED_LIST = /^(\s*)(\d{1,9})[.)]\s/
|
|
17
|
+
const RE_BLOCKQUOTE = /^\s{0,3}>/
|
|
18
|
+
const RE_HTML_BLOCK_1 = /^\s{0,3}<(script|pre|style|textarea|!--|!DOCTYPE|\?|!\[CDATA\[)/i
|
|
19
|
+
const RE_HTML_BLOCK_2 = /^\s{0,3}<\/?[a-zA-Z][a-zA-Z0-9-]*(\s|>|$)/
|
|
20
|
+
const RE_TABLE_DELIMITER = /^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?$/
|
|
21
|
+
const RE_ESCAPE_SPECIAL = /[.*+?^${}()|[\]\\]/g
|
|
22
|
+
|
|
23
|
+
/** fence 结束模式缓存 */
|
|
24
|
+
const fenceEndPatternCache = new Map<string, RegExp>()
|
|
25
|
+
|
|
26
|
+
/** 容器模式缓存 */
|
|
27
|
+
const containerPatternCache = new Map<string, RegExp>()
|
|
28
|
+
|
|
9
29
|
// ============ 代码块检测 ============
|
|
10
30
|
|
|
11
31
|
/**
|
|
12
32
|
* 检测行是否是代码块 fence 开始
|
|
13
33
|
*/
|
|
14
34
|
export function detectFenceStart(line: string): { char: string; length: number } | null {
|
|
15
|
-
const match = line.match(
|
|
35
|
+
const match = line.match(RE_FENCE_START)
|
|
16
36
|
if (match) {
|
|
17
37
|
const fence = match[2]
|
|
18
38
|
const char = fence[0]
|
|
@@ -29,7 +49,13 @@ export function detectFenceEnd(line: string, context: BlockContext): boolean {
|
|
|
29
49
|
return false
|
|
30
50
|
}
|
|
31
51
|
|
|
32
|
-
|
|
52
|
+
// 使用缓存的正则表达式
|
|
53
|
+
const cacheKey = `${context.fenceChar}-${context.fenceLength}`
|
|
54
|
+
let pattern = fenceEndPatternCache.get(cacheKey)
|
|
55
|
+
if (!pattern) {
|
|
56
|
+
pattern = new RegExp(`^\\s{0,3}${context.fenceChar}{${context.fenceLength},}\\s*$`)
|
|
57
|
+
fenceEndPatternCache.set(cacheKey, pattern)
|
|
58
|
+
}
|
|
33
59
|
return pattern.test(line)
|
|
34
60
|
}
|
|
35
61
|
|
|
@@ -39,21 +65,21 @@ export function detectFenceEnd(line: string, context: BlockContext): boolean {
|
|
|
39
65
|
* 检测是否是空行或仅包含空白字符
|
|
40
66
|
*/
|
|
41
67
|
export function isEmptyLine(line: string): boolean {
|
|
42
|
-
return
|
|
68
|
+
return RE_EMPTY_LINE.test(line)
|
|
43
69
|
}
|
|
44
70
|
|
|
45
71
|
/**
|
|
46
72
|
* 检测是否是标题行
|
|
47
73
|
*/
|
|
48
74
|
export function isHeading(line: string): boolean {
|
|
49
|
-
return
|
|
75
|
+
return RE_HEADING.test(line)
|
|
50
76
|
}
|
|
51
77
|
|
|
52
78
|
/**
|
|
53
79
|
* 检测是否是 thematic break(水平线)
|
|
54
80
|
*/
|
|
55
81
|
export function isThematicBreak(line: string): boolean {
|
|
56
|
-
return
|
|
82
|
+
return RE_THEMATIC_BREAK.test(line.trim())
|
|
57
83
|
}
|
|
58
84
|
|
|
59
85
|
/**
|
|
@@ -61,13 +87,13 @@ export function isThematicBreak(line: string): boolean {
|
|
|
61
87
|
*/
|
|
62
88
|
export function isListItemStart(line: string): { ordered: boolean; indent: number } | null {
|
|
63
89
|
// 无序列表: - * +
|
|
64
|
-
const unordered = line.match(
|
|
90
|
+
const unordered = line.match(RE_UNORDERED_LIST)
|
|
65
91
|
if (unordered) {
|
|
66
92
|
return { ordered: false, indent: unordered[1].length }
|
|
67
93
|
}
|
|
68
94
|
|
|
69
95
|
// 有序列表: 1. 2) 等
|
|
70
|
-
const ordered = line.match(
|
|
96
|
+
const ordered = line.match(RE_ORDERED_LIST)
|
|
71
97
|
if (ordered) {
|
|
72
98
|
return { ordered: true, indent: ordered[1].length }
|
|
73
99
|
}
|
|
@@ -79,24 +105,21 @@ export function isListItemStart(line: string): { ordered: boolean; indent: numbe
|
|
|
79
105
|
* 检测是否是引用块开始
|
|
80
106
|
*/
|
|
81
107
|
export function isBlockquoteStart(line: string): boolean {
|
|
82
|
-
return
|
|
108
|
+
return RE_BLOCKQUOTE.test(line)
|
|
83
109
|
}
|
|
84
110
|
|
|
85
111
|
/**
|
|
86
112
|
* 检测是否是 HTML 块
|
|
87
113
|
*/
|
|
88
114
|
export function isHtmlBlock(line: string): boolean {
|
|
89
|
-
return (
|
|
90
|
-
/^\s{0,3}<(script|pre|style|textarea|!--|!DOCTYPE|\?|!\[CDATA\[)/i.test(line) ||
|
|
91
|
-
/^\s{0,3}<\/?[a-zA-Z][a-zA-Z0-9-]*(\s|>|$)/.test(line)
|
|
92
|
-
)
|
|
115
|
+
return RE_HTML_BLOCK_1.test(line) || RE_HTML_BLOCK_2.test(line)
|
|
93
116
|
}
|
|
94
117
|
|
|
95
118
|
/**
|
|
96
119
|
* 检测表格分隔行
|
|
97
120
|
*/
|
|
98
121
|
export function isTableDelimiter(line: string): boolean {
|
|
99
|
-
return
|
|
122
|
+
return RE_TABLE_DELIMITER.test(line.trim())
|
|
100
123
|
}
|
|
101
124
|
|
|
102
125
|
// ============ 容器检测 ============
|
|
@@ -114,10 +137,16 @@ export function detectContainer(line: string, config?: ContainerConfig): Contain
|
|
|
114
137
|
const marker = config?.marker || ':'
|
|
115
138
|
const minLength = config?.minMarkerLength || 3
|
|
116
139
|
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
)
|
|
140
|
+
// 使用缓存的正则表达式
|
|
141
|
+
const cacheKey = `${marker}-${minLength}`
|
|
142
|
+
let pattern = containerPatternCache.get(cacheKey)
|
|
143
|
+
if (!pattern) {
|
|
144
|
+
const escapedMarker = marker.replace(RE_ESCAPE_SPECIAL, '\\$&')
|
|
145
|
+
pattern = new RegExp(
|
|
146
|
+
`^(\\s*)(${escapedMarker}{${minLength},})(?:\\s+(\\w[\\w-]*))?(?:\\s+(.*))?\\s*$`
|
|
147
|
+
)
|
|
148
|
+
containerPatternCache.set(cacheKey, pattern)
|
|
149
|
+
}
|
|
121
150
|
|
|
122
151
|
const match = line.match(pattern)
|
|
123
152
|
if (!match) {
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type {
|
|
|
19
19
|
BlockContext,
|
|
20
20
|
ContainerMatch,
|
|
21
21
|
BlockTypeInfo,
|
|
22
|
+
AstNode,
|
|
22
23
|
Root,
|
|
23
24
|
RootContent
|
|
24
25
|
} from './types'
|
|
@@ -76,7 +77,9 @@ export type {
|
|
|
76
77
|
TransformerPlugin,
|
|
77
78
|
TransformerOptions,
|
|
78
79
|
TransformerState,
|
|
79
|
-
AnimationEffect
|
|
80
|
+
AnimationEffect,
|
|
81
|
+
TextChunk,
|
|
82
|
+
TextNodeWithChunks
|
|
80
83
|
} from './transformer'
|
|
81
84
|
|
|
82
85
|
/**
|