import { I as IncrementalUpdate, P as ParsedBlock, D as DefinitionMap, F as FootnoteDefinitionMap, a as ParserState, B as BlockStatus } from './index-CWuosVAK.js'; export { A as AstNode, M as MathOptions, b as ParserOptions } from './index-CWuosVAK.js'; import { E as EngineParserOptions, I as IAstBuilder } from './types-B7GTGJc2.js'; export { a as EngineType, b as IncremarkPlugin, M as MarkedEngineExtension, c as MicromarkEngineExtension } from './types-B7GTGJc2.js'; import { Root, RootContent, Text } from 'mdast'; export { Root, RootContent } from 'mdast'; export { M as MarkedAstBuilder } from './MarkedAstBuildter-B2QhLKKy.js'; export { collectFootnoteReferences, traverseAst } from './utils/index.js'; import 'micromark-util-types'; import 'mdast-util-from-markdown'; import 'marked'; /** * AST 构建器类型(用于注入) */ type AstBuilderClass = new (options: EngineParserOptions) => IAstBuilder; /** * 扩展的解析器选项(支持注入自定义 AstBuilder) */ interface IncremarkParserOptions extends EngineParserOptions { /** * 自定义 AST 构建器类 * * 用于注入不同的引擎实现,实现 tree-shaking * * @example * ```ts * // 使用 micromark 引擎 * import { MicromarkAstBuilder } from '@incremark/core/engines/micromark' * const parser = createIncremarkParser({ * astBuilder: MicromarkAstBuilder * }) * ``` */ astBuilder?: AstBuilderClass; } declare class IncremarkParser { private lines; /** 行偏移量前缀和:lineOffsets[i] = 第i行起始位置的偏移量 */ private lineOffsets; private completedBlocks; private pendingStartLine; private context; private options; /** 边界检测器 */ private readonly boundaryDetector; /** AST 构建器 */ private astBuilder; /** Definition 管理器 */ private readonly definitionManager; /** Footnote 管理器 */ private readonly footnoteManager; /** 上次 append 返回的 pending blocks,用于 getAst 复用 */ private lastPendingBlocks; constructor(options?: IncremarkParserOptions); /** * 生成 block 的 id(直接使用 offset) * @param startOffset - block 的起始偏移量 */ private generateBlockId; /** * 生成 pending block 的稳定 id(基于 startOffset) * pending blocks 在每次 append 时都会重新生成,使用 startOffset 确保 id 稳定 * @param startOffset - block 的起始偏移量,用作稳定的 id */ private generatePendingBlockId; /** * 更新已完成的 blocks 中的 definitions 和 footnote definitions */ private updateDefinitionsFromCompletedBlocks; /** * 增量更新 lines 和 lineOffsets * 优化策略:只 split 新增的 chunk,不拼接旧字符串,避免长行性能劣化 */ private updateLines; /** * O(1) 获取行偏移量 */ private getLineOffset; /** * 查找稳定边界 * 返回稳定边界行号和该行对应的上下文(用于后续更新,避免重复计算) */ private findStableBoundary; /** * 追加新的 chunk 并返回增量更新 */ append(chunk: string): IncrementalUpdate; /** * 触发状态变化回调 */ private emitChange; /** * 标记解析完成,处理剩余内容 * 也可用于强制中断时(如用户点击停止),将 pending 内容标记为 completed */ finalize(): IncrementalUpdate; /** * 强制中断解析,将所有待处理内容标记为完成 * @deprecated 请使用 finalize() 代替,功能完全相同 */ abort(): IncrementalUpdate; /** * 获取当前完整的 AST * 复用上次 append 的 pending 结果,避免重复解析 */ getAst(): Root; /** * 获取所有已完成的块 */ getCompletedBlocks(): ParsedBlock[]; /** * 获取当前缓冲区内容 */ getBuffer(): string; /** * 获取 Definition 映射表(用于引用式图片和链接) */ getDefinitionMap(): DefinitionMap; /** * 获取 Footnote Definition 映射表 */ getFootnoteDefinitionMap(): FootnoteDefinitionMap; /** * 获取脚注引用的出现顺序 */ getFootnoteReferenceOrder(): string[]; /** * 设置状态变化回调(用于 DevTools 等) */ setOnChange(callback: ((state: ParserState) => void) | undefined): void; /** * 重置解析器状态 */ reset(): void; /** * 一次性渲染完整 Markdown(reset + append + finalize) * @param content 完整的 Markdown 内容 * @returns 解析结果 */ render(content: string): IncrementalUpdate; /** * 更新解析器配置(动态更新,不需要重建 parser 实例) * * 注意:更新配置后会自动调用 reset() 重置状态 * * @param options 部分配置选项 * * @example * ```ts * // 动态启用 TeX 数学公式语法 * parser.updateOptions({ math: { tex: true } }) * * // 禁用 GFM * parser.updateOptions({ gfm: false }) * * // 切换引擎 * import { MicromarkAstBuilder } from '@incremark/core/engines/micromark' * parser.updateOptions({ astBuilder: MicromarkAstBuilder }) * ``` */ updateOptions(options: Partial): void; } /** * 创建 Incremark 解析器实例 * * @param options 解析器配置 * @param options.astBuilder 自定义 AST 构建器类(用于切换引擎) * @param options.plugins 统一插件列表 * * @example * ```ts * // 使用默认的 marked 引擎(极速模式) * const parser = createIncremarkParser({ gfm: true, math: true }) * * // 使用 micromark 引擎(需要单独导入,支持 tree-shaking) * import { MicromarkAstBuilder } from '@incremark/core/engines/micromark' * const parser = createIncremarkParser({ * astBuilder: MicromarkAstBuilder, * gfm: true * }) * ``` */ declare function createIncremarkParser(options?: IncremarkParserOptions): IncremarkParser; /** * 源 Block 类型(来自解析器) */ interface SourceBlock { /** 唯一标识 */ id: string; /** AST 节点 */ node: RootContent; /** 块状态 */ status: BlockStatus; /** 用户自定义元数据 */ meta?: T; } /** * 显示用的 Block(转换后) * * 注意:DisplayBlock 的 status 含义与 SourceBlock 不同: * - SourceBlock.status: 表示**解析器**的状态(解析是否完成) * - DisplayBlock.status: 表示**打字机动画**的状态(动画是否完成) * * 在打字机模式下: * - 即使解析器已完成(SourceBlock.status = 'completed'), * 如果打字机动画还在进行中,DisplayBlock.status 仍然是 'pending' * - 只有打字机动画完成后,DisplayBlock.status 才变成 'completed' */ interface DisplayBlock extends SourceBlock { /** 用于显示的 AST 节点(可能是截断的) */ displayNode: RootContent; /** 显示进度 0-1 */ progress: number; /** 是否已完成显示(打字机动画是否完成) */ isDisplayComplete: boolean; } /** * 动画效果类型 * - 'none': 无动画效果 * - 'fade-in': 新增字符渐入效果 * - 'typing': 打字机光标效果 */ type AnimationEffect = 'none' | 'fade-in' | 'typing'; /** * Transformer 插件 */ interface TransformerPlugin { /** 插件名称 */ name: string; /** * 判断是否处理此节点 * 返回 true 表示这个插件要处理此节点 */ match?: (node: RootContent) => boolean; /** * 自定义字符数计算 * 返回 undefined 则使用默认逻辑 * 返回 0 表示立即显示(不参与逐字符效果) */ countChars?: (node: RootContent) => number | undefined; /** * 自定义截断逻辑 * @param node 原始节点 * @param displayedChars 当前应显示的字符数 * @param totalChars 该节点的总字符数 * @returns 截断后的节点,null 表示不显示 */ sliceNode?: (node: RootContent, displayedChars: number, totalChars: number) => RootContent | null; /** * 节点显示完成时的回调 */ onComplete?: (node: RootContent) => void; } /** * Transformer 配置选项 */ interface TransformerOptions { /** * 每 tick 增加的字符数 * - number: 固定步长(默认 1) * - [min, max]: 随机步长区间(更自然的打字效果) */ charsPerTick?: number | [number, number]; /** tick 间隔 (ms),默认 20 */ tickInterval?: number; /** 动画效果,默认 'none' */ effect?: AnimationEffect; /** 插件列表 */ plugins?: TransformerPlugin[]; /** 状态变化回调 */ onChange?: (displayBlocks: DisplayBlock[]) => void; /** * 所有动画完成时的回调 * 当队列中没有更多 block 需要处理时触发 */ onAllComplete?: () => void; /** * 是否在页面不可见时自动暂停 * 默认 true,节省资源 */ pauseOnHidden?: boolean; } /** * Transformer 内部状态 */ interface TransformerState { /** 已完成显示的 blocks */ completedBlocks: SourceBlock[]; /** 当前正在显示的 block */ currentBlock: SourceBlock | null; /** 当前 block 已显示的字符数 */ currentProgress: number; /** 等待显示的 blocks */ pendingBlocks: SourceBlock[]; } /** * Block Transformer * * 用于控制 blocks 的逐步显示(打字机效果) * 作为解析器和渲染器之间的中间层 * * 特性: * - 使用 requestAnimationFrame 实现流畅动画 * - 支持随机步长,模拟真实打字效果 * - 支持 typing 动画效果 * - 页面不可见时自动暂停,节省资源 * - 插件系统支持自定义节点处理 * * @example * ```typescript * const transformer = new BlockTransformer({ * charsPerTick: [1, 3], // 随机 1-3 个字符 * tickInterval: 30, * effect: 'typing', * onChange: (displayBlocks) => { * // 更新 UI * } * }) * * // 推入新 blocks * transformer.push(blocks) * * // 获取当前显示状态 * const displayBlocks = transformer.getDisplayBlocks() * ``` */ declare class BlockTransformer { private state; private options; private rafId; private lastTickTime; private isRunning; private isPaused; private chunks; private visibilityHandler; /** 缓存的已截断 displayNode(稳定的部分,避免重复遍历) */ private cachedDisplayNode; /** 缓存的字符数(避免重复计算) */ private cachedTotalChars; /** 当前缓存的进度(对应 cachedDisplayNode) */ private cachedProgress; constructor(options?: TransformerOptions); /** * 推入新的 blocks * * 逻辑: * 1. 移除不在传入列表中的旧 blocks(处理容器增量解析等场景) * 2. 如果 block ID 不存在,添加到 pending * 3. 如果 block ID 已存在且内容变化,更新对应位置的 block */ push(blocks: SourceBlock[]): void; /** * 更新指定 block(用于 pending block 内容增加时) */ update(block: SourceBlock): void; /** * 跳过所有动画,直接显示全部内容 */ skip(): void; /** * 重置状态 */ reset(): void; /** * 暂停动画 */ pause(): void; /** * 恢复动画 */ resume(): void; /** * 获取用于渲染的 display blocks * 优化:使用缓存的 displayNode,避免重复遍历已稳定的节点 * * 注意:DisplayBlock 的 status 表示的是**打字机动画状态**,而不是解析器的状态: * - 'completed': 打字机动画已完成,内容已完全显示 * - 'pending': 打字机动画还在进行中,内容还在逐字显示 */ getDisplayBlocks(): DisplayBlock[]; /** * 是否正在处理中 */ isProcessing(): boolean; /** * 是否已暂停 */ isPausedState(): boolean; /** * 获取内部状态(用于调试) */ getState(): Readonly>; /** * 动态更新配置 */ setOptions(options: Partial>): void; /** * 获取当前配置 */ getOptions(): { charsPerTick: number | [number, number]; tickInterval: number; effect: AnimationEffect; }; /** * 获取当前动画效果 */ getEffect(): AnimationEffect; /** * 销毁,清理资源 */ destroy(): void; /** * 处理 block 内容更新时的字符数变化和进度调整 * 统一 push 和 update 方法中的重复逻辑 */ private handleContentChange; private getAllBlockIds; private setupVisibilityHandler; private removeVisibilityHandler; private startIfNeeded; private scheduleNextFrame; private animationFrame; private tick; /** * 从 AST 节点中提取指定范围的文本 * * 优化说明: * - 提前终止:当 charIndex >= end 时立即返回,避免不必要的遍历 * - 局部更新:charIndex 只在需要时更新,减少计算 * - 早期返回:发现足够的文本后可以提前退出(当前未实现,可作为未来优化) * * @param node 要提取文本的 AST 节点 * @param start 起始字符索引(包含) * @param end 结束字符索引(不包含) * @returns 提取的文本 */ private extractText; private getStep; private processNext; private cancelRaf; private stop; private emit; private countChars; private sliceNode; private notifyComplete; /** * 更新缓存的 displayNode * 使用真正的增量追加模式:只处理新增部分,不重复遍历已稳定的节点 */ private updateCachedDisplayNode; /** * 获取总字符数(带缓存) * * 缓存策略: * - 首次调用时计算并缓存 * - 内容更新时通过 clearCache() 清除缓存,下次重新计算 * - 切换到新 block 时也会清除缓存 */ private getTotalChars; /** * 清除缓存(当 block 切换或内容更新时) */ private clearCache; /** * 获取累积的 chunks(用于 fade-in 效果) * stableChars 表示在 chunks 之前的稳定字符数 */ private getAccumulatedChunks; } /** * 创建 BlockTransformer 实例的工厂函数 */ declare function createBlockTransformer(options?: TransformerOptions): BlockTransformer; /** * 文本块片段(用于渐入动画) */ interface TextChunk { /** 文本内容 */ text: string; /** 创建时间戳 */ createdAt: number; } /** * 扩展的文本节点(支持 chunks) */ interface TextNodeWithChunks extends Text { /** 稳定部分的长度(不需要动画) */ stableLength?: number; /** 临时的文本片段,用于渐入动画 */ chunks?: TextChunk[]; } /** * 计算 AST 节点的总字符数 */ declare function countChars(node: RootContent): number; /** * 累积的 chunks 信息 */ interface AccumulatedChunks { /** 已经稳定显示的字符数(不需要动画) */ stableChars: number; /** 累积的 chunk 列表 */ chunks: TextChunk[]; } /** * 截断 AST 节点,只保留前 maxChars 个字符 * 支持 chunks(用于渐入动画) * * 性能说明: * - 此函数每次调用都会从头遍历 AST 节点 * - 但由于 BlockTransformer 是按 block 处理的,每次只遍历单个 block 的 AST * - 单个 block(如一个段落、一个代码块)通常只有几百个字符,性能开销很小 * - 对于整个文档的渲染,已完成的 blocks 不会重新遍历 * * @param node 原始节点(单个 block 的 AST) * @param maxChars 最大字符数 * @param accumulatedChunks 累积的 chunks 信息(用于渐入动画) * @returns 截断后的节点,如果 maxChars <= 0 返回 null */ declare function sliceAst(node: RootContent, maxChars: number, accumulatedChunks?: AccumulatedChunks): RootContent | null; /** * 深拷贝 AST 节点 * 使用递归浅拷贝实现,比 JSON.parse/stringify 更高效 * 且保持对象结构完整性 */ declare function cloneNode(node: T): T; /** * 代码块插件:整体出现,不逐字符显示 * * 注意:默认不启用,代码块默认参与打字机效果 * 如需整体显示代码块,可手动添加此插件 */ declare const codeBlockPlugin: TransformerPlugin; /** * Mermaid 图表插件:整体出现 * * 注意:默认不启用,mermaid 默认参与打字机效果 * 如需整体显示 mermaid,可手动添加此插件 */ declare const mermaidPlugin: TransformerPlugin; /** * 图片插件:立即显示(不参与打字机效果) * 图片没有文本内容,应立即显示 */ declare const imagePlugin: TransformerPlugin; /** * 数学公式插件:整体出现 * * 注意:默认不启用,数学公式默认参与打字机效果 * 如需整体显示公式,可手动添加此插件 */ declare const mathPlugin: TransformerPlugin; /** * 分割线插件:立即显示 * 分隔线没有文本内容,应立即显示 */ declare const thematicBreakPlugin: TransformerPlugin; /** * 默认插件集合 * * 只包含确实需要特殊处理的节点: * - 图片:无文本内容,立即显示 * - 分隔线:无文本内容,立即显示 * * 代码块、mermaid、数学公式默认参与打字机效果 * 如需整体显示,可手动添加对应插件 */ declare const defaultPlugins: TransformerPlugin[]; /** * 完整插件集合(所有特殊节点整体显示) * 包含代码块、mermaid、数学公式等的整体显示 */ declare const allPlugins: TransformerPlugin[]; /** * 创建自定义插件的辅助函数 */ declare function createPlugin(name: string, matcher: (node: RootContent) => boolean, options?: Partial>): TransformerPlugin; export { type AnimationEffect, type AstBuilderClass, BlockStatus, BlockTransformer, type DisplayBlock, EngineParserOptions, IAstBuilder, IncremarkParser, type IncremarkParserOptions, IncrementalUpdate, ParsedBlock, ParserState, type SourceBlock, type TextChunk, type TextNodeWithChunks, type TransformerOptions, type TransformerPlugin, type TransformerState, allPlugins, cloneNode, codeBlockPlugin, countChars, createBlockTransformer, createIncremarkParser, createPlugin, defaultPlugins, imagePlugin, mathPlugin, mermaidPlugin, sliceAst, thematicBreakPlugin };