@stream-mdx/core 0.1.1 → 0.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/README.md +4 -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 +71 -1
- package/dist/types.d.ts +71 -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,47 @@ 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 DiffLineKind = "meta" | "hunk" | "add" | "del" | "context";
|
|
132
|
+
type ThemedToken = {
|
|
133
|
+
content: string;
|
|
134
|
+
color?: string | null;
|
|
135
|
+
fontStyle?: number | null;
|
|
136
|
+
};
|
|
137
|
+
type ThemedLine = ThemedToken[];
|
|
138
|
+
type DiffLine = {
|
|
139
|
+
kind: DiffLineKind;
|
|
140
|
+
oldNo?: number | null;
|
|
141
|
+
newNo?: number | null;
|
|
142
|
+
raw: string;
|
|
143
|
+
tokens?: ThemedLine | null;
|
|
144
|
+
};
|
|
145
|
+
type DiffBlock = {
|
|
146
|
+
kind: "diff";
|
|
147
|
+
filePath?: string | null;
|
|
148
|
+
language?: string | null;
|
|
149
|
+
lines: DiffLine[];
|
|
150
|
+
additions?: number | null;
|
|
151
|
+
deletions?: number | null;
|
|
152
|
+
unified?: string | null;
|
|
153
|
+
};
|
|
154
|
+
type LazyTokenizationPriority = "visible" | "prefetch";
|
|
112
155
|
/**
|
|
113
156
|
* Worker communication protocol
|
|
114
157
|
*/
|
|
@@ -124,8 +167,17 @@ type WorkerIn = {
|
|
|
124
167
|
callouts?: boolean;
|
|
125
168
|
math?: boolean;
|
|
126
169
|
formatAnticipation?: FormatAnticipationConfig;
|
|
170
|
+
codeHighlighting?: CodeHighlightingMode;
|
|
171
|
+
outputMode?: CodeHighlightOutputMode;
|
|
127
172
|
liveCodeHighlighting?: boolean;
|
|
173
|
+
liveTokenization?: boolean;
|
|
174
|
+
emitHighlightTokens?: boolean;
|
|
175
|
+
emitDiffBlocks?: boolean;
|
|
128
176
|
mdxComponentNames?: string[];
|
|
177
|
+
lazyTokenization?: {
|
|
178
|
+
enabled?: boolean;
|
|
179
|
+
thresholdLines?: number;
|
|
180
|
+
};
|
|
129
181
|
};
|
|
130
182
|
mdx?: {
|
|
131
183
|
compileMode?: "server" | "worker";
|
|
@@ -137,6 +189,12 @@ type WorkerIn = {
|
|
|
137
189
|
type: "FINALIZE";
|
|
138
190
|
} | {
|
|
139
191
|
type: "DEBUG_STATE";
|
|
192
|
+
} | {
|
|
193
|
+
type: "TOKENIZE_RANGE";
|
|
194
|
+
blockId: string;
|
|
195
|
+
startLine: number;
|
|
196
|
+
endLine: number;
|
|
197
|
+
priority?: LazyTokenizationPriority;
|
|
140
198
|
} | {
|
|
141
199
|
type: "MDX_COMPILED";
|
|
142
200
|
blockId: string;
|
|
@@ -260,6 +318,14 @@ interface PerformanceMetrics {
|
|
|
260
318
|
appendLineBatches?: number;
|
|
261
319
|
appendLineTotalLines?: number;
|
|
262
320
|
appendLineMaxLines?: number;
|
|
321
|
+
lazyTokenization?: {
|
|
322
|
+
requests: number;
|
|
323
|
+
avgRangeLines: number;
|
|
324
|
+
maxRangeLines: number;
|
|
325
|
+
avgLatencyMs: number;
|
|
326
|
+
maxLatencyMs: number;
|
|
327
|
+
maxQueue: number;
|
|
328
|
+
};
|
|
263
329
|
}
|
|
264
330
|
/**
|
|
265
331
|
* Incremental patch protocol (initial block-level implementation).
|
|
@@ -318,6 +384,10 @@ type Patch = {
|
|
|
318
384
|
startIndex: number;
|
|
319
385
|
lines: string[];
|
|
320
386
|
highlight?: Array<string | null>;
|
|
387
|
+
tokens?: Array<TokenLineV1 | null>;
|
|
388
|
+
diffKind?: Array<DiffKind | null>;
|
|
389
|
+
oldNo?: Array<number | null>;
|
|
390
|
+
newNo?: Array<number | null>;
|
|
321
391
|
} | {
|
|
322
392
|
op: "setHTML";
|
|
323
393
|
at: NodePath;
|
|
@@ -353,4 +423,4 @@ interface CoalescingMetrics {
|
|
|
353
423
|
insertChildCoalesced: number;
|
|
354
424
|
}
|
|
355
425
|
|
|
356
|
-
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 };
|
|
426
|
+
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CodeHighlightOutputMode, type CodeHighlightingMode, type CompiledMdxModule, type DiffBlock, type DiffKind, type DiffLine, type DiffLineKind, 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 ThemedLine, type ThemedToken, 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,47 @@ 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 DiffLineKind = "meta" | "hunk" | "add" | "del" | "context";
|
|
132
|
+
type ThemedToken = {
|
|
133
|
+
content: string;
|
|
134
|
+
color?: string | null;
|
|
135
|
+
fontStyle?: number | null;
|
|
136
|
+
};
|
|
137
|
+
type ThemedLine = ThemedToken[];
|
|
138
|
+
type DiffLine = {
|
|
139
|
+
kind: DiffLineKind;
|
|
140
|
+
oldNo?: number | null;
|
|
141
|
+
newNo?: number | null;
|
|
142
|
+
raw: string;
|
|
143
|
+
tokens?: ThemedLine | null;
|
|
144
|
+
};
|
|
145
|
+
type DiffBlock = {
|
|
146
|
+
kind: "diff";
|
|
147
|
+
filePath?: string | null;
|
|
148
|
+
language?: string | null;
|
|
149
|
+
lines: DiffLine[];
|
|
150
|
+
additions?: number | null;
|
|
151
|
+
deletions?: number | null;
|
|
152
|
+
unified?: string | null;
|
|
153
|
+
};
|
|
154
|
+
type LazyTokenizationPriority = "visible" | "prefetch";
|
|
112
155
|
/**
|
|
113
156
|
* Worker communication protocol
|
|
114
157
|
*/
|
|
@@ -124,8 +167,17 @@ type WorkerIn = {
|
|
|
124
167
|
callouts?: boolean;
|
|
125
168
|
math?: boolean;
|
|
126
169
|
formatAnticipation?: FormatAnticipationConfig;
|
|
170
|
+
codeHighlighting?: CodeHighlightingMode;
|
|
171
|
+
outputMode?: CodeHighlightOutputMode;
|
|
127
172
|
liveCodeHighlighting?: boolean;
|
|
173
|
+
liveTokenization?: boolean;
|
|
174
|
+
emitHighlightTokens?: boolean;
|
|
175
|
+
emitDiffBlocks?: boolean;
|
|
128
176
|
mdxComponentNames?: string[];
|
|
177
|
+
lazyTokenization?: {
|
|
178
|
+
enabled?: boolean;
|
|
179
|
+
thresholdLines?: number;
|
|
180
|
+
};
|
|
129
181
|
};
|
|
130
182
|
mdx?: {
|
|
131
183
|
compileMode?: "server" | "worker";
|
|
@@ -137,6 +189,12 @@ type WorkerIn = {
|
|
|
137
189
|
type: "FINALIZE";
|
|
138
190
|
} | {
|
|
139
191
|
type: "DEBUG_STATE";
|
|
192
|
+
} | {
|
|
193
|
+
type: "TOKENIZE_RANGE";
|
|
194
|
+
blockId: string;
|
|
195
|
+
startLine: number;
|
|
196
|
+
endLine: number;
|
|
197
|
+
priority?: LazyTokenizationPriority;
|
|
140
198
|
} | {
|
|
141
199
|
type: "MDX_COMPILED";
|
|
142
200
|
blockId: string;
|
|
@@ -260,6 +318,14 @@ interface PerformanceMetrics {
|
|
|
260
318
|
appendLineBatches?: number;
|
|
261
319
|
appendLineTotalLines?: number;
|
|
262
320
|
appendLineMaxLines?: number;
|
|
321
|
+
lazyTokenization?: {
|
|
322
|
+
requests: number;
|
|
323
|
+
avgRangeLines: number;
|
|
324
|
+
maxRangeLines: number;
|
|
325
|
+
avgLatencyMs: number;
|
|
326
|
+
maxLatencyMs: number;
|
|
327
|
+
maxQueue: number;
|
|
328
|
+
};
|
|
263
329
|
}
|
|
264
330
|
/**
|
|
265
331
|
* Incremental patch protocol (initial block-level implementation).
|
|
@@ -318,6 +384,10 @@ type Patch = {
|
|
|
318
384
|
startIndex: number;
|
|
319
385
|
lines: string[];
|
|
320
386
|
highlight?: Array<string | null>;
|
|
387
|
+
tokens?: Array<TokenLineV1 | null>;
|
|
388
|
+
diffKind?: Array<DiffKind | null>;
|
|
389
|
+
oldNo?: Array<number | null>;
|
|
390
|
+
newNo?: Array<number | null>;
|
|
321
391
|
} | {
|
|
322
392
|
op: "setHTML";
|
|
323
393
|
at: NodePath;
|
|
@@ -353,4 +423,4 @@ interface CoalescingMetrics {
|
|
|
353
423
|
insertChildCoalesced: number;
|
|
354
424
|
}
|
|
355
425
|
|
|
356
|
-
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 };
|
|
426
|
+
export { type ASTInlinePlugin, type Block, type CoalescingMetrics, type CodeHighlightOutputMode, type CodeHighlightingMode, type CompiledMdxModule, type DiffBlock, type DiffKind, type DiffLine, type DiffLineKind, 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 ThemedLine, type ThemedToken, 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] : "";
|