@stream-mdx/core 0.1.0 → 0.2.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/CHANGELOG.md +6 -0
- package/README.md +6 -0
- package/dist/code-highlighting.cjs +20 -0
- package/dist/code-highlighting.d.cts +9 -1
- package/dist/code-highlighting.d.ts +9 -1
- package/dist/code-highlighting.mjs +18 -0
- package/dist/index.cjs +354 -149
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +352 -149
- package/dist/mixed-content.cjs +14 -0
- package/dist/mixed-content.d.cts +3 -1
- package/dist/mixed-content.d.ts +3 -1
- package/dist/mixed-content.mjs +14 -0
- package/dist/perf/patch-coalescing.cjs +58 -1
- package/dist/perf/patch-coalescing.mjs +58 -1
- package/dist/types.d.cts +64 -1
- package/dist/types.d.ts +64 -1
- package/dist/utils.cjs +16 -6
- package/dist/utils.mjs +16 -6
- package/package.json +1 -1
package/dist/mixed-content.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InlineNode, MixedContentSegment } from './types.js';
|
|
1
|
+
import { ProtectedRange, InlineNode, MixedContentSegment } from './types.js';
|
|
2
2
|
|
|
3
3
|
interface MixedContentAutoCloseHtmlOptions {
|
|
4
4
|
autoClose?: boolean;
|
|
@@ -13,6 +13,8 @@ interface MixedContentAutoCloseMdxOptions {
|
|
|
13
13
|
interface MixedContentOptions {
|
|
14
14
|
html?: MixedContentAutoCloseHtmlOptions;
|
|
15
15
|
mdx?: MixedContentAutoCloseMdxOptions;
|
|
16
|
+
protectedRanges?: ReadonlyArray<ProtectedRange>;
|
|
17
|
+
protectedRangeKinds?: ReadonlyArray<ProtectedRange["kind"]>;
|
|
16
18
|
}
|
|
17
19
|
declare function extractMixedContentSegments(raw: string, baseOffset: number | undefined, parseInline: (content: string) => InlineNode[], options?: MixedContentOptions): MixedContentSegment[];
|
|
18
20
|
declare function isLikelyMdxComponent(tagName: string): boolean;
|
package/dist/mixed-content.mjs
CHANGED
|
@@ -179,6 +179,8 @@ function splitByTagSegments(source, baseOffset, parseInline, options) {
|
|
|
179
179
|
const mdxAutoClose = options?.mdx?.autoClose === true;
|
|
180
180
|
const mdxMaxNewlines = normalizeNewlineLimit(options?.mdx?.maxNewlines);
|
|
181
181
|
const mdxAllowlist = normalizeComponentAllowlist(options?.mdx?.componentAllowlist);
|
|
182
|
+
const protectedRanges = options?.protectedRanges ?? [];
|
|
183
|
+
const protectedKinds = protectedRanges.length ? new Set(options?.protectedRangeKinds ?? ["math-inline", "math-display", "code-inline", "code-block", "autolink"]) : null;
|
|
182
184
|
while (match !== null) {
|
|
183
185
|
const start = match.index;
|
|
184
186
|
const tagName = match[1];
|
|
@@ -193,6 +195,18 @@ function splitByTagSegments(source, baseOffset, parseInline, options) {
|
|
|
193
195
|
continue;
|
|
194
196
|
}
|
|
195
197
|
let end = tagPattern.lastIndex;
|
|
198
|
+
if (protectedKinds && protectedRanges.length > 0) {
|
|
199
|
+
const absoluteStart = baseIsFinite ? baseOffset + start : start;
|
|
200
|
+
const absoluteEnd = baseIsFinite ? baseOffset + end : end;
|
|
201
|
+
const covered = protectedRanges.some(
|
|
202
|
+
(range) => protectedKinds.has(range.kind) && typeof range.from === "number" && typeof range.to === "number" && range.from <= absoluteStart && range.to >= absoluteEnd
|
|
203
|
+
);
|
|
204
|
+
if (covered) {
|
|
205
|
+
tagPattern.lastIndex = start + 1;
|
|
206
|
+
match = tagPattern.exec(source);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
196
210
|
if (!isSelfClosing && !mdxAllowed) {
|
|
197
211
|
const closingIndex = findClosingHtmlTag(lowerSource, tagName.toLowerCase(), end);
|
|
198
212
|
if (closingIndex === -1) {
|
|
@@ -140,6 +140,14 @@ function mergeAppendLines(window, startIndex) {
|
|
|
140
140
|
}
|
|
141
141
|
const lines = [...base.lines ?? []];
|
|
142
142
|
const highlight = Array.isArray(base.highlight) ? [...base.highlight] : [];
|
|
143
|
+
const tokens = Array.isArray(base.tokens) ? [...base.tokens] : [];
|
|
144
|
+
const diffKind = Array.isArray(base.diffKind) ? [...base.diffKind] : [];
|
|
145
|
+
const oldNo = Array.isArray(base.oldNo) ? [...base.oldNo] : [];
|
|
146
|
+
const newNo = Array.isArray(base.newNo) ? [...base.newNo] : [];
|
|
147
|
+
let includeTokens = Array.isArray(base.tokens);
|
|
148
|
+
let includeDiffKind = Array.isArray(base.diffKind);
|
|
149
|
+
let includeOldNo = Array.isArray(base.oldNo);
|
|
150
|
+
let includeNewNo = Array.isArray(base.newNo);
|
|
143
151
|
const baseStart = base.startIndex;
|
|
144
152
|
let expectedStart = baseStart + lines.length;
|
|
145
153
|
let j = startIndex + 1;
|
|
@@ -147,6 +155,7 @@ function mergeAppendLines(window, startIndex) {
|
|
|
147
155
|
while (j < window.length && mergedCount < APPEND_MERGE_LIMIT) {
|
|
148
156
|
const next = window[j];
|
|
149
157
|
if (next.op === "appendLines" && next.at.blockId === base.at.blockId && next.at.nodeId === base.at.nodeId && typeof next.startIndex === "number" && next.startIndex === expectedStart) {
|
|
158
|
+
const priorLineCount = lines.length;
|
|
150
159
|
lines.push(...next.lines ?? []);
|
|
151
160
|
const nextHighlights = Array.isArray(next.highlight) ? next.highlight : [];
|
|
152
161
|
const appendedCount = next.lines?.length ?? 0;
|
|
@@ -160,6 +169,50 @@ function mergeAppendLines(window, startIndex) {
|
|
|
160
169
|
highlight.push(null);
|
|
161
170
|
}
|
|
162
171
|
}
|
|
172
|
+
if (Array.isArray(next.tokens)) {
|
|
173
|
+
if (!includeTokens) {
|
|
174
|
+
tokens.push(...new Array(priorLineCount).fill(null));
|
|
175
|
+
includeTokens = true;
|
|
176
|
+
}
|
|
177
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
178
|
+
tokens.push(idx < next.tokens.length ? next.tokens[idx] ?? null : null);
|
|
179
|
+
}
|
|
180
|
+
} else if (includeTokens) {
|
|
181
|
+
tokens.push(...new Array(appendedCount).fill(null));
|
|
182
|
+
}
|
|
183
|
+
if (Array.isArray(next.diffKind)) {
|
|
184
|
+
if (!includeDiffKind) {
|
|
185
|
+
diffKind.push(...new Array(priorLineCount).fill(null));
|
|
186
|
+
includeDiffKind = true;
|
|
187
|
+
}
|
|
188
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
189
|
+
diffKind.push(idx < next.diffKind.length ? next.diffKind[idx] ?? null : null);
|
|
190
|
+
}
|
|
191
|
+
} else if (includeDiffKind) {
|
|
192
|
+
diffKind.push(...new Array(appendedCount).fill(null));
|
|
193
|
+
}
|
|
194
|
+
if (Array.isArray(next.oldNo)) {
|
|
195
|
+
if (!includeOldNo) {
|
|
196
|
+
oldNo.push(...new Array(priorLineCount).fill(null));
|
|
197
|
+
includeOldNo = true;
|
|
198
|
+
}
|
|
199
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
200
|
+
oldNo.push(idx < next.oldNo.length ? next.oldNo[idx] ?? null : null);
|
|
201
|
+
}
|
|
202
|
+
} else if (includeOldNo) {
|
|
203
|
+
oldNo.push(...new Array(appendedCount).fill(null));
|
|
204
|
+
}
|
|
205
|
+
if (Array.isArray(next.newNo)) {
|
|
206
|
+
if (!includeNewNo) {
|
|
207
|
+
newNo.push(...new Array(priorLineCount).fill(null));
|
|
208
|
+
includeNewNo = true;
|
|
209
|
+
}
|
|
210
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
211
|
+
newNo.push(idx < next.newNo.length ? next.newNo[idx] ?? null : null);
|
|
212
|
+
}
|
|
213
|
+
} else if (includeNewNo) {
|
|
214
|
+
newNo.push(...new Array(appendedCount).fill(null));
|
|
215
|
+
}
|
|
163
216
|
expectedStart = baseStart + lines.length;
|
|
164
217
|
mergedCount++;
|
|
165
218
|
j++;
|
|
@@ -170,7 +223,11 @@ function mergeAppendLines(window, startIndex) {
|
|
|
170
223
|
const combined = {
|
|
171
224
|
...base,
|
|
172
225
|
lines,
|
|
173
|
-
highlight: highlight.length > 0 ? highlight : void 0
|
|
226
|
+
highlight: highlight.length > 0 ? highlight : void 0,
|
|
227
|
+
tokens: includeTokens && tokens.length > 0 ? tokens : void 0,
|
|
228
|
+
diffKind: includeDiffKind && diffKind.length > 0 ? diffKind : void 0,
|
|
229
|
+
oldNo: includeOldNo && oldNo.length > 0 ? oldNo : void 0,
|
|
230
|
+
newNo: includeNewNo && newNo.length > 0 ? newNo : void 0
|
|
174
231
|
};
|
|
175
232
|
return { patch: combined, nextIndex: j };
|
|
176
233
|
}
|
|
@@ -112,6 +112,14 @@ function mergeAppendLines(window, startIndex) {
|
|
|
112
112
|
}
|
|
113
113
|
const lines = [...base.lines ?? []];
|
|
114
114
|
const highlight = Array.isArray(base.highlight) ? [...base.highlight] : [];
|
|
115
|
+
const tokens = Array.isArray(base.tokens) ? [...base.tokens] : [];
|
|
116
|
+
const diffKind = Array.isArray(base.diffKind) ? [...base.diffKind] : [];
|
|
117
|
+
const oldNo = Array.isArray(base.oldNo) ? [...base.oldNo] : [];
|
|
118
|
+
const newNo = Array.isArray(base.newNo) ? [...base.newNo] : [];
|
|
119
|
+
let includeTokens = Array.isArray(base.tokens);
|
|
120
|
+
let includeDiffKind = Array.isArray(base.diffKind);
|
|
121
|
+
let includeOldNo = Array.isArray(base.oldNo);
|
|
122
|
+
let includeNewNo = Array.isArray(base.newNo);
|
|
115
123
|
const baseStart = base.startIndex;
|
|
116
124
|
let expectedStart = baseStart + lines.length;
|
|
117
125
|
let j = startIndex + 1;
|
|
@@ -119,6 +127,7 @@ function mergeAppendLines(window, startIndex) {
|
|
|
119
127
|
while (j < window.length && mergedCount < APPEND_MERGE_LIMIT) {
|
|
120
128
|
const next = window[j];
|
|
121
129
|
if (next.op === "appendLines" && next.at.blockId === base.at.blockId && next.at.nodeId === base.at.nodeId && typeof next.startIndex === "number" && next.startIndex === expectedStart) {
|
|
130
|
+
const priorLineCount = lines.length;
|
|
122
131
|
lines.push(...next.lines ?? []);
|
|
123
132
|
const nextHighlights = Array.isArray(next.highlight) ? next.highlight : [];
|
|
124
133
|
const appendedCount = next.lines?.length ?? 0;
|
|
@@ -132,6 +141,50 @@ function mergeAppendLines(window, startIndex) {
|
|
|
132
141
|
highlight.push(null);
|
|
133
142
|
}
|
|
134
143
|
}
|
|
144
|
+
if (Array.isArray(next.tokens)) {
|
|
145
|
+
if (!includeTokens) {
|
|
146
|
+
tokens.push(...new Array(priorLineCount).fill(null));
|
|
147
|
+
includeTokens = true;
|
|
148
|
+
}
|
|
149
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
150
|
+
tokens.push(idx < next.tokens.length ? next.tokens[idx] ?? null : null);
|
|
151
|
+
}
|
|
152
|
+
} else if (includeTokens) {
|
|
153
|
+
tokens.push(...new Array(appendedCount).fill(null));
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(next.diffKind)) {
|
|
156
|
+
if (!includeDiffKind) {
|
|
157
|
+
diffKind.push(...new Array(priorLineCount).fill(null));
|
|
158
|
+
includeDiffKind = true;
|
|
159
|
+
}
|
|
160
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
161
|
+
diffKind.push(idx < next.diffKind.length ? next.diffKind[idx] ?? null : null);
|
|
162
|
+
}
|
|
163
|
+
} else if (includeDiffKind) {
|
|
164
|
+
diffKind.push(...new Array(appendedCount).fill(null));
|
|
165
|
+
}
|
|
166
|
+
if (Array.isArray(next.oldNo)) {
|
|
167
|
+
if (!includeOldNo) {
|
|
168
|
+
oldNo.push(...new Array(priorLineCount).fill(null));
|
|
169
|
+
includeOldNo = true;
|
|
170
|
+
}
|
|
171
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
172
|
+
oldNo.push(idx < next.oldNo.length ? next.oldNo[idx] ?? null : null);
|
|
173
|
+
}
|
|
174
|
+
} else if (includeOldNo) {
|
|
175
|
+
oldNo.push(...new Array(appendedCount).fill(null));
|
|
176
|
+
}
|
|
177
|
+
if (Array.isArray(next.newNo)) {
|
|
178
|
+
if (!includeNewNo) {
|
|
179
|
+
newNo.push(...new Array(priorLineCount).fill(null));
|
|
180
|
+
includeNewNo = true;
|
|
181
|
+
}
|
|
182
|
+
for (let idx = 0; idx < appendedCount; idx++) {
|
|
183
|
+
newNo.push(idx < next.newNo.length ? next.newNo[idx] ?? null : null);
|
|
184
|
+
}
|
|
185
|
+
} else if (includeNewNo) {
|
|
186
|
+
newNo.push(...new Array(appendedCount).fill(null));
|
|
187
|
+
}
|
|
135
188
|
expectedStart = baseStart + lines.length;
|
|
136
189
|
mergedCount++;
|
|
137
190
|
j++;
|
|
@@ -142,7 +195,11 @@ function mergeAppendLines(window, startIndex) {
|
|
|
142
195
|
const combined = {
|
|
143
196
|
...base,
|
|
144
197
|
lines,
|
|
145
|
-
highlight: highlight.length > 0 ? highlight : void 0
|
|
198
|
+
highlight: highlight.length > 0 ? highlight : void 0,
|
|
199
|
+
tokens: includeTokens && tokens.length > 0 ? tokens : void 0,
|
|
200
|
+
diffKind: includeDiffKind && diffKind.length > 0 ? diffKind : void 0,
|
|
201
|
+
oldNo: includeOldNo && oldNo.length > 0 ? oldNo : void 0,
|
|
202
|
+
newNo: includeNewNo && newNo.length > 0 ? newNo : void 0
|
|
146
203
|
};
|
|
147
204
|
return { patch: combined, nextIndex: j };
|
|
148
205
|
}
|
package/dist/types.d.cts
CHANGED
|
@@ -47,6 +47,8 @@ type FormatAnticipationConfig = boolean | {
|
|
|
47
47
|
mdx?: boolean;
|
|
48
48
|
regex?: boolean;
|
|
49
49
|
};
|
|
50
|
+
type CodeHighlightingMode = "final" | "incremental" | "live";
|
|
51
|
+
type CodeHighlightOutputMode = "html" | "tokens" | "both";
|
|
50
52
|
interface InlineHtmlDescriptor {
|
|
51
53
|
tagName: string;
|
|
52
54
|
attributes: Record<string, string>;
|
|
@@ -109,6 +111,24 @@ type InlineNode = {
|
|
|
109
111
|
label: string;
|
|
110
112
|
number?: number;
|
|
111
113
|
};
|
|
114
|
+
type TokenStyle = {
|
|
115
|
+
fg?: string;
|
|
116
|
+
bg?: string;
|
|
117
|
+
fs?: number;
|
|
118
|
+
};
|
|
119
|
+
type TokenSpan = {
|
|
120
|
+
t: string;
|
|
121
|
+
v?: {
|
|
122
|
+
dark?: TokenStyle;
|
|
123
|
+
light?: TokenStyle;
|
|
124
|
+
};
|
|
125
|
+
s?: TokenStyle;
|
|
126
|
+
};
|
|
127
|
+
type TokenLineV1 = {
|
|
128
|
+
spans: TokenSpan[];
|
|
129
|
+
};
|
|
130
|
+
type DiffKind = "add" | "remove" | "context" | "hunk" | "meta";
|
|
131
|
+
type LazyTokenizationPriority = "visible" | "prefetch";
|
|
112
132
|
/**
|
|
113
133
|
* Worker communication protocol
|
|
114
134
|
*/
|
|
@@ -124,8 +144,14 @@ type WorkerIn = {
|
|
|
124
144
|
callouts?: boolean;
|
|
125
145
|
math?: boolean;
|
|
126
146
|
formatAnticipation?: FormatAnticipationConfig;
|
|
147
|
+
codeHighlighting?: CodeHighlightingMode;
|
|
148
|
+
outputMode?: CodeHighlightOutputMode;
|
|
127
149
|
liveCodeHighlighting?: boolean;
|
|
128
150
|
mdxComponentNames?: string[];
|
|
151
|
+
lazyTokenization?: {
|
|
152
|
+
enabled?: boolean;
|
|
153
|
+
thresholdLines?: number;
|
|
154
|
+
};
|
|
129
155
|
};
|
|
130
156
|
mdx?: {
|
|
131
157
|
compileMode?: "server" | "worker";
|
|
@@ -135,6 +161,14 @@ type WorkerIn = {
|
|
|
135
161
|
text: string;
|
|
136
162
|
} | {
|
|
137
163
|
type: "FINALIZE";
|
|
164
|
+
} | {
|
|
165
|
+
type: "DEBUG_STATE";
|
|
166
|
+
} | {
|
|
167
|
+
type: "TOKENIZE_RANGE";
|
|
168
|
+
blockId: string;
|
|
169
|
+
startLine: number;
|
|
170
|
+
endLine: number;
|
|
171
|
+
priority?: LazyTokenizationPriority;
|
|
138
172
|
} | {
|
|
139
173
|
type: "MDX_COMPILED";
|
|
140
174
|
blockId: string;
|
|
@@ -167,6 +201,23 @@ type WorkerOut = {
|
|
|
167
201
|
} | {
|
|
168
202
|
type: "METRICS";
|
|
169
203
|
metrics: PerformanceMetrics;
|
|
204
|
+
} | {
|
|
205
|
+
type: "DEBUG_STATE";
|
|
206
|
+
state: {
|
|
207
|
+
contentLength: number;
|
|
208
|
+
contentTail: string;
|
|
209
|
+
blockCount: number;
|
|
210
|
+
blockTypeCounts: Record<string, number>;
|
|
211
|
+
lastBlockType?: string;
|
|
212
|
+
lastBlockRange?: {
|
|
213
|
+
from: number;
|
|
214
|
+
to: number;
|
|
215
|
+
};
|
|
216
|
+
lastBlockRawTail?: string;
|
|
217
|
+
hasInlineCodeHeading: boolean;
|
|
218
|
+
hasCodeBlocksHeading: boolean;
|
|
219
|
+
hasMediaHeading: boolean;
|
|
220
|
+
};
|
|
170
221
|
} | {
|
|
171
222
|
type: "ERROR";
|
|
172
223
|
phase: WorkerPhase;
|
|
@@ -241,6 +292,14 @@ interface PerformanceMetrics {
|
|
|
241
292
|
appendLineBatches?: number;
|
|
242
293
|
appendLineTotalLines?: number;
|
|
243
294
|
appendLineMaxLines?: number;
|
|
295
|
+
lazyTokenization?: {
|
|
296
|
+
requests: number;
|
|
297
|
+
avgRangeLines: number;
|
|
298
|
+
maxRangeLines: number;
|
|
299
|
+
avgLatencyMs: number;
|
|
300
|
+
maxLatencyMs: number;
|
|
301
|
+
maxQueue: number;
|
|
302
|
+
};
|
|
244
303
|
}
|
|
245
304
|
/**
|
|
246
305
|
* Incremental patch protocol (initial block-level implementation).
|
|
@@ -299,6 +358,10 @@ type Patch = {
|
|
|
299
358
|
startIndex: number;
|
|
300
359
|
lines: string[];
|
|
301
360
|
highlight?: Array<string | null>;
|
|
361
|
+
tokens?: Array<TokenLineV1 | null>;
|
|
362
|
+
diffKind?: Array<DiffKind | null>;
|
|
363
|
+
oldNo?: Array<number | null>;
|
|
364
|
+
newNo?: Array<number | null>;
|
|
302
365
|
} | {
|
|
303
366
|
op: "setHTML";
|
|
304
367
|
at: NodePath;
|
|
@@ -334,4 +397,4 @@ interface CoalescingMetrics {
|
|
|
334
397
|
insertChildCoalesced: number;
|
|
335
398
|
}
|
|
336
399
|
|
|
337
|
-
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CompiledMdxModule, type FormatAnticipationConfig, type InlineHtmlDescriptor, type InlineNode, type InlinePlugin, LANGUAGE_ALIASES, type MixedContentSegment, type NodePath, type NodeSnapshot, PATCH_ROOT_ID, type Patch, type PatchMetrics, type PerformanceMetrics, type ProtectedRange, type ProtectedRangeKind, type RegexAnticipationPattern, type RegexInlinePlugin, type SetPropsBatchEntry, type WorkerErrorPayload, type WorkerIn, type WorkerOut, type WorkerPhase };
|
|
400
|
+
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CodeHighlightOutputMode, type CodeHighlightingMode, type CompiledMdxModule, type DiffKind, type FormatAnticipationConfig, type InlineHtmlDescriptor, type InlineNode, type InlinePlugin, LANGUAGE_ALIASES, type LazyTokenizationPriority, type MixedContentSegment, type NodePath, type NodeSnapshot, PATCH_ROOT_ID, type Patch, type PatchMetrics, type PerformanceMetrics, type ProtectedRange, type ProtectedRangeKind, type RegexAnticipationPattern, type RegexInlinePlugin, type SetPropsBatchEntry, type TokenLineV1, type TokenSpan, type TokenStyle, type WorkerErrorPayload, type WorkerIn, type WorkerOut, type WorkerPhase };
|
package/dist/types.d.ts
CHANGED
|
@@ -47,6 +47,8 @@ type FormatAnticipationConfig = boolean | {
|
|
|
47
47
|
mdx?: boolean;
|
|
48
48
|
regex?: boolean;
|
|
49
49
|
};
|
|
50
|
+
type CodeHighlightingMode = "final" | "incremental" | "live";
|
|
51
|
+
type CodeHighlightOutputMode = "html" | "tokens" | "both";
|
|
50
52
|
interface InlineHtmlDescriptor {
|
|
51
53
|
tagName: string;
|
|
52
54
|
attributes: Record<string, string>;
|
|
@@ -109,6 +111,24 @@ type InlineNode = {
|
|
|
109
111
|
label: string;
|
|
110
112
|
number?: number;
|
|
111
113
|
};
|
|
114
|
+
type TokenStyle = {
|
|
115
|
+
fg?: string;
|
|
116
|
+
bg?: string;
|
|
117
|
+
fs?: number;
|
|
118
|
+
};
|
|
119
|
+
type TokenSpan = {
|
|
120
|
+
t: string;
|
|
121
|
+
v?: {
|
|
122
|
+
dark?: TokenStyle;
|
|
123
|
+
light?: TokenStyle;
|
|
124
|
+
};
|
|
125
|
+
s?: TokenStyle;
|
|
126
|
+
};
|
|
127
|
+
type TokenLineV1 = {
|
|
128
|
+
spans: TokenSpan[];
|
|
129
|
+
};
|
|
130
|
+
type DiffKind = "add" | "remove" | "context" | "hunk" | "meta";
|
|
131
|
+
type LazyTokenizationPriority = "visible" | "prefetch";
|
|
112
132
|
/**
|
|
113
133
|
* Worker communication protocol
|
|
114
134
|
*/
|
|
@@ -124,8 +144,14 @@ type WorkerIn = {
|
|
|
124
144
|
callouts?: boolean;
|
|
125
145
|
math?: boolean;
|
|
126
146
|
formatAnticipation?: FormatAnticipationConfig;
|
|
147
|
+
codeHighlighting?: CodeHighlightingMode;
|
|
148
|
+
outputMode?: CodeHighlightOutputMode;
|
|
127
149
|
liveCodeHighlighting?: boolean;
|
|
128
150
|
mdxComponentNames?: string[];
|
|
151
|
+
lazyTokenization?: {
|
|
152
|
+
enabled?: boolean;
|
|
153
|
+
thresholdLines?: number;
|
|
154
|
+
};
|
|
129
155
|
};
|
|
130
156
|
mdx?: {
|
|
131
157
|
compileMode?: "server" | "worker";
|
|
@@ -135,6 +161,14 @@ type WorkerIn = {
|
|
|
135
161
|
text: string;
|
|
136
162
|
} | {
|
|
137
163
|
type: "FINALIZE";
|
|
164
|
+
} | {
|
|
165
|
+
type: "DEBUG_STATE";
|
|
166
|
+
} | {
|
|
167
|
+
type: "TOKENIZE_RANGE";
|
|
168
|
+
blockId: string;
|
|
169
|
+
startLine: number;
|
|
170
|
+
endLine: number;
|
|
171
|
+
priority?: LazyTokenizationPriority;
|
|
138
172
|
} | {
|
|
139
173
|
type: "MDX_COMPILED";
|
|
140
174
|
blockId: string;
|
|
@@ -167,6 +201,23 @@ type WorkerOut = {
|
|
|
167
201
|
} | {
|
|
168
202
|
type: "METRICS";
|
|
169
203
|
metrics: PerformanceMetrics;
|
|
204
|
+
} | {
|
|
205
|
+
type: "DEBUG_STATE";
|
|
206
|
+
state: {
|
|
207
|
+
contentLength: number;
|
|
208
|
+
contentTail: string;
|
|
209
|
+
blockCount: number;
|
|
210
|
+
blockTypeCounts: Record<string, number>;
|
|
211
|
+
lastBlockType?: string;
|
|
212
|
+
lastBlockRange?: {
|
|
213
|
+
from: number;
|
|
214
|
+
to: number;
|
|
215
|
+
};
|
|
216
|
+
lastBlockRawTail?: string;
|
|
217
|
+
hasInlineCodeHeading: boolean;
|
|
218
|
+
hasCodeBlocksHeading: boolean;
|
|
219
|
+
hasMediaHeading: boolean;
|
|
220
|
+
};
|
|
170
221
|
} | {
|
|
171
222
|
type: "ERROR";
|
|
172
223
|
phase: WorkerPhase;
|
|
@@ -241,6 +292,14 @@ interface PerformanceMetrics {
|
|
|
241
292
|
appendLineBatches?: number;
|
|
242
293
|
appendLineTotalLines?: number;
|
|
243
294
|
appendLineMaxLines?: number;
|
|
295
|
+
lazyTokenization?: {
|
|
296
|
+
requests: number;
|
|
297
|
+
avgRangeLines: number;
|
|
298
|
+
maxRangeLines: number;
|
|
299
|
+
avgLatencyMs: number;
|
|
300
|
+
maxLatencyMs: number;
|
|
301
|
+
maxQueue: number;
|
|
302
|
+
};
|
|
244
303
|
}
|
|
245
304
|
/**
|
|
246
305
|
* Incremental patch protocol (initial block-level implementation).
|
|
@@ -299,6 +358,10 @@ type Patch = {
|
|
|
299
358
|
startIndex: number;
|
|
300
359
|
lines: string[];
|
|
301
360
|
highlight?: Array<string | null>;
|
|
361
|
+
tokens?: Array<TokenLineV1 | null>;
|
|
362
|
+
diffKind?: Array<DiffKind | null>;
|
|
363
|
+
oldNo?: Array<number | null>;
|
|
364
|
+
newNo?: Array<number | null>;
|
|
302
365
|
} | {
|
|
303
366
|
op: "setHTML";
|
|
304
367
|
at: NodePath;
|
|
@@ -334,4 +397,4 @@ interface CoalescingMetrics {
|
|
|
334
397
|
insertChildCoalesced: number;
|
|
335
398
|
}
|
|
336
399
|
|
|
337
|
-
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CompiledMdxModule, type FormatAnticipationConfig, type InlineHtmlDescriptor, type InlineNode, type InlinePlugin, LANGUAGE_ALIASES, type MixedContentSegment, type NodePath, type NodeSnapshot, PATCH_ROOT_ID, type Patch, type PatchMetrics, type PerformanceMetrics, type ProtectedRange, type ProtectedRangeKind, type RegexAnticipationPattern, type RegexInlinePlugin, type SetPropsBatchEntry, type WorkerErrorPayload, type WorkerIn, type WorkerOut, type WorkerPhase };
|
|
400
|
+
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CodeHighlightOutputMode, type CodeHighlightingMode, type CompiledMdxModule, type DiffKind, type FormatAnticipationConfig, type InlineHtmlDescriptor, type InlineNode, type InlinePlugin, LANGUAGE_ALIASES, type LazyTokenizationPriority, type MixedContentSegment, type NodePath, type NodeSnapshot, PATCH_ROOT_ID, type Patch, type PatchMetrics, type PerformanceMetrics, type ProtectedRange, type ProtectedRangeKind, type RegexAnticipationPattern, type RegexInlinePlugin, type SetPropsBatchEntry, type TokenLineV1, type TokenSpan, type TokenStyle, type WorkerErrorPayload, type WorkerIn, type WorkerOut, type WorkerPhase };
|
package/dist/utils.cjs
CHANGED
|
@@ -91,23 +91,33 @@ function getBlockKey(block) {
|
|
|
91
91
|
}
|
|
92
92
|
function detectMDX(content, options) {
|
|
93
93
|
const inlineCodeRanges = collectInlineCodeRanges(content);
|
|
94
|
+
const protectedRanges = options?.protectedRanges ?? [];
|
|
95
|
+
const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
|
|
96
|
+
const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block", "html-inline", "html-block", "autolink"]) : null;
|
|
94
97
|
const componentPattern = /<([A-Z][\w-]*)(\s|\/?>)/g;
|
|
95
98
|
let componentMatch = componentPattern.exec(content);
|
|
96
99
|
while (componentMatch !== null) {
|
|
97
100
|
const start = componentMatch.index;
|
|
98
101
|
const end = start + componentMatch[0].length;
|
|
99
|
-
if (
|
|
100
|
-
|
|
102
|
+
if (isWithinRanges(start, end, inlineCodeRanges)) {
|
|
103
|
+
componentMatch = componentPattern.exec(content);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (protectedKinds) {
|
|
107
|
+
const absoluteStart = baseOffset + start;
|
|
108
|
+
const absoluteEnd = baseOffset + end;
|
|
109
|
+
const covered = protectedRanges.some((range) => protectedKinds.has(range.kind) && range.from <= absoluteStart && range.to >= absoluteEnd);
|
|
110
|
+
if (covered) {
|
|
111
|
+
componentMatch = componentPattern.exec(content);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
101
114
|
}
|
|
102
|
-
|
|
115
|
+
return true;
|
|
103
116
|
}
|
|
104
117
|
if (/(^|\n)\s*(import|export)\s/.test(content)) {
|
|
105
118
|
return true;
|
|
106
119
|
}
|
|
107
120
|
const expressionPattern = /\{[^{}]+\}/g;
|
|
108
|
-
const protectedRanges = options?.protectedRanges ?? [];
|
|
109
|
-
const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
|
|
110
|
-
const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block"]) : null;
|
|
111
121
|
for (let match = expressionPattern.exec(content); match !== null; match = expressionPattern.exec(content)) {
|
|
112
122
|
const index = match.index;
|
|
113
123
|
const prev = index > 0 ? content[index - 1] : "";
|
package/dist/utils.mjs
CHANGED
|
@@ -55,23 +55,33 @@ function getBlockKey(block) {
|
|
|
55
55
|
}
|
|
56
56
|
function detectMDX(content, options) {
|
|
57
57
|
const inlineCodeRanges = collectInlineCodeRanges(content);
|
|
58
|
+
const protectedRanges = options?.protectedRanges ?? [];
|
|
59
|
+
const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
|
|
60
|
+
const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block", "html-inline", "html-block", "autolink"]) : null;
|
|
58
61
|
const componentPattern = /<([A-Z][\w-]*)(\s|\/?>)/g;
|
|
59
62
|
let componentMatch = componentPattern.exec(content);
|
|
60
63
|
while (componentMatch !== null) {
|
|
61
64
|
const start = componentMatch.index;
|
|
62
65
|
const end = start + componentMatch[0].length;
|
|
63
|
-
if (
|
|
64
|
-
|
|
66
|
+
if (isWithinRanges(start, end, inlineCodeRanges)) {
|
|
67
|
+
componentMatch = componentPattern.exec(content);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (protectedKinds) {
|
|
71
|
+
const absoluteStart = baseOffset + start;
|
|
72
|
+
const absoluteEnd = baseOffset + end;
|
|
73
|
+
const covered = protectedRanges.some((range) => protectedKinds.has(range.kind) && range.from <= absoluteStart && range.to >= absoluteEnd);
|
|
74
|
+
if (covered) {
|
|
75
|
+
componentMatch = componentPattern.exec(content);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
|
-
|
|
79
|
+
return true;
|
|
67
80
|
}
|
|
68
81
|
if (/(^|\n)\s*(import|export)\s/.test(content)) {
|
|
69
82
|
return true;
|
|
70
83
|
}
|
|
71
84
|
const expressionPattern = /\{[^{}]+\}/g;
|
|
72
|
-
const protectedRanges = options?.protectedRanges ?? [];
|
|
73
|
-
const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
|
|
74
|
-
const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block"]) : null;
|
|
75
85
|
for (let match = expressionPattern.exec(content); match !== null; match = expressionPattern.exec(content)) {
|
|
76
86
|
const index = match.index;
|
|
77
87
|
const prev = index > 0 ? content[index - 1] : "";
|