@incremark/core 0.2.4 → 0.2.6
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 +66 -10
- package/dist/detector/index.js.map +1 -1
- package/dist/{index-zDgyJFpf.d.ts → index-BMUkM7mT.d.ts} +18 -0
- package/dist/index.d.ts +30 -4
- package/dist/index.js +177 -75
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
- package/src/transformer/styles.css +0 -33
package/dist/detector/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { r as createInitialContext, o as detectContainer, p as detectContainerEnd, g as detectFenceEnd, f as detectFenceStart, q as isBlockBoundary, l as isBlockquoteStart, i as isEmptyLine, T as isFootnoteContinuation, S as isFootnoteDefinitionStart, h as isHeading, m as isHtmlBlock, k as isListItemStart, n as isTableDelimiter, j as isThematicBreak, u as updateContext } from '../index-
|
|
1
|
+
export { r as createInitialContext, o as detectContainer, p as detectContainerEnd, g as detectFenceEnd, f as detectFenceStart, q as isBlockBoundary, l as isBlockquoteStart, i as isEmptyLine, T as isFootnoteContinuation, S as isFootnoteDefinitionStart, h as isHeading, m as isHtmlBlock, k as isListItemStart, n as isTableDelimiter, j as isThematicBreak, u as updateContext } from '../index-BMUkM7mT.js';
|
|
2
2
|
import 'mdast';
|
|
3
3
|
import 'micromark-util-types';
|
|
4
4
|
import 'mdast-util-from-markdown';
|
package/dist/detector/index.js
CHANGED
|
@@ -3,14 +3,12 @@ var RE_FENCE_START = /^(\s*)((`{3,})|(~{3,}))/;
|
|
|
3
3
|
var RE_EMPTY_LINE = /^\s*$/;
|
|
4
4
|
var RE_HEADING = /^#{1,6}\s/;
|
|
5
5
|
var RE_THEMATIC_BREAK = /^(\*{3,}|-{3,}|_{3,})\s*$/;
|
|
6
|
-
var RE_UNORDERED_LIST = /^(\s*)([-*+])\s/;
|
|
7
|
-
var RE_ORDERED_LIST = /^(\s*)(\d{1,9})[.)]\s/;
|
|
8
6
|
var RE_BLOCKQUOTE = /^\s{0,3}>/;
|
|
9
7
|
var RE_HTML_BLOCK_1 = /^\s{0,3}<(script|pre|style|textarea|!--|!DOCTYPE|\?|!\[CDATA\[)/i;
|
|
10
8
|
var RE_HTML_BLOCK_2 = /^\s{0,3}<\/?[a-zA-Z][a-zA-Z0-9-]*(\s|>|$)/;
|
|
11
9
|
var RE_TABLE_DELIMITER = /^\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?$/;
|
|
12
10
|
var RE_ESCAPE_SPECIAL = /[.*+?^${}()|[\]\\]/g;
|
|
13
|
-
var RE_FOOTNOTE_DEFINITION = /^\[\^[^\]]
|
|
11
|
+
var RE_FOOTNOTE_DEFINITION = /^\[\^([^\]]+)\]:\s/;
|
|
14
12
|
var RE_FOOTNOTE_CONTINUATION = /^(?: |\t)/;
|
|
15
13
|
var fenceEndPatternCache = /* @__PURE__ */ new Map();
|
|
16
14
|
var containerPatternCache = /* @__PURE__ */ new Map();
|
|
@@ -45,13 +43,23 @@ function isThematicBreak(line) {
|
|
|
45
43
|
return RE_THEMATIC_BREAK.test(line.trim());
|
|
46
44
|
}
|
|
47
45
|
function isListItemStart(line) {
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
return
|
|
46
|
+
const hasListMarker = /^(\s*)([-*+]|\d{1,9}[.)])/.test(line);
|
|
47
|
+
if (!hasListMarker) {
|
|
48
|
+
return null;
|
|
51
49
|
}
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
|
|
50
|
+
const match = line.match(/^(\s*)([-*+]|\d{1,9}[.)])(.*)/);
|
|
51
|
+
if (match) {
|
|
52
|
+
const indent = match[1].length;
|
|
53
|
+
const marker = match[2];
|
|
54
|
+
const rest = match[3];
|
|
55
|
+
if (rest.trim()) {
|
|
56
|
+
const isOrdered = /^\d{1,9}[.)]/.test(marker);
|
|
57
|
+
return { ordered: isOrdered, indent };
|
|
58
|
+
}
|
|
59
|
+
if (/^\s+$/.test(rest)) {
|
|
60
|
+
const isOrdered = /^\d{1,9}[.)]/.test(marker);
|
|
61
|
+
return { ordered: isOrdered, indent };
|
|
62
|
+
}
|
|
55
63
|
}
|
|
56
64
|
return null;
|
|
57
65
|
}
|
|
@@ -131,7 +139,9 @@ function createInitialContext() {
|
|
|
131
139
|
blockquoteDepth: 0,
|
|
132
140
|
inContainer: false,
|
|
133
141
|
containerDepth: 0,
|
|
134
|
-
inList: false
|
|
142
|
+
inList: false,
|
|
143
|
+
inFootnote: false,
|
|
144
|
+
footnoteIdentifier: void 0
|
|
135
145
|
};
|
|
136
146
|
}
|
|
137
147
|
function isListContinuation(line, listIndent) {
|
|
@@ -187,6 +197,17 @@ function updateContext(line, context, containerConfig) {
|
|
|
187
197
|
}
|
|
188
198
|
}
|
|
189
199
|
}
|
|
200
|
+
if (context.inFootnote && isFootnoteDefinitionStart(line)) {
|
|
201
|
+
const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1];
|
|
202
|
+
newContext.footnoteIdentifier = identifier;
|
|
203
|
+
return newContext;
|
|
204
|
+
}
|
|
205
|
+
if (!context.inFootnote && isFootnoteDefinitionStart(line)) {
|
|
206
|
+
const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1];
|
|
207
|
+
newContext.inFootnote = true;
|
|
208
|
+
newContext.footnoteIdentifier = identifier;
|
|
209
|
+
return newContext;
|
|
210
|
+
}
|
|
190
211
|
const listItem = isListItemStart(line);
|
|
191
212
|
if (context.inList) {
|
|
192
213
|
if (context.listMayEnd) {
|
|
@@ -235,6 +256,41 @@ function updateContext(line, context, containerConfig) {
|
|
|
235
256
|
return newContext;
|
|
236
257
|
}
|
|
237
258
|
}
|
|
259
|
+
if (context.inFootnote) {
|
|
260
|
+
if (isEmptyLine(line)) {
|
|
261
|
+
return newContext;
|
|
262
|
+
} else if (isListItemStart(line)) {
|
|
263
|
+
const listItemInfo = isListItemStart(line);
|
|
264
|
+
if (listItemInfo.indent === 0) {
|
|
265
|
+
newContext.inFootnote = false;
|
|
266
|
+
newContext.footnoteIdentifier = void 0;
|
|
267
|
+
} else {
|
|
268
|
+
return newContext;
|
|
269
|
+
}
|
|
270
|
+
} else if (isHeading(line)) {
|
|
271
|
+
newContext.inFootnote = false;
|
|
272
|
+
newContext.footnoteIdentifier = void 0;
|
|
273
|
+
return newContext;
|
|
274
|
+
} else if (detectFenceStart(line)) {
|
|
275
|
+
newContext.inFootnote = false;
|
|
276
|
+
newContext.footnoteIdentifier = void 0;
|
|
277
|
+
return newContext;
|
|
278
|
+
} else if (isBlockquoteStart(line)) {
|
|
279
|
+
newContext.inFootnote = false;
|
|
280
|
+
newContext.footnoteIdentifier = void 0;
|
|
281
|
+
return newContext;
|
|
282
|
+
} else if (isFootnoteContinuation(line)) {
|
|
283
|
+
return newContext;
|
|
284
|
+
} else if (isFootnoteDefinitionStart(line)) {
|
|
285
|
+
const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1];
|
|
286
|
+
newContext.footnoteIdentifier = identifier;
|
|
287
|
+
return newContext;
|
|
288
|
+
} else {
|
|
289
|
+
newContext.inFootnote = false;
|
|
290
|
+
newContext.footnoteIdentifier = void 0;
|
|
291
|
+
return newContext;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
238
294
|
return newContext;
|
|
239
295
|
}
|
|
240
296
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/detector/index.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\nconst RE_FOOTNOTE_DEFINITION = /^\\[\\^[^\\]]+\\]:\\s/\nconst RE_FOOTNOTE_CONTINUATION = /^(?: |\\t)/\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 * 格式: [^id]: content\n * \n * @example\n * isFootnoteDefinitionStart('[^1]: 脚注内容') // true\n * isFootnoteDefinitionStart('[^note]: 内容') // true\n * isFootnoteDefinitionStart(' 缩进内容') // false\n */\nexport function isFootnoteDefinitionStart(line: string): boolean {\n return RE_FOOTNOTE_DEFINITION.test(line)\n}\n\n/**\n * 检测是否是脚注定义的延续行(缩进行)\n * 至少4个空格或1个tab\n * \n * @example\n * isFootnoteContinuation(' 第二行') // true\n * isFootnoteContinuation('\\t第二行') // true\n * isFootnoteContinuation(' 两个空格') // false\n */\nexport function isFootnoteContinuation(line: string): boolean {\n return RE_FOOTNOTE_CONTINUATION.test(line)\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 // 支持两种格式:\n // 1. ::: name attr (有空格分隔)\n // 2. :::name{...} (directive 语法,无空格)\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 inList: false\n }\n}\n\n/**\n * 检测是否是列表项的延续内容(缩进内容或空行)\n * @param line 当前行\n * @param listIndent 列表的基础缩进\n */\nfunction isListContinuation(line: string, listIndent: number): boolean {\n // 空行可能是列表内部的段落分隔\n if (isEmptyLine(line)) {\n return true\n }\n\n // 检查是否有足够的缩进(列表内容至少需要缩进到列表标记之后)\n // 通常列表标记后至少需要 2 个字符的缩进(如 \"1. \" 或 \"- \")\n const contentIndent = line.match(/^(\\s*)/)?.[1].length ?? 0\n return contentIndent > listIndent\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 // 检查是否是容器结束\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 // 检查是否是嵌套容器开始\n const nested = detectContainer(line, containerCfg)\n if (nested && !nested.isEnd) {\n newContext.containerDepth = context.containerDepth + 1\n return newContext\n }\n\n // ⚠️ 关键:在容器内,无论是什么内容(空行、列表、段落等),都保持 inContainer = true\n // 只有容器结束标记才能改变容器状态\n // 这里不需要做任何操作,因为 newContext 已经复制了 context,inContainer 已经是 true\n return newContext\n } else {\n // 不在容器内,检查是否是容器开始\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 // 列表处理\n const listItem = isListItemStart(line)\n\n if (context.inList) {\n // 已经在列表中\n if (context.listMayEnd) {\n // 上一行是空行,需要确认列表是否结束\n if (listItem) {\n // 遇到新的列表项\n // 检查是否是同类型列表的延续\n if (listItem.ordered === context.listOrdered && listItem.indent === context.listIndent) {\n // 同类型同级别列表项,列表继续\n newContext.listMayEnd = false\n return newContext\n }\n // 不同类型或不同级别,列表结束,新列表开始\n newContext.inList = true\n newContext.listOrdered = listItem.ordered\n newContext.listIndent = listItem.indent\n newContext.listMayEnd = false\n return newContext\n } else if (isListContinuation(line, context.listIndent ?? 0)) {\n // 缩进内容或空行,列表继续\n newContext.listMayEnd = isEmptyLine(line)\n return newContext\n } else {\n // 非列表内容,列表结束\n newContext.inList = false\n newContext.listOrdered = undefined\n newContext.listIndent = undefined\n newContext.listMayEnd = false\n return newContext\n }\n } else {\n // 上一行不是空行\n if (listItem) {\n // 新列表项(可能是同级或嵌套)\n return newContext\n } else if (isEmptyLine(line)) {\n // 遇到空行,列表可能结束\n newContext.listMayEnd = true\n return newContext\n } else if (isListContinuation(line, context.listIndent ?? 0)) {\n // 缩进内容,列表继续\n return newContext\n } else {\n // 非缩进非列表内容,列表结束\n newContext.inList = false\n newContext.listOrdered = undefined\n newContext.listIndent = undefined\n newContext.listMayEnd = false\n return newContext\n }\n }\n } else {\n // 不在列表中\n if (listItem) {\n // 列表开始\n newContext.inList = true\n newContext.listOrdered = listItem.ordered\n newContext.listIndent = listItem.indent\n newContext.listMayEnd = false\n return newContext\n }\n }\n\n return newContext\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/detector/index.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\nconst RE_FOOTNOTE_DEFINITION = /^\\[\\^([^\\]]+)\\]:\\s/\nconst RE_FOOTNOTE_CONTINUATION = /^(?: |\\t)/\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 *\n * CommonMark 规范:列表项可以是以下形式:\n * - `- text`(无缩进)\n * - `1. text`(有序列表)\n * - ` - text`(缩进4个空格,作为上一个列表项的延续)\n *\n * 注意:` - text` 这种形式,虽然 `-` 后面没有空格,\n * 但因为前面有4个空格的缩进,所以是列表项的有效形式。\n */\nexport function isListItemStart(line: string): { ordered: boolean; indent: number } | null {\n // 先检查是否以列表标记开头(-、*、+、数字)\n const hasListMarker = /^(\\s*)([-*+]|\\d{1,9}[.)])/.test(line)\n \n if (!hasListMarker) {\n return null\n }\n \n // 如果有列表标记,检查是否是列表项的延续(缩进4+个空格)\n const match = line.match(/^(\\s*)([-*+]|\\d{1,9}[.)])(.*)/)\n if (match) {\n const indent = match[1].length\n const marker = match[2]\n const rest = match[3]\n \n // 如果标记后有内容,检查是否是有效的列表项\n if (rest.trim()) {\n const isOrdered = /^\\d{1,9}[.)]/.test(marker)\n return { ordered: isOrdered, indent }\n }\n \n // 标记后只有空格,可能是缩进的列表项\n // 如 \" - text\" 或 \" 1. text\"\n if (/^\\s+$/.test(rest)) {\n const isOrdered = /^\\d{1,9}[.)]/.test(marker)\n return { ordered: isOrdered, indent }\n }\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 * 格式: [^id]: content\n * \n * @example\n * isFootnoteDefinitionStart('[^1]: 脚注内容') // true\n * isFootnoteDefinitionStart('[^note]: 内容') // true\n * isFootnoteDefinitionStart(' 缩进内容') // false\n */\nexport function isFootnoteDefinitionStart(line: string): boolean {\n return RE_FOOTNOTE_DEFINITION.test(line)\n}\n\n/**\n * 检测是否是脚注定义的延续行(缩进行)\n * 至少4个空格或1个tab\n * \n * @example\n * isFootnoteContinuation(' 第二行') // true\n * isFootnoteContinuation('\\t第二行') // true\n * isFootnoteContinuation(' 两个空格') // false\n */\nexport function isFootnoteContinuation(line: string): boolean {\n return RE_FOOTNOTE_CONTINUATION.test(line)\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 // 支持两种格式:\n // 1. ::: name attr (有空格分隔)\n // 2. :::name{...} (directive 语法,无空格)\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 inList: false,\n inFootnote: false,\n footnoteIdentifier: undefined\n }\n}\n\n/**\n * 检测是否是列表项的延续内容(缩进内容或空行)\n * @param line 当前行\n * @param listIndent 列表的基础缩进\n */\nfunction isListContinuation(line: string, listIndent: number): boolean {\n // 空行可能是列表内部的段落分隔\n if (isEmptyLine(line)) {\n return true\n }\n\n // 检查是否有足够的缩进(列表内容至少需要缩进到列表标记之后)\n // 通常列表标记后至少需要 2 个字符的缩进(如 \"1. \" 或 \"- \")\n const contentIndent = line.match(/^(\\s*)/)?.[1].length ?? 0\n return contentIndent > listIndent\n}\n\n/**\n * 更新代码块上下文\n */\nfunction updateCodeContext(line: string, context: BlockContext): BlockContext | null {\n const newContext = { ...context }\n\n if (context.inFencedCode) {\n if (detectFenceEnd(line, context)) {\n newContext.inFencedCode = false\n newContext.fenceChar = undefined\n newContext.fenceLength = undefined\n return newContext\n }\n return null\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 return null\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 // 检查是否是容器结束\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 // 检查是否是嵌套容器开始\n const nested = detectContainer(line, containerCfg)\n if (nested && !nested.isEnd) {\n newContext.containerDepth = context.containerDepth + 1\n return newContext\n }\n\n // ⚠️ 关键:在容器内,无论是什么内容(空行、列表、段落等),都保持 inContainer = true\n // 只有容器结束标记才能改变容器状态\n // 这里不需要做任何操作,因为 newContext 已经复制了 context,inContainer 已经是 true\n return newContext\n } else {\n // 不在容器内,检查是否是容器开始\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 // 脚注处理\n // 脚注定义会结束所有其他块(列表等),必须优先处理\n \n // 在脚注中,遇到新脚注定义:前一个脚注结束,新脚注开始\n if (context.inFootnote && isFootnoteDefinitionStart(line)) {\n const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1]\n newContext.footnoteIdentifier = identifier\n return newContext\n }\n \n // 不在脚注中,遇到脚注定义:脚注开始\n if (!context.inFootnote && isFootnoteDefinitionStart(line)) {\n const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1]\n newContext.inFootnote = true\n newContext.footnoteIdentifier = identifier\n return newContext\n }\n\n // 列表处理\n const listItem = isListItemStart(line)\n\n if (context.inList) {\n // 已经在列表中\n if (context.listMayEnd) {\n // 上一行是空行,需要确认列表是否结束\n if (listItem) {\n // 遇到新的列表项\n // 检查是否是同类型列表的延续\n if (listItem.ordered === context.listOrdered && listItem.indent === context.listIndent) {\n // 同类型同级别列表项,列表继续\n newContext.listMayEnd = false\n return newContext\n }\n // 不同类型或不同级别,列表结束,新列表开始\n newContext.inList = true\n newContext.listOrdered = listItem.ordered\n newContext.listIndent = listItem.indent\n newContext.listMayEnd = false\n return newContext\n } else if (isListContinuation(line, context.listIndent ?? 0)) {\n // 缩进内容或空行,列表继续\n newContext.listMayEnd = isEmptyLine(line)\n return newContext\n } else {\n // 非列表内容,列表结束\n newContext.inList = false\n newContext.listOrdered = undefined\n newContext.listIndent = undefined\n newContext.listMayEnd = false\n return newContext\n }\n } else {\n // 上一行不是空行\n if (listItem) {\n // 新列表项(可能是同级或嵌套)\n return newContext\n } else if (isEmptyLine(line)) {\n // 遇到空行,列表可能结束\n newContext.listMayEnd = true\n return newContext\n } else if (isListContinuation(line, context.listIndent ?? 0)) {\n // 缩进内容,列表继续\n return newContext\n } else {\n // 非缩进非列表内容,列表结束\n newContext.inList = false\n newContext.listOrdered = undefined\n newContext.listIndent = undefined\n newContext.listMayEnd = false\n return newContext\n }\n }\n } else {\n // 不在列表中\n if (listItem) {\n // 列表开始\n newContext.inList = true\n newContext.listOrdered = listItem.ordered\n newContext.listIndent = listItem.indent\n newContext.listMayEnd = false\n return newContext\n }\n }\n\n // 脚注处理\n if (context.inFootnote) {\n // 已经在脚注中\n if (isEmptyLine(line)) {\n // 空行可能结束脚注(但不立即结束,等待下一行判断)\n // 保持 inFootnote = true,这样可以处理脚注内部的多段落\n return newContext\n } else if (isListItemStart(line)) {\n // 列表项处理\n const listItemInfo = isListItemStart(line)!\n \n // 如果是无缩进的列表项(如 `- xxx`),则脚注结束\n // 如果是缩进的列表项(如 ` - xxx`),则是脚注的延续内容\n if (listItemInfo.indent === 0) {\n // 无缩进列表项:脚注结束,开始新列表\n newContext.inFootnote = false\n newContext.footnoteIdentifier = undefined\n // 继续处理列表项的逻辑(不在 else 分支,会继续执行列表处理)\n } else {\n // 缩进列表项:视为脚注的延续内容(可能包含嵌套列表)\n // 保持 inFootnote = true\n return newContext\n }\n } else if (isHeading(line)) {\n // 标题结束脚注\n newContext.inFootnote = false\n newContext.footnoteIdentifier = undefined\n return newContext\n } else if (detectFenceStart(line)) {\n // 代码块结束脚注\n newContext.inFootnote = false\n newContext.footnoteIdentifier = undefined\n return newContext\n } else if (isBlockquoteStart(line)) {\n // 引用块结束脚注\n newContext.inFootnote = false\n newContext.footnoteIdentifier = undefined\n return newContext\n } else if (isFootnoteContinuation(line)) {\n // 真正的脚注延续:以4+空格开头且不是列表项等\n return newContext\n } else if (isFootnoteDefinitionStart(line)) {\n // 新脚注开始,前一个脚注结束\n const identifier = line.match(RE_FOOTNOTE_DEFINITION)?.[1]\n newContext.footnoteIdentifier = identifier\n return newContext\n } else {\n // 其他内容(普通文本、表格等),脚注结束\n newContext.inFootnote = false\n newContext.footnoteIdentifier = undefined\n return newContext\n }\n }\n\n return newContext\n}\n\n"]}
|
|
@@ -228,6 +228,12 @@ interface ParserState {
|
|
|
228
228
|
interface ParserOptions {
|
|
229
229
|
/** 启用 GFM 扩展(表格、任务列表等) */
|
|
230
230
|
gfm?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* 启用数学公式支持($..$ 行内公式和 $$...$$ 块级公式)
|
|
233
|
+
* - false/undefined: 禁用(默认)
|
|
234
|
+
* - true: 启用数学公式解析
|
|
235
|
+
*/
|
|
236
|
+
math?: boolean;
|
|
231
237
|
/**
|
|
232
238
|
* 启用 ::: 容器语法支持(用于边界检测)
|
|
233
239
|
* - false: 禁用(默认)
|
|
@@ -281,6 +287,10 @@ interface BlockContext {
|
|
|
281
287
|
listIndent?: number;
|
|
282
288
|
/** 遇到空行后,列表可能结束(等待下一行确认) */
|
|
283
289
|
listMayEnd?: boolean;
|
|
290
|
+
/** 当前是否在脚注定义中 */
|
|
291
|
+
inFootnote?: boolean;
|
|
292
|
+
/** 脚注标识符 */
|
|
293
|
+
footnoteIdentifier?: string;
|
|
284
294
|
}
|
|
285
295
|
/**
|
|
286
296
|
* 容器检测结果
|
|
@@ -337,6 +347,14 @@ declare function isHeading(line: string): boolean;
|
|
|
337
347
|
declare function isThematicBreak(line: string): boolean;
|
|
338
348
|
/**
|
|
339
349
|
* 检测是否是列表项开始
|
|
350
|
+
*
|
|
351
|
+
* CommonMark 规范:列表项可以是以下形式:
|
|
352
|
+
* - `- text`(无缩进)
|
|
353
|
+
* - `1. text`(有序列表)
|
|
354
|
+
* - ` - text`(缩进4个空格,作为上一个列表项的延续)
|
|
355
|
+
*
|
|
356
|
+
* 注意:` - text` 这种形式,虽然 `-` 后面没有空格,
|
|
357
|
+
* 但因为前面有4个空格的缩进,所以是列表项的有效形式。
|
|
340
358
|
*/
|
|
341
359
|
declare function isListItemStart(line: string): {
|
|
342
360
|
ordered: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as ParserOptions, I as IncrementalUpdate, a as ParsedBlock, D as DefinitionMap, F as FootnoteDefinitionMap, b as ParserState, B as BlockStatus } from './index-
|
|
2
|
-
export { A as AstNode, c as BlockContext, e as BlockTypeInfo, C as ContainerConfig, d as ContainerMatch, J as HTML_ATTR_BLACKLIST, K as HTML_PROTOCOL_BLACKLIST, H as HTML_TAG_BLACKLIST, N as HtmlAttrInfo, R as HtmlContentType, M as HtmlElementNode, Q as HtmlTreeExtensionOptions, O as ParsedHtmlTag, s as createHtmlTreeTransformer, r as createInitialContext, o as detectContainer, p as detectContainerEnd, g as detectFenceEnd, f as detectFenceStart, x as detectHtmlContentType, E as findHtmlElementsByTag, G as htmlElementToString, L as htmlTreeExtension, q as isBlockBoundary, l as isBlockquoteStart, i as isEmptyLine, h as isHeading, m as isHtmlBlock, y as isHtmlElementNode, k as isListItemStart, n as isTableDelimiter, j as isThematicBreak, w as parseHtmlFragment, v as parseHtmlTag, t as transformHtmlNodes, u as updateContext, z as walkHtmlElements } from './index-
|
|
1
|
+
import { P as ParserOptions, I as IncrementalUpdate, a as ParsedBlock, D as DefinitionMap, F as FootnoteDefinitionMap, b as ParserState, B as BlockStatus } from './index-BMUkM7mT.js';
|
|
2
|
+
export { A as AstNode, c as BlockContext, e as BlockTypeInfo, C as ContainerConfig, d as ContainerMatch, J as HTML_ATTR_BLACKLIST, K as HTML_PROTOCOL_BLACKLIST, H as HTML_TAG_BLACKLIST, N as HtmlAttrInfo, R as HtmlContentType, M as HtmlElementNode, Q as HtmlTreeExtensionOptions, O as ParsedHtmlTag, s as createHtmlTreeTransformer, r as createInitialContext, o as detectContainer, p as detectContainerEnd, g as detectFenceEnd, f as detectFenceStart, x as detectHtmlContentType, E as findHtmlElementsByTag, G as htmlElementToString, L as htmlTreeExtension, q as isBlockBoundary, l as isBlockquoteStart, i as isEmptyLine, h as isHeading, m as isHtmlBlock, y as isHtmlElementNode, k as isListItemStart, n as isTableDelimiter, j as isThematicBreak, w as parseHtmlFragment, v as parseHtmlTag, t as transformHtmlNodes, u as updateContext, z as walkHtmlElements } from './index-BMUkM7mT.js';
|
|
3
3
|
import { Root, RootContent, Text } from 'mdast';
|
|
4
4
|
export { Root, RootContent } from 'mdast';
|
|
5
5
|
export { calculateLineOffset, generateId, joinLines, resetIdCounter, splitLines } from './utils/index.js';
|
|
@@ -40,7 +40,7 @@ declare class IncremarkParser {
|
|
|
40
40
|
*/
|
|
41
41
|
private convertHtmlToText;
|
|
42
42
|
private parse;
|
|
43
|
-
private
|
|
43
|
+
private updateDefinitionsFromCompletedBlocks;
|
|
44
44
|
private findDefinition;
|
|
45
45
|
private findFootnoteDefinition;
|
|
46
46
|
/**
|
|
@@ -94,7 +94,7 @@ declare class IncremarkParser {
|
|
|
94
94
|
finalize(): IncrementalUpdate;
|
|
95
95
|
/**
|
|
96
96
|
* 强制中断解析,将所有待处理内容标记为完成
|
|
97
|
-
*
|
|
97
|
+
* @deprecated 请使用 finalize() 代替,功能完全相同
|
|
98
98
|
*/
|
|
99
99
|
abort(): IncrementalUpdate;
|
|
100
100
|
/**
|
|
@@ -221,6 +221,11 @@ interface TransformerOptions {
|
|
|
221
221
|
plugins?: TransformerPlugin[];
|
|
222
222
|
/** 状态变化回调 */
|
|
223
223
|
onChange?: (displayBlocks: DisplayBlock[]) => void;
|
|
224
|
+
/**
|
|
225
|
+
* 所有动画完成时的回调
|
|
226
|
+
* 当队列中没有更多 block 需要处理时触发
|
|
227
|
+
*/
|
|
228
|
+
onAllComplete?: () => void;
|
|
224
229
|
/**
|
|
225
230
|
* 是否在页面不可见时自动暂停
|
|
226
231
|
* 默认 true,节省资源
|
|
@@ -350,6 +355,11 @@ declare class BlockTransformer<T = unknown> {
|
|
|
350
355
|
* 销毁,清理资源
|
|
351
356
|
*/
|
|
352
357
|
destroy(): void;
|
|
358
|
+
/**
|
|
359
|
+
* 处理 block 内容更新时的字符数变化和进度调整
|
|
360
|
+
* 统一 push 和 update 方法中的重复逻辑
|
|
361
|
+
*/
|
|
362
|
+
private handleContentChange;
|
|
353
363
|
private getAllBlockIds;
|
|
354
364
|
private setupVisibilityHandler;
|
|
355
365
|
private removeVisibilityHandler;
|
|
@@ -359,6 +369,16 @@ declare class BlockTransformer<T = unknown> {
|
|
|
359
369
|
private tick;
|
|
360
370
|
/**
|
|
361
371
|
* 从 AST 节点中提取指定范围的文本
|
|
372
|
+
*
|
|
373
|
+
* 优化说明:
|
|
374
|
+
* - 提前终止:当 charIndex >= end 时立即返回,避免不必要的遍历
|
|
375
|
+
* - 局部更新:charIndex 只在需要时更新,减少计算
|
|
376
|
+
* - 早期返回:发现足够的文本后可以提前退出(当前未实现,可作为未来优化)
|
|
377
|
+
*
|
|
378
|
+
* @param node 要提取文本的 AST 节点
|
|
379
|
+
* @param start 起始字符索引(包含)
|
|
380
|
+
* @param end 结束字符索引(不包含)
|
|
381
|
+
* @returns 提取的文本
|
|
362
382
|
*/
|
|
363
383
|
private extractText;
|
|
364
384
|
private getStep;
|
|
@@ -376,6 +396,11 @@ declare class BlockTransformer<T = unknown> {
|
|
|
376
396
|
private updateCachedDisplayNode;
|
|
377
397
|
/**
|
|
378
398
|
* 获取总字符数(带缓存)
|
|
399
|
+
*
|
|
400
|
+
* 缓存策略:
|
|
401
|
+
* - 首次调用时计算并缓存
|
|
402
|
+
* - 内容更新时通过 clearCache() 清除缓存,下次重新计算
|
|
403
|
+
* - 切换到新 block 时也会清除缓存
|
|
379
404
|
*/
|
|
380
405
|
private getTotalChars;
|
|
381
406
|
/**
|
|
@@ -384,6 +409,7 @@ declare class BlockTransformer<T = unknown> {
|
|
|
384
409
|
private clearCache;
|
|
385
410
|
/**
|
|
386
411
|
* 获取累积的 chunks(用于 fade-in 效果)
|
|
412
|
+
* stableChars 表示在 chunks 之前的稳定字符数
|
|
387
413
|
*/
|
|
388
414
|
private getAccumulatedChunks;
|
|
389
415
|
}
|