@ai-markdown/core 3.2.1 → 3.3.0
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/LICENSE +72 -0
- package/components/package.json +8 -0
- package/dist/components/index.cjs +555 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.d.cts +233 -0
- package/dist/components/index.d.ts +233 -0
- package/dist/components/index.js +528 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.cjs +932 -979
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +260 -326
- package/dist/index.d.ts +260 -326
- package/dist/index.dev.cjs +929 -979
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +907 -944
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +910 -944
- package/dist/index.js.map +1 -1
- package/package.json +21 -5
package/dist/index.dev.js
CHANGED
|
@@ -1,990 +1,953 @@
|
|
|
1
|
-
// src/blockPlan.ts
|
|
2
1
|
import { SKIP, visit } from "unist-util-visit";
|
|
3
|
-
import { isFootnoteSection, normalizeId } from "@ai-markdown/engine";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import { EngineRawHtmlDepthError, advanceIncrementalParse, buildCrossChunkHandlers, buildPhantomSuffix, extractContributions, extractDefBodiesFromHast, footnoteSafeId, isFootnoteSection, lastMeaningfulIdx, normalizeForMatch, normalizeId, parseStage, phantomSuffixCloser, transformStage } from "@ai-markdown/engine";
|
|
3
|
+
const TAINT_TYPES = /* @__PURE__ */ new Set([
|
|
4
|
+
"footnoteReference",
|
|
5
|
+
"footnoteDefinition",
|
|
6
|
+
"linkReference",
|
|
7
|
+
"imageReference",
|
|
8
|
+
"definition"
|
|
10
9
|
]);
|
|
11
|
-
|
|
10
|
+
const CTX_TYPES = TAINT_TYPES;
|
|
12
11
|
function extractRaw(node, source) {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
if (!node.position) return "";
|
|
13
|
+
return source.slice(node.position.start.offset, node.position.end.offset);
|
|
15
14
|
}
|
|
16
15
|
function hasMdastSource(node) {
|
|
17
|
-
|
|
16
|
+
return node.position !== void 0;
|
|
18
17
|
}
|
|
19
18
|
function computeHtmlBlockDigest(el, source, ownEnd) {
|
|
20
|
-
|
|
19
|
+
return computeHtmlBlockDigestWithExtent(el, source, ownEnd).digest;
|
|
21
20
|
}
|
|
22
21
|
function computeHtmlBlockDigestWithExtent(el, source, ownEnd) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
const swallowed = source !== void 0 && ownEnd !== void 0 && maxEnd > ownEnd ? source.slice(ownEnd, maxEnd) : "";
|
|
44
|
-
return { digest: `${maxEnd}:${count}:${hasFootnoteSection ? 1 : 0}:${fnv1a(swallowed)}`, maxEnd };
|
|
22
|
+
let maxEnd = el.position?.end?.offset ?? 0;
|
|
23
|
+
let count = 0;
|
|
24
|
+
let hasFootnoteSection = false;
|
|
25
|
+
const stack = [...el.children];
|
|
26
|
+
while (stack.length > 0) {
|
|
27
|
+
const node = stack.pop();
|
|
28
|
+
count++;
|
|
29
|
+
const end = node.position?.end?.offset;
|
|
30
|
+
if (end !== void 0 && end > maxEnd) maxEnd = end;
|
|
31
|
+
if (node.type === "element") {
|
|
32
|
+
if (isFootnoteSection(node)) hasFootnoteSection = true;
|
|
33
|
+
for (const child of node.children) stack.push(child);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const swallowed = source !== void 0 && ownEnd !== void 0 && maxEnd > ownEnd ? source.slice(ownEnd, maxEnd) : "";
|
|
37
|
+
return {
|
|
38
|
+
digest: `${maxEnd}:${count}:${hasFootnoteSection ? 1 : 0}:${fnv1a(swallowed)}`,
|
|
39
|
+
maxEnd
|
|
40
|
+
};
|
|
45
41
|
}
|
|
46
42
|
function fnv1a(text) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
43
|
+
let h = 2166136261;
|
|
44
|
+
for (let i = 0; i < text.length; i++) {
|
|
45
|
+
h ^= text.charCodeAt(i);
|
|
46
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
47
|
+
}
|
|
48
|
+
return h.toString(36);
|
|
53
49
|
}
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
const EMPTY_LABELS = /* @__PURE__ */ new Set();
|
|
51
|
+
const FOOTNOTE_SECTION_KEY = "__footnote_section__";
|
|
56
52
|
function buildBlocks(mdast, hast, source, options = {}) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
53
|
+
const phantomFootnotes = options.phantomFootnoteLabels ?? EMPTY_LABELS;
|
|
54
|
+
const mdastByOffset = /* @__PURE__ */ new Map();
|
|
55
|
+
const mdastRanges = [];
|
|
56
|
+
for (const child of mdast.children) {
|
|
57
|
+
const off = child.position?.start.offset;
|
|
58
|
+
const endOff = child.position?.end.offset;
|
|
59
|
+
if (off !== void 0) mdastByOffset.set(off, child);
|
|
60
|
+
if (off !== void 0 && endOff !== void 0) mdastRanges.push({
|
|
61
|
+
start: off,
|
|
62
|
+
end: endOff,
|
|
63
|
+
node: child
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
for (let i = 1; i < mdastRanges.length; i++) if (mdastRanges[i].start < mdastRanges[i - 1].start) throw new Error("block-memo: mdast.children not sorted by source offset — a remark plugin is reordering top-level children.");
|
|
67
|
+
function findContainingMdast(offset) {
|
|
68
|
+
let lo = 0;
|
|
69
|
+
let hi = mdastRanges.length;
|
|
70
|
+
while (lo < hi) {
|
|
71
|
+
const mid = lo + hi >>> 1;
|
|
72
|
+
if (mdastRanges[mid].start <= offset) lo = mid + 1;
|
|
73
|
+
else hi = mid;
|
|
74
|
+
}
|
|
75
|
+
const idx = lo - 1;
|
|
76
|
+
if (idx < 0) return void 0;
|
|
77
|
+
const r = mdastRanges[idx];
|
|
78
|
+
return offset < r.end ? r.node : void 0;
|
|
79
|
+
}
|
|
80
|
+
const ctxParts = [];
|
|
81
|
+
const taintOffsets = [];
|
|
82
|
+
const firstTaintAtOrAfter = (offset) => {
|
|
83
|
+
let lo = 0;
|
|
84
|
+
let hi = taintOffsets.length;
|
|
85
|
+
while (lo < hi) {
|
|
86
|
+
const mid = lo + hi >>> 1;
|
|
87
|
+
if (taintOffsets[mid] < offset) lo = mid + 1;
|
|
88
|
+
else hi = mid;
|
|
89
|
+
}
|
|
90
|
+
return lo;
|
|
91
|
+
};
|
|
92
|
+
visit(options.contextMdast ?? mdast, (n) => {
|
|
93
|
+
if (!CTX_TYPES.has(n.type)) return;
|
|
94
|
+
const at = n.position?.start?.offset;
|
|
95
|
+
if (at !== void 0) taintOffsets.push(at);
|
|
96
|
+
if (n.type === "footnoteReference") ctxParts.push(["fr", n.identifier]);
|
|
97
|
+
else if (n.type === "footnoteDefinition") ctxParts.push([
|
|
98
|
+
"fd",
|
|
99
|
+
n.identifier,
|
|
100
|
+
extractRaw(n, source)
|
|
101
|
+
]);
|
|
102
|
+
else if (n.type === "linkReference") ctxParts.push(["lr", n.identifier]);
|
|
103
|
+
else if (n.type === "imageReference") ctxParts.push(["ir", n.identifier]);
|
|
104
|
+
else if (n.type === "definition") ctxParts.push([
|
|
105
|
+
"d",
|
|
106
|
+
n.identifier,
|
|
107
|
+
n.url,
|
|
108
|
+
n.title ?? null
|
|
109
|
+
]);
|
|
110
|
+
});
|
|
111
|
+
for (let i = 1; i < taintOffsets.length; i++) if (taintOffsets[i] < taintOffsets[i - 1]) throw new Error("block-memo: taint node start offsets are not source-ordered — a remark plugin is reordering nodes or emitting bad positions.");
|
|
112
|
+
const globalCtx = JSON.stringify(ctxParts);
|
|
113
|
+
const plan = [];
|
|
114
|
+
const blocks = [];
|
|
115
|
+
const blockHasts = [];
|
|
116
|
+
let synthetic;
|
|
117
|
+
const refLocalCtx = /* @__PURE__ */ new Map();
|
|
118
|
+
{
|
|
119
|
+
const counts = /* @__PURE__ */ new Map();
|
|
120
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
121
|
+
const rankOf = (id) => {
|
|
122
|
+
if (phantomFootnotes.has(id)) return -1;
|
|
123
|
+
let rank = ranks.get(id);
|
|
124
|
+
if (rank === void 0) {
|
|
125
|
+
rank = ranks.size;
|
|
126
|
+
ranks.set(id, rank);
|
|
127
|
+
}
|
|
128
|
+
return rank;
|
|
129
|
+
};
|
|
130
|
+
visit(options.contextMdast ?? mdast, (n) => {
|
|
131
|
+
if (n.type === "footnoteDefinition") {
|
|
132
|
+
rankOf(normalizeId(String(n.identifier)));
|
|
133
|
+
return SKIP;
|
|
134
|
+
}
|
|
135
|
+
if (n.type !== "footnoteReference") return;
|
|
136
|
+
const id = normalizeId(String(n.identifier));
|
|
137
|
+
const prior = counts.get(id) ?? 0;
|
|
138
|
+
refLocalCtx.set(n, [prior, rankOf(id)]);
|
|
139
|
+
counts.set(id, prior + 1);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
for (let i = 0; i < hast.children.length; i++) {
|
|
143
|
+
const hastChild = hast.children[i];
|
|
144
|
+
if (hastChild.type !== "element") {
|
|
145
|
+
const off = hastChild.position?.start.offset;
|
|
146
|
+
const key = off !== void 0 ? `inline-${off}` : `inline-i${i}`;
|
|
147
|
+
plan.push({
|
|
148
|
+
kind: "inline",
|
|
149
|
+
el: hastChild,
|
|
150
|
+
key
|
|
151
|
+
});
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const el = hastChild;
|
|
155
|
+
if (isFootnoteSection(el)) {
|
|
156
|
+
synthetic = el;
|
|
157
|
+
plan.push({
|
|
158
|
+
kind: "synthetic",
|
|
159
|
+
el,
|
|
160
|
+
key: FOOTNOTE_SECTION_KEY
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const hastOffset = el.position?.start.offset;
|
|
165
|
+
if (hastOffset === void 0) {
|
|
166
|
+
plan.push({
|
|
167
|
+
kind: "inline",
|
|
168
|
+
el,
|
|
169
|
+
key: `inline-i${i}`
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
let mdastNode = mdastByOffset.get(hastOffset);
|
|
174
|
+
let viaRangeFallback = false;
|
|
175
|
+
if (!mdastNode) {
|
|
176
|
+
mdastNode = findContainingMdast(hastOffset);
|
|
177
|
+
viaRangeFallback = mdastNode !== void 0;
|
|
178
|
+
}
|
|
179
|
+
if (!mdastNode) throw new Error(`block-memo: hast block at offset ${hastOffset} has no mdast counterpart. A rehype plugin may have synthesized positions outside source. tagName=${el.tagName}`);
|
|
180
|
+
if (mdastNode.type === "footnoteDefinition") {
|
|
181
|
+
plan.push({
|
|
182
|
+
kind: "inline",
|
|
183
|
+
el,
|
|
184
|
+
key: `inline-${hastOffset}`
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const isRawHtmlBlock = mdastNode.type === "html" || viaRangeFallback;
|
|
189
|
+
let hasReference = false;
|
|
190
|
+
const swallowed = isRawHtmlBlock ? scanSwallowedSubtree(el) : null;
|
|
191
|
+
const footnoteRefLabels = [];
|
|
192
|
+
const linkRefLabels = [];
|
|
193
|
+
const imageRefLabels = [];
|
|
194
|
+
const footnoteDefLabels = [];
|
|
195
|
+
const local = [];
|
|
196
|
+
visit(mdastNode, (n) => {
|
|
197
|
+
if (!TAINT_TYPES.has(n.type)) return;
|
|
198
|
+
hasReference = true;
|
|
199
|
+
const id = "identifier" in n ? normalizeId(String(n.identifier)) : null;
|
|
200
|
+
if (id === null) return;
|
|
201
|
+
if (n.type === "footnoteReference") {
|
|
202
|
+
footnoteRefLabels.push(id);
|
|
203
|
+
const ctx = refLocalCtx.get(n);
|
|
204
|
+
if (ctx) local.push([
|
|
205
|
+
id,
|
|
206
|
+
ctx[0],
|
|
207
|
+
ctx[1]
|
|
208
|
+
]);
|
|
209
|
+
} else if (n.type === "linkReference") linkRefLabels.push(id);
|
|
210
|
+
else if (n.type === "imageReference") imageRefLabels.push(id);
|
|
211
|
+
else if (n.type === "footnoteDefinition") footnoteDefLabels.push(id);
|
|
212
|
+
});
|
|
213
|
+
if (swallowed !== null && swallowed.hasReference) {
|
|
214
|
+
hasReference = true;
|
|
215
|
+
footnoteRefLabels.push(...swallowed.refLabels);
|
|
216
|
+
linkRefLabels.push(...swallowed.linkLabels);
|
|
217
|
+
imageRefLabels.push(...swallowed.imageLabels);
|
|
218
|
+
local.push(...swallowed.local);
|
|
219
|
+
}
|
|
220
|
+
const footnoteRefLocalCtx = local.length > 0 ? JSON.stringify(local) : void 0;
|
|
221
|
+
const swallowedDefCtx = swallowed !== null && swallowed.bakedDefs.length > 0 ? JSON.stringify(swallowed.bakedDefs) : void 0;
|
|
222
|
+
const mdastPos = mdastNode.position;
|
|
223
|
+
if (!mdastPos || mdastPos.start?.offset === void 0 || mdastPos.end?.offset === void 0) {
|
|
224
|
+
plan.push({
|
|
225
|
+
kind: "inline",
|
|
226
|
+
el,
|
|
227
|
+
key: `inline-${hastOffset}`
|
|
228
|
+
});
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
let hastDigest;
|
|
232
|
+
let swallowedSource;
|
|
233
|
+
let swallowedTaint = false;
|
|
234
|
+
if (isRawHtmlBlock) {
|
|
235
|
+
const d = computeHtmlBlockDigestWithExtent(el, source, mdastPos.end.offset);
|
|
236
|
+
hastDigest = d.digest;
|
|
237
|
+
swallowedSource = source.slice(mdastPos.end.offset, d.maxEnd);
|
|
238
|
+
const first = firstTaintAtOrAfter(mdastPos.end.offset);
|
|
239
|
+
swallowedTaint = first < taintOffsets.length && taintOffsets[first] < d.maxEnd;
|
|
240
|
+
}
|
|
241
|
+
if (swallowedTaint) hasReference = true;
|
|
242
|
+
const info = {
|
|
243
|
+
raw: extractRaw(mdastNode, source),
|
|
244
|
+
startOffset: mdastPos.start.offset,
|
|
245
|
+
endOffset: mdastPos.end.offset,
|
|
246
|
+
startLine: mdastPos.start.line,
|
|
247
|
+
startColumn: mdastPos.start.column,
|
|
248
|
+
hasReference,
|
|
249
|
+
...hastDigest !== void 0 ? { hastDigest } : {},
|
|
250
|
+
...swallowedSource !== void 0 ? { swallowedSource } : {},
|
|
251
|
+
...swallowed?.hasFootnoteSection ? { containsFootnoteSection: true } : {},
|
|
252
|
+
...hasReference ? { taintLabels: {
|
|
253
|
+
footnoteRefLabels,
|
|
254
|
+
linkRefLabels,
|
|
255
|
+
imageRefLabels,
|
|
256
|
+
footnoteDefLabels,
|
|
257
|
+
...footnoteRefLocalCtx !== void 0 ? { footnoteRefLocalCtx } : {},
|
|
258
|
+
...swallowedDefCtx !== void 0 ? { swallowedDefCtx } : {}
|
|
259
|
+
} } : {}
|
|
260
|
+
};
|
|
261
|
+
blocks.push(info);
|
|
262
|
+
blockHasts.push(el);
|
|
263
|
+
plan.push({
|
|
264
|
+
kind: "block",
|
|
265
|
+
el,
|
|
266
|
+
info,
|
|
267
|
+
key: `block-${hastOffset}`
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
plan,
|
|
272
|
+
globalCtx,
|
|
273
|
+
blocks,
|
|
274
|
+
blockHasts,
|
|
275
|
+
synthetic
|
|
276
|
+
};
|
|
263
277
|
}
|
|
264
278
|
function computeBlockFingerprint(taintLabels, registry, thisChunkSym, clobberPrefix) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
return parts.join("|");
|
|
279
|
+
const parts = [clobberPrefix];
|
|
280
|
+
for (const label of taintLabels.footnoteRefLabels) parts.push(`fn:${label}=${registry.globalNumber(label) ?? "null"}`);
|
|
281
|
+
if (taintLabels.footnoteRefLocalCtx !== void 0) parts.push(`fl:${taintLabels.footnoteRefLocalCtx}`);
|
|
282
|
+
if (taintLabels.swallowedDefCtx !== void 0) parts.push(`sd:${taintLabels.swallowedDefCtx}`);
|
|
283
|
+
for (const label of taintLabels.linkRefLabels) {
|
|
284
|
+
const def = registry.resolveLinkDef(label);
|
|
285
|
+
parts.push(`lr:${label}=${def ? JSON.stringify([def.url, def.title ?? null]) : "null"}`);
|
|
286
|
+
}
|
|
287
|
+
for (const label of taintLabels.imageRefLabels) {
|
|
288
|
+
const def = registry.resolveLinkDef(label);
|
|
289
|
+
parts.push(`ir:${label}=${def ? JSON.stringify([def.url, def.title ?? null]) : "null"}`);
|
|
290
|
+
}
|
|
291
|
+
for (const label of taintLabels.footnoteDefLabels) {
|
|
292
|
+
const isCanonical = registry.canonicalFootnoteFor(label) === thisChunkSym ? 1 : 0;
|
|
293
|
+
parts.push(`fd:${label}=${isCanonical}/${registry.getRefsForLabel(label)}`);
|
|
294
|
+
}
|
|
295
|
+
return parts.join("|");
|
|
284
296
|
}
|
|
285
|
-
|
|
297
|
+
const PLACEHOLDER_TAGS = /* @__PURE__ */ new Set([
|
|
298
|
+
"footnote-sup",
|
|
299
|
+
"cross-chunk-link",
|
|
300
|
+
"cross-chunk-image"
|
|
301
|
+
]);
|
|
286
302
|
function scanSwallowedSubtree(el) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
303
|
+
const refLabels = [];
|
|
304
|
+
const linkLabels = [];
|
|
305
|
+
const imageLabels = [];
|
|
306
|
+
const local = [];
|
|
307
|
+
const bakedDefs = [];
|
|
308
|
+
let hasReference = false;
|
|
309
|
+
let hasFootnoteSection = false;
|
|
310
|
+
visit(el, "element", (node) => {
|
|
311
|
+
if (isFootnoteSection(node)) {
|
|
312
|
+
hasFootnoteSection = true;
|
|
313
|
+
hasReference = true;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const props = node.properties ?? {};
|
|
317
|
+
if (PLACEHOLDER_TAGS.has(node.tagName)) {
|
|
318
|
+
hasReference = true;
|
|
319
|
+
const identifier = props.identifier ?? props.label;
|
|
320
|
+
const label = identifier === void 0 ? null : normalizeId(String(identifier));
|
|
321
|
+
if (label === null) return;
|
|
322
|
+
if (node.tagName === "footnote-sup") {
|
|
323
|
+
refLabels.push(label);
|
|
324
|
+
const occ = Number(props.localOccurrence);
|
|
325
|
+
const num = Number(props.localNumber);
|
|
326
|
+
local.push([
|
|
327
|
+
label,
|
|
328
|
+
Number.isFinite(occ) ? occ : -1,
|
|
329
|
+
Number.isFinite(num) ? num : -1
|
|
330
|
+
]);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (node.tagName === "cross-chunk-link") linkLabels.push(label);
|
|
334
|
+
else imageLabels.push(label);
|
|
335
|
+
if (typeof props.localUrl === "string") bakedDefs.push([
|
|
336
|
+
label,
|
|
337
|
+
props.localUrl,
|
|
338
|
+
typeof props.localTitle === "string" ? props.localTitle : null
|
|
339
|
+
]);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (node.tagName === "a" && props.dataFootnoteRef !== void 0) hasReference = true;
|
|
343
|
+
});
|
|
344
|
+
return {
|
|
345
|
+
hasReference,
|
|
346
|
+
refLabels,
|
|
347
|
+
linkLabels,
|
|
348
|
+
imageLabels,
|
|
349
|
+
local,
|
|
350
|
+
bakedDefs,
|
|
351
|
+
hasFootnoteSection
|
|
352
|
+
};
|
|
323
353
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
354
|
+
const UNPAIRED_TYPES = /* @__PURE__ */ new Set([
|
|
355
|
+
"html",
|
|
356
|
+
"definition",
|
|
357
|
+
"footnoteDefinition"
|
|
358
|
+
]);
|
|
328
359
|
function createBlockPlanner() {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
360
|
+
let previous;
|
|
361
|
+
const eligible = /* @__PURE__ */ new WeakMap();
|
|
362
|
+
const isEligible = (node) => {
|
|
363
|
+
let result = eligible.get(node);
|
|
364
|
+
if (result === void 0) {
|
|
365
|
+
result = true;
|
|
366
|
+
visit(node, (child) => {
|
|
367
|
+
if (UNPAIRED_TYPES.has(child.type)) result = false;
|
|
368
|
+
});
|
|
369
|
+
eligible.set(node, result);
|
|
370
|
+
}
|
|
371
|
+
return result;
|
|
372
|
+
};
|
|
373
|
+
return (mdast, hast, source, options = {}) => {
|
|
374
|
+
let m = 0;
|
|
375
|
+
let h = 0;
|
|
376
|
+
let reusedContext = false;
|
|
377
|
+
if (previous && source.startsWith(previous.source) && options.phantomFootnoteLabels === previous.phantoms) {
|
|
378
|
+
const prevHast = previous.hast.children;
|
|
379
|
+
const prevPlan = previous.result.plan;
|
|
380
|
+
const isRetainedGap = (i) => {
|
|
381
|
+
const gap = hast.children[i];
|
|
382
|
+
return gap === prevHast[i] && gap.type === "text" && !/\S/.test(gap.value);
|
|
383
|
+
};
|
|
384
|
+
while (m < mdast.children.length) {
|
|
385
|
+
const node = mdast.children[m];
|
|
386
|
+
const el = hast.children[h];
|
|
387
|
+
const item = prevPlan[h];
|
|
388
|
+
if (node !== previous.mdast.children[m] || el !== prevHast[h] || !el || el.type !== "element" || !item || item.kind !== "block" || item.info.startOffset !== node.position?.start.offset || !isEligible(node)) break;
|
|
389
|
+
const startOffset = item.info.startOffset;
|
|
390
|
+
let next = h + 1;
|
|
391
|
+
let complete = true;
|
|
392
|
+
for (;;) {
|
|
393
|
+
let probe = next;
|
|
394
|
+
while (probe < hast.children.length && isRetainedGap(probe)) probe++;
|
|
395
|
+
const sibling = prevPlan[probe];
|
|
396
|
+
if (!sibling || sibling.kind !== "block" || sibling.info.startOffset !== startOffset) break;
|
|
397
|
+
if (hast.children[probe] !== prevHast[probe]) {
|
|
398
|
+
complete = false;
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
next = probe + 1;
|
|
402
|
+
}
|
|
403
|
+
if (!complete) break;
|
|
404
|
+
reusedContext ||= item.info.hasReference;
|
|
405
|
+
m++;
|
|
406
|
+
h = next;
|
|
407
|
+
while (h < hast.children.length && isRetainedGap(h)) h++;
|
|
408
|
+
}
|
|
409
|
+
if (m > 0) {
|
|
410
|
+
const prefixEnd = mdast.children[m - 1].position?.end.offset ?? 0;
|
|
411
|
+
for (let i = h; i < hast.children.length; i++) {
|
|
412
|
+
const child = hast.children[i];
|
|
413
|
+
const at = child.type === "element" ? child.position?.start.offset : void 0;
|
|
414
|
+
if (at !== void 0 && at < prefixEnd) {
|
|
415
|
+
m = 0;
|
|
416
|
+
h = 0;
|
|
417
|
+
reusedContext = false;
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
let result;
|
|
424
|
+
if (m > 0 && previous) {
|
|
425
|
+
const tail = buildBlocks({
|
|
426
|
+
...mdast,
|
|
427
|
+
children: mdast.children.slice(m)
|
|
428
|
+
}, {
|
|
429
|
+
...hast,
|
|
430
|
+
children: hast.children.slice(h)
|
|
431
|
+
}, source, reusedContext ? {
|
|
432
|
+
...options,
|
|
433
|
+
contextMdast: options.contextMdast ?? mdast
|
|
434
|
+
} : options);
|
|
435
|
+
const prefix = previous.result.plan.slice(0, h);
|
|
436
|
+
const prefixBlocks = prefix.filter((item) => item.kind === "block");
|
|
437
|
+
result = {
|
|
438
|
+
...tail,
|
|
439
|
+
plan: [...prefix, ...tail.plan.map((item) => /^inline-i\d+$/.test(item.key) ? {
|
|
440
|
+
...item,
|
|
441
|
+
key: `inline-i${Number(item.key.slice(8)) + h}`
|
|
442
|
+
} : item)],
|
|
443
|
+
blocks: [...prefixBlocks.map((item) => item.info), ...tail.blocks],
|
|
444
|
+
blockHasts: [...prefixBlocks.map((item) => item.el), ...tail.blockHasts]
|
|
445
|
+
};
|
|
446
|
+
} else result = buildBlocks(mdast, hast, source, options);
|
|
447
|
+
previous = {
|
|
448
|
+
mdast,
|
|
449
|
+
hast,
|
|
450
|
+
source,
|
|
451
|
+
result,
|
|
452
|
+
phantoms: options.phantomFootnoteLabels
|
|
453
|
+
};
|
|
454
|
+
return result;
|
|
455
|
+
};
|
|
420
456
|
}
|
|
421
|
-
|
|
422
|
-
// src/contribution.ts
|
|
423
|
-
import { extractContributions, extractDefBodiesFromHast, footnoteSafeId } from "@ai-markdown/engine";
|
|
424
457
|
function createContributionSession() {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
defs,
|
|
489
|
-
linkDefs,
|
|
490
|
-
ownFootnoteLabels: ownLabels.footnoteLabels,
|
|
491
|
-
ownLinkLabels: ownLabels.linkLabels
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
};
|
|
458
|
+
let lastContribution = null;
|
|
459
|
+
return { commit({ pipeline, ownLabels, registry, targetPhantoms, sym, clobberPrefix, chain }) {
|
|
460
|
+
if (!registry || !sym) return;
|
|
461
|
+
const refs = [];
|
|
462
|
+
const defMeta = /* @__PURE__ */ new Map();
|
|
463
|
+
const linkDefs = /* @__PURE__ */ new Map();
|
|
464
|
+
for (const node of extractContributions(pipeline.mdast, { phantomFootnoteLabels: targetPhantoms.missingFootnotes })) if (node.kind === "ref") refs.push({
|
|
465
|
+
label: node.label,
|
|
466
|
+
kind: node.refKind,
|
|
467
|
+
referenceType: node.referenceType,
|
|
468
|
+
...node.nestedIn !== void 0 ? { nestedIn: node.nestedIn } : {}
|
|
469
|
+
});
|
|
470
|
+
else if (node.kind === "fnDef") defMeta.set(node.label, {
|
|
471
|
+
identifier: node.label,
|
|
472
|
+
sourceIdentifier: node.sourceIdentifier,
|
|
473
|
+
contentSource: node.content
|
|
474
|
+
});
|
|
475
|
+
else if (node.kind === "linkDef") linkDefs.set(node.label, {
|
|
476
|
+
identifier: node.label,
|
|
477
|
+
url: node.url,
|
|
478
|
+
title: node.title
|
|
479
|
+
});
|
|
480
|
+
const fp = JSON.stringify({
|
|
481
|
+
r: refs,
|
|
482
|
+
d: Array.from(defMeta.entries()).map(([k, v]) => [
|
|
483
|
+
k,
|
|
484
|
+
v.sourceIdentifier,
|
|
485
|
+
v.contentSource
|
|
486
|
+
]),
|
|
487
|
+
l: Array.from(linkDefs.entries()).map(([k, v]) => [
|
|
488
|
+
k,
|
|
489
|
+
v.url,
|
|
490
|
+
v.title ?? ""
|
|
491
|
+
]),
|
|
492
|
+
ofn: Array.from(ownLabels.footnoteLabels).sort(),
|
|
493
|
+
ol: Array.from(ownLabels.linkLabels).sort(),
|
|
494
|
+
tpfn: Array.from(targetPhantoms.missingFootnotes).sort(),
|
|
495
|
+
tpl: Array.from(targetPhantoms.missingLinks).sort()
|
|
496
|
+
});
|
|
497
|
+
const last = lastContribution;
|
|
498
|
+
if (last?.registry === registry && last.symbol === sym && last.fp === fp && last.chain.length === chain.length && last.chain.every((dep, i) => dep === chain[i])) return;
|
|
499
|
+
const bodiesBySafeId = extractDefBodiesFromHast(pipeline.hast, clobberPrefix);
|
|
500
|
+
const defs = /* @__PURE__ */ new Map();
|
|
501
|
+
for (const [label, meta] of defMeta) defs.set(label, {
|
|
502
|
+
identifier: meta.identifier,
|
|
503
|
+
sourceIdentifier: meta.sourceIdentifier,
|
|
504
|
+
contentSource: meta.contentSource,
|
|
505
|
+
bodyHast: bodiesBySafeId.get(footnoteSafeId(meta.sourceIdentifier)) ?? []
|
|
506
|
+
});
|
|
507
|
+
lastContribution = {
|
|
508
|
+
registry,
|
|
509
|
+
symbol: sym,
|
|
510
|
+
fp,
|
|
511
|
+
chain
|
|
512
|
+
};
|
|
513
|
+
registry.contributeChunkData(sym, {
|
|
514
|
+
refs,
|
|
515
|
+
defs,
|
|
516
|
+
linkDefs,
|
|
517
|
+
ownFootnoteLabels: ownLabels.footnoteLabels,
|
|
518
|
+
ownLinkLabels: ownLabels.linkLabels
|
|
519
|
+
});
|
|
520
|
+
} };
|
|
495
521
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
return coord;
|
|
522
|
+
function createSmoothCoordinator$1(onEmpty) {
|
|
523
|
+
const order = [];
|
|
524
|
+
const done = /* @__PURE__ */ new Set();
|
|
525
|
+
const lastProgressAt = /* @__PURE__ */ new Map();
|
|
526
|
+
return {
|
|
527
|
+
order,
|
|
528
|
+
done,
|
|
529
|
+
lastProgressAt,
|
|
530
|
+
version: 0,
|
|
531
|
+
_refcounts: /* @__PURE__ */ new Map(),
|
|
532
|
+
_subscribers: /* @__PURE__ */ new Set(),
|
|
533
|
+
_notifyScheduled: false,
|
|
534
|
+
register(chunkId) {
|
|
535
|
+
const count = this._refcounts.get(chunkId) ?? 0;
|
|
536
|
+
this._refcounts.set(chunkId, count + 1);
|
|
537
|
+
if (count === 0 && !order.includes(chunkId)) {
|
|
538
|
+
order.push(chunkId);
|
|
539
|
+
this._notify();
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
release(chunkId) {
|
|
543
|
+
const count = this._refcounts.get(chunkId);
|
|
544
|
+
if (count === void 0) return;
|
|
545
|
+
if (count > 1) {
|
|
546
|
+
this._refcounts.set(chunkId, count - 1);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
this._refcounts.set(chunkId, 0);
|
|
550
|
+
queueMicrotask(() => {
|
|
551
|
+
if (this._refcounts.get(chunkId) !== 0) return;
|
|
552
|
+
this._refcounts.delete(chunkId);
|
|
553
|
+
const idx = order.indexOf(chunkId);
|
|
554
|
+
if (idx !== -1) order.splice(idx, 1);
|
|
555
|
+
done.delete(chunkId);
|
|
556
|
+
lastProgressAt.delete(chunkId);
|
|
557
|
+
this._notify();
|
|
558
|
+
if (order.length === 0 && onEmpty) onEmpty();
|
|
559
|
+
});
|
|
560
|
+
},
|
|
561
|
+
markDone(chunkId) {
|
|
562
|
+
if (done.has(chunkId)) return;
|
|
563
|
+
done.add(chunkId);
|
|
564
|
+
this._notify();
|
|
565
|
+
},
|
|
566
|
+
stampProgress(chunkId, at) {
|
|
567
|
+
lastProgressAt.set(chunkId, at);
|
|
568
|
+
},
|
|
569
|
+
isReleased(chunkId) {
|
|
570
|
+
for (const id of order) {
|
|
571
|
+
if (id === chunkId) return true;
|
|
572
|
+
if (!done.has(id)) return false;
|
|
573
|
+
}
|
|
574
|
+
return true;
|
|
575
|
+
},
|
|
576
|
+
earliestBlockerOf(chunkId) {
|
|
577
|
+
for (const id of order) {
|
|
578
|
+
if (id === chunkId) return null;
|
|
579
|
+
if (!done.has(id)) return id;
|
|
580
|
+
}
|
|
581
|
+
return null;
|
|
582
|
+
},
|
|
583
|
+
subscribe(cb) {
|
|
584
|
+
this._subscribers.add(cb);
|
|
585
|
+
return () => {
|
|
586
|
+
this._subscribers.delete(cb);
|
|
587
|
+
};
|
|
588
|
+
},
|
|
589
|
+
_notify() {
|
|
590
|
+
this.version++;
|
|
591
|
+
if (this._notifyScheduled) return;
|
|
592
|
+
this._notifyScheduled = true;
|
|
593
|
+
queueMicrotask(() => {
|
|
594
|
+
this._notifyScheduled = false;
|
|
595
|
+
for (const cb of [...this._subscribers]) cb();
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
};
|
|
576
599
|
}
|
|
577
600
|
function evaluateGateWarn(coordinator, chunkId, nowMs, thresholdMs) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return nowMs - progressedAt < thresholdMs ? "rearm" : "warn";
|
|
601
|
+
const blocker = coordinator.earliestBlockerOf(chunkId);
|
|
602
|
+
if (!blocker) return "clear";
|
|
603
|
+
return nowMs - (coordinator.lastProgressAt.get(blocker) ?? 0) < thresholdMs ? "rearm" : "warn";
|
|
582
604
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
function createSmoothCoordinator2(onEmpty) {
|
|
586
|
-
return createSmoothCoordinator(onEmpty);
|
|
605
|
+
function createSmoothCoordinator(onEmpty) {
|
|
606
|
+
return createSmoothCoordinator$1(onEmpty);
|
|
587
607
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
608
|
+
const DESCEND_THROUGH = /* @__PURE__ */ new Set([
|
|
609
|
+
"blockquote",
|
|
610
|
+
"list",
|
|
611
|
+
"listItem",
|
|
612
|
+
"footnoteDefinition"
|
|
613
|
+
]);
|
|
591
614
|
function deriveTailSignal(mdast, contentLength) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
615
|
+
const children = mdast.children;
|
|
616
|
+
let index = children.length - 1;
|
|
617
|
+
while (index >= 0) {
|
|
618
|
+
const offset = children[index].position?.start?.offset;
|
|
619
|
+
if (offset !== void 0 && offset >= contentLength) {
|
|
620
|
+
index--;
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
if (index < 0) return null;
|
|
626
|
+
let node = children[index];
|
|
627
|
+
let deepestFootnoteDef = null;
|
|
628
|
+
for (;;) {
|
|
629
|
+
if (node.type === "footnoteDefinition") deepestFootnoteDef = node;
|
|
630
|
+
if (node.type === "definition") return { kind: "invisible-def" };
|
|
631
|
+
if (!DESCEND_THROUGH.has(node.type)) break;
|
|
632
|
+
const kids = node.children;
|
|
633
|
+
if (!kids || kids.length === 0) break;
|
|
634
|
+
node = kids[kids.length - 1];
|
|
635
|
+
}
|
|
636
|
+
return deepestFootnoteDef ? {
|
|
637
|
+
kind: "footnote-def",
|
|
638
|
+
identifier: deepestFootnoteDef.identifier
|
|
639
|
+
} : null;
|
|
616
640
|
}
|
|
617
|
-
|
|
618
|
-
// src/aggregateFootnotes.ts
|
|
619
|
-
import { footnoteSafeId as footnoteSafeId2, lastMeaningfulIdx } from "@ai-markdown/engine";
|
|
620
|
-
|
|
621
|
-
// src/cloneHastForRender.ts
|
|
622
641
|
function cloneHastForRender(node) {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
const data = copy.data;
|
|
635
|
-
if (data.originalUrls) data.originalUrls = { ...data.originalUrls };
|
|
636
|
-
}
|
|
637
|
-
return copy;
|
|
642
|
+
const copy = { ...node };
|
|
643
|
+
const withChildren = copy;
|
|
644
|
+
if (Array.isArray(withChildren.children)) withChildren.children = withChildren.children.map((child) => cloneHastForRender(child));
|
|
645
|
+
const withProperties = copy;
|
|
646
|
+
if (withProperties.properties) withProperties.properties = { ...withProperties.properties };
|
|
647
|
+
if (copy.data) {
|
|
648
|
+
copy.data = { ...copy.data };
|
|
649
|
+
const data = copy.data;
|
|
650
|
+
if (data.originalUrls) data.originalUrls = { ...data.originalUrls };
|
|
651
|
+
}
|
|
652
|
+
return copy;
|
|
638
653
|
}
|
|
639
|
-
|
|
640
|
-
// src/aggregateFootnotes.ts
|
|
641
654
|
function buildBackref(href, occurrence, globalNumber) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
655
|
+
const children = [{
|
|
656
|
+
type: "text",
|
|
657
|
+
value: "↩"
|
|
658
|
+
}];
|
|
659
|
+
if (occurrence > 1) children.push({
|
|
660
|
+
type: "element",
|
|
661
|
+
tagName: "sup",
|
|
662
|
+
properties: {},
|
|
663
|
+
children: [{
|
|
664
|
+
type: "text",
|
|
665
|
+
value: String(occurrence)
|
|
666
|
+
}]
|
|
667
|
+
});
|
|
668
|
+
return {
|
|
669
|
+
type: "element",
|
|
670
|
+
tagName: "a",
|
|
671
|
+
properties: {
|
|
672
|
+
href,
|
|
673
|
+
dataFootnoteBackref: "",
|
|
674
|
+
className: ["data-footnote-backref"],
|
|
675
|
+
ariaLabel: occurrence === 1 ? `Back to reference ${globalNumber}` : `Back to reference ${globalNumber}-${occurrence}`
|
|
676
|
+
},
|
|
677
|
+
children
|
|
678
|
+
};
|
|
663
679
|
}
|
|
664
680
|
function buildAggregateTree(registry, clobberPrefix, preserveOrphanReferences = false) {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
// `<hr>` so the visual break is preserved without sanitize-friendly CSS.
|
|
759
|
-
{
|
|
760
|
-
type: "element",
|
|
761
|
-
tagName: "hr",
|
|
762
|
-
properties: {},
|
|
763
|
-
children: []
|
|
764
|
-
},
|
|
765
|
-
{
|
|
766
|
-
type: "element",
|
|
767
|
-
tagName: "ol",
|
|
768
|
-
properties: {},
|
|
769
|
-
children: liElements
|
|
770
|
-
}
|
|
771
|
-
]
|
|
772
|
-
};
|
|
681
|
+
const seen = /* @__PURE__ */ new Set();
|
|
682
|
+
const ordered = [];
|
|
683
|
+
for (const sym of registry.chunkOrder) {
|
|
684
|
+
const data = registry.chunkData.get(sym);
|
|
685
|
+
if (!data) continue;
|
|
686
|
+
for (const ref of data.refs) {
|
|
687
|
+
if (ref.kind !== "footnote") continue;
|
|
688
|
+
if (seen.has(ref.label)) continue;
|
|
689
|
+
seen.add(ref.label);
|
|
690
|
+
const canonicalSym = registry.canonicalFootnoteFor(ref.label);
|
|
691
|
+
if (!canonicalSym) continue;
|
|
692
|
+
const def = registry.chunkData.get(canonicalSym)?.defs.get(ref.label);
|
|
693
|
+
if (!def) continue;
|
|
694
|
+
const n = registry.globalNumber(ref.label);
|
|
695
|
+
if (n === null) continue;
|
|
696
|
+
const sourceIdentifier = def.sourceIdentifier ?? ref.label;
|
|
697
|
+
ordered.push({
|
|
698
|
+
normalizedLabel: ref.label,
|
|
699
|
+
sourceIdentifier,
|
|
700
|
+
bodyHast: def.bodyHast ?? [],
|
|
701
|
+
n,
|
|
702
|
+
withBackref: true
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
ordered.sort((a, b) => (a.n ?? 0) - (b.n ?? 0));
|
|
707
|
+
if (preserveOrphanReferences) for (const sym of registry.chunkOrder) {
|
|
708
|
+
const data = registry.chunkData.get(sym);
|
|
709
|
+
if (!data) continue;
|
|
710
|
+
for (const [label, def] of data.defs) {
|
|
711
|
+
if (seen.has(label)) continue;
|
|
712
|
+
if (registry.canonicalFootnoteFor(label) !== sym) continue;
|
|
713
|
+
seen.add(label);
|
|
714
|
+
ordered.push({
|
|
715
|
+
normalizedLabel: label,
|
|
716
|
+
sourceIdentifier: def.sourceIdentifier ?? label,
|
|
717
|
+
bodyHast: def.bodyHast ?? [],
|
|
718
|
+
n: null,
|
|
719
|
+
withBackref: false
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
if (ordered.length === 0) return null;
|
|
724
|
+
return {
|
|
725
|
+
type: "element",
|
|
726
|
+
tagName: "section",
|
|
727
|
+
properties: {
|
|
728
|
+
className: ["footnotes"],
|
|
729
|
+
dataFootnotes: true,
|
|
730
|
+
ariaLabel: "Footnotes"
|
|
731
|
+
},
|
|
732
|
+
children: [{
|
|
733
|
+
type: "element",
|
|
734
|
+
tagName: "hr",
|
|
735
|
+
properties: {},
|
|
736
|
+
children: []
|
|
737
|
+
}, {
|
|
738
|
+
type: "element",
|
|
739
|
+
tagName: "ol",
|
|
740
|
+
properties: {},
|
|
741
|
+
children: ordered.map(({ normalizedLabel, sourceIdentifier, bodyHast, n, withBackref }) => {
|
|
742
|
+
const safeId = footnoteSafeId(sourceIdentifier);
|
|
743
|
+
const liChildren = bodyHast.map((c) => cloneHastForRender(c));
|
|
744
|
+
if (withBackref) {
|
|
745
|
+
const totalRefs = registry.getRefsForLabel(normalizedLabel);
|
|
746
|
+
const tailIdx = lastMeaningfulIdx(liChildren);
|
|
747
|
+
const tail = tailIdx !== -1 ? liChildren[tailIdx] : null;
|
|
748
|
+
const dest = tail && tail.type === "element" && tail.tagName === "p" ? tail : null;
|
|
749
|
+
const appended = [];
|
|
750
|
+
for (let i = 1; i <= Math.max(totalRefs, 1); i++) {
|
|
751
|
+
appended.push({
|
|
752
|
+
type: "text",
|
|
753
|
+
value: " "
|
|
754
|
+
});
|
|
755
|
+
const href = i === 1 ? `#${clobberPrefix}fnref-${safeId}` : `#${clobberPrefix}fnref-${safeId}-${i}`;
|
|
756
|
+
appended.push(buildBackref(href, i, n ?? 0));
|
|
757
|
+
}
|
|
758
|
+
if (dest) dest.children = [...dest.children, ...appended];
|
|
759
|
+
else if (tailIdx !== -1) liChildren.splice(tailIdx + 1, 0, ...appended);
|
|
760
|
+
else liChildren.push(...appended);
|
|
761
|
+
}
|
|
762
|
+
return {
|
|
763
|
+
type: "element",
|
|
764
|
+
tagName: "li",
|
|
765
|
+
properties: {
|
|
766
|
+
id: `${clobberPrefix}fn-${safeId}`,
|
|
767
|
+
...n !== null ? { value: String(n) } : {}
|
|
768
|
+
},
|
|
769
|
+
children: liChildren
|
|
770
|
+
};
|
|
771
|
+
})
|
|
772
|
+
}]
|
|
773
|
+
};
|
|
773
774
|
}
|
|
774
|
-
|
|
775
|
-
// src/pipelineSession.ts
|
|
776
|
-
import {
|
|
777
|
-
EngineRawHtmlDepthError,
|
|
778
|
-
advanceIncrementalParse,
|
|
779
|
-
buildPhantomSuffix,
|
|
780
|
-
phantomSuffixCloser,
|
|
781
|
-
parseStage,
|
|
782
|
-
transformStage
|
|
783
|
-
} from "@ai-markdown/engine";
|
|
784
|
-
var unmeasured = (_stage, fn) => fn();
|
|
775
|
+
const unmeasured = (_stage, fn) => fn();
|
|
785
776
|
function endPoint(text) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
777
|
+
let line = 1;
|
|
778
|
+
let lineStart = 0;
|
|
779
|
+
for (let i = 0; i < text.length; i++) {
|
|
780
|
+
const code = text.charCodeAt(i);
|
|
781
|
+
if (code === 10 || code === 13 && text.charCodeAt(i + 1) !== 10) {
|
|
782
|
+
line += 1;
|
|
783
|
+
lineStart = i + 1;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
line,
|
|
788
|
+
column: text.length - lineStart + 1,
|
|
789
|
+
offset: text.length
|
|
790
|
+
};
|
|
796
791
|
}
|
|
797
792
|
function plainTextTrees(content) {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
793
|
+
const position = {
|
|
794
|
+
start: {
|
|
795
|
+
line: 1,
|
|
796
|
+
column: 1,
|
|
797
|
+
offset: 0
|
|
798
|
+
},
|
|
799
|
+
end: endPoint(content)
|
|
800
|
+
};
|
|
801
|
+
const text = {
|
|
802
|
+
type: "text",
|
|
803
|
+
value: content,
|
|
804
|
+
position
|
|
805
|
+
};
|
|
806
|
+
return {
|
|
807
|
+
mdast: {
|
|
808
|
+
type: "root",
|
|
809
|
+
children: [{
|
|
810
|
+
type: "paragraph",
|
|
811
|
+
children: [text],
|
|
812
|
+
position
|
|
813
|
+
}],
|
|
814
|
+
position
|
|
815
|
+
},
|
|
816
|
+
hast: {
|
|
817
|
+
type: "root",
|
|
818
|
+
children: [{
|
|
819
|
+
type: "element",
|
|
820
|
+
tagName: "p",
|
|
821
|
+
properties: {},
|
|
822
|
+
children: [text],
|
|
823
|
+
position
|
|
824
|
+
}],
|
|
825
|
+
position
|
|
826
|
+
}
|
|
827
|
+
};
|
|
808
828
|
}
|
|
809
829
|
function createPipelineSession() {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
// phantom label sets are deliberately NOT here: their churn tracks
|
|
891
|
-
// the suffix (always re-parsed with the tail), never the prefix.
|
|
892
|
-
depsKey: [
|
|
893
|
-
remarkPlugins,
|
|
894
|
-
rehypePlugins,
|
|
895
|
-
remarkRehypeOptions,
|
|
896
|
-
handlers,
|
|
897
|
-
preserveForBodyHarvest,
|
|
898
|
-
documentId,
|
|
899
|
-
// Explicit even though `rehypePlugins` already carries it: a
|
|
900
|
-
// credential change must never reuse trees stamped under the
|
|
901
|
-
// old one.
|
|
902
|
-
provenance,
|
|
903
|
-
// The boundary scanner's grammar profile. The scan checkpoint
|
|
904
|
-
// already refuses to resume under a different profile, but the
|
|
905
|
-
// retained TREES were still spliced against — a prefix frozen
|
|
906
|
-
// under one profile must not survive into frames under the other.
|
|
907
|
-
defListEnabled,
|
|
908
|
-
gfmTaskListItems,
|
|
909
|
-
mathFlow
|
|
910
|
-
],
|
|
911
|
-
defListEnabled,
|
|
912
|
-
gfmTaskListItems,
|
|
913
|
-
mathFlow,
|
|
914
|
-
phantomSuffix,
|
|
915
|
-
measure: measureHere
|
|
916
|
-
});
|
|
917
|
-
state = result.nextState;
|
|
918
|
-
return { mdast: result.mdast, hast: result.hast };
|
|
919
|
-
} catch (error) {
|
|
920
|
-
state = null;
|
|
921
|
-
if (true) {
|
|
922
|
-
console.error("[ai-react-markdown] incremental parse failed \u2014 full parse fallback for this frame:", error);
|
|
923
|
-
}
|
|
924
|
-
return fullPipeline();
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
};
|
|
830
|
+
let state = null;
|
|
831
|
+
return {
|
|
832
|
+
reset() {
|
|
833
|
+
state = null;
|
|
834
|
+
},
|
|
835
|
+
parse({ content, targetPhantoms, remarkPlugins, rehypePlugins, remarkRehypeOptions, handlers, preserveForBodyHarvest, documentId, provenance, incrementalParse, defListEnabled, gfmTaskListItems = false, mathFlow, measure: measureHere = unmeasured }) {
|
|
836
|
+
const phantomDefs = buildPhantomSuffix(targetPhantoms);
|
|
837
|
+
const phantomSuffix = phantomDefs === "" ? "" : phantomSuffixCloser(content ?? "") + phantomDefs;
|
|
838
|
+
const augmented = (content ?? "") + phantomSuffix;
|
|
839
|
+
const baseHandlers = remarkRehypeOptions?.handlers ?? {};
|
|
840
|
+
const mergedRemarkRehypeOptions = handlers ? {
|
|
841
|
+
...remarkRehypeOptions,
|
|
842
|
+
handlers: {
|
|
843
|
+
...baseHandlers,
|
|
844
|
+
...handlers
|
|
845
|
+
},
|
|
846
|
+
phantomFootnoteLabels: targetPhantoms.missingFootnotes,
|
|
847
|
+
phantomLinkLabels: targetPhantoms.missingLinks,
|
|
848
|
+
preserveOrphan: preserveForBodyHarvest,
|
|
849
|
+
documentId,
|
|
850
|
+
provenance
|
|
851
|
+
} : { ...remarkRehypeOptions };
|
|
852
|
+
const fullPipeline = () => {
|
|
853
|
+
try {
|
|
854
|
+
const parsed = measureHere("parse", () => parseStage({
|
|
855
|
+
children: augmented,
|
|
856
|
+
remarkPlugins,
|
|
857
|
+
rehypePlugins,
|
|
858
|
+
remarkRehypeOptions: mergedRemarkRehypeOptions
|
|
859
|
+
}));
|
|
860
|
+
const hastRoot = measureHere("transform", () => transformStage(parsed));
|
|
861
|
+
return {
|
|
862
|
+
mdast: parsed.mdast,
|
|
863
|
+
hast: hastRoot
|
|
864
|
+
};
|
|
865
|
+
} catch (error) {
|
|
866
|
+
if (!(error instanceof EngineRawHtmlDepthError)) throw error;
|
|
867
|
+
console.error("[ai-react-markdown] raw HTML nested past the engine depth bound — rendering this frame as plain text:", error);
|
|
868
|
+
return plainTextTrees(content ?? "");
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
if (!incrementalParse) {
|
|
872
|
+
state = null;
|
|
873
|
+
return fullPipeline();
|
|
874
|
+
}
|
|
875
|
+
try {
|
|
876
|
+
const result = advanceIncrementalParse(state, content ?? "", {
|
|
877
|
+
remarkPlugins,
|
|
878
|
+
rehypePlugins,
|
|
879
|
+
remarkRehypeOptions: mergedRemarkRehypeOptions,
|
|
880
|
+
depsKey: [
|
|
881
|
+
remarkPlugins,
|
|
882
|
+
rehypePlugins,
|
|
883
|
+
remarkRehypeOptions,
|
|
884
|
+
handlers,
|
|
885
|
+
preserveForBodyHarvest,
|
|
886
|
+
documentId,
|
|
887
|
+
provenance,
|
|
888
|
+
defListEnabled,
|
|
889
|
+
gfmTaskListItems,
|
|
890
|
+
mathFlow
|
|
891
|
+
],
|
|
892
|
+
defListEnabled,
|
|
893
|
+
gfmTaskListItems,
|
|
894
|
+
mathFlow,
|
|
895
|
+
phantomSuffix,
|
|
896
|
+
measure: measureHere
|
|
897
|
+
});
|
|
898
|
+
state = result.nextState;
|
|
899
|
+
return {
|
|
900
|
+
mdast: result.mdast,
|
|
901
|
+
hast: result.hast
|
|
902
|
+
};
|
|
903
|
+
} catch (error) {
|
|
904
|
+
state = null;
|
|
905
|
+
console.error("[ai-react-markdown] incremental parse failed — full parse fallback for this frame:", error);
|
|
906
|
+
return fullPipeline();
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
};
|
|
928
910
|
}
|
|
929
|
-
|
|
930
|
-
// src/coordinationPreparation.ts
|
|
931
|
-
import { buildCrossChunkHandlers, normalizeForMatch } from "@ai-markdown/engine";
|
|
932
911
|
function derivePhantomTargets({ content, ownLabels, labels }, previous) {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
912
|
+
const missingFootnotes = /* @__PURE__ */ new Set();
|
|
913
|
+
const missingLinks = /* @__PURE__ */ new Set();
|
|
914
|
+
if (labels) {
|
|
915
|
+
const footnotes = [...labels.footnoteLabels].filter((label) => !ownLabels.footnoteLabels.has(label));
|
|
916
|
+
const links = [...labels.linkLabels].filter((label) => !ownLabels.linkLabels.has(label));
|
|
917
|
+
if (footnotes.length || links.length) {
|
|
918
|
+
const normalized = normalizeForMatch(content);
|
|
919
|
+
for (const label of footnotes) if (normalized.includes(label)) missingFootnotes.add(label);
|
|
920
|
+
for (const label of links) if (normalized.includes(label)) missingLinks.add(label);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (previous && missingFootnotes.size === previous.missingFootnotes.size && missingLinks.size === previous.missingLinks.size && [...missingFootnotes].every((label) => previous.missingFootnotes.has(label)) && [...missingLinks].every((label) => previous.missingLinks.has(label))) return previous;
|
|
924
|
+
return {
|
|
925
|
+
missingFootnotes,
|
|
926
|
+
missingLinks
|
|
927
|
+
};
|
|
947
928
|
}
|
|
948
|
-
function deriveCoordinationPolicy({
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
return { mode, handlers, preserveForBodyHarvest };
|
|
929
|
+
function deriveCoordinationPolicy({ coordinated, registered, preserveOrphanReferences }, previous) {
|
|
930
|
+
const mode = coordinated ? "coordinated" : preserveOrphanReferences ? "orphan" : "standalone";
|
|
931
|
+
const preserveForBodyHarvest = preserveOrphanReferences || coordinated && registered;
|
|
932
|
+
if (previous?.mode === mode && previous.preserveForBodyHarvest === preserveForBodyHarvest) return previous;
|
|
933
|
+
return {
|
|
934
|
+
mode,
|
|
935
|
+
handlers: previous?.mode === mode ? previous.handlers : mode === "coordinated" ? buildCrossChunkHandlers() : mode === "orphan" ? { footnoteDefinition: buildCrossChunkHandlers().footnoteDefinition } : void 0,
|
|
936
|
+
preserveForBodyHarvest
|
|
937
|
+
};
|
|
958
938
|
}
|
|
959
939
|
function buildContributionChain(inputs) {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
940
|
+
return [
|
|
941
|
+
inputs.remarkPlugins,
|
|
942
|
+
inputs.rehypePlugins,
|
|
943
|
+
inputs.remarkRehypeOptions,
|
|
944
|
+
inputs.handlers,
|
|
945
|
+
inputs.preserveForBodyHarvest,
|
|
946
|
+
inputs.clobberPrefix,
|
|
947
|
+
inputs.documentId,
|
|
948
|
+
inputs.provenance
|
|
949
|
+
];
|
|
970
950
|
}
|
|
971
|
-
export {
|
|
972
|
-
|
|
973
|
-
buildBlocks,
|
|
974
|
-
buildContributionChain,
|
|
975
|
-
cloneHastForRender,
|
|
976
|
-
computeBlockFingerprint,
|
|
977
|
-
computeHtmlBlockDigest,
|
|
978
|
-
computeHtmlBlockDigestWithExtent,
|
|
979
|
-
createBlockPlanner,
|
|
980
|
-
createContributionSession,
|
|
981
|
-
createPipelineSession,
|
|
982
|
-
createSmoothCoordinator2 as createSmoothCoordinator,
|
|
983
|
-
deriveCoordinationPolicy,
|
|
984
|
-
derivePhantomTargets,
|
|
985
|
-
deriveTailSignal,
|
|
986
|
-
evaluateGateWarn,
|
|
987
|
-
hasMdastSource,
|
|
988
|
-
isFootnoteSection
|
|
989
|
-
};
|
|
951
|
+
export { buildAggregateTree, buildBlocks, buildContributionChain, cloneHastForRender, computeBlockFingerprint, computeHtmlBlockDigest, computeHtmlBlockDigestWithExtent, createBlockPlanner, createContributionSession, createPipelineSession, createSmoothCoordinator, deriveCoordinationPolicy, derivePhantomTargets, deriveTailSignal, evaluateGateWarn, hasMdastSource, isFootnoteSection };
|
|
952
|
+
|
|
990
953
|
//# sourceMappingURL=index.dev.js.map
|