@stream-mdx/core 0.0.2 → 0.0.3
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 +7 -0
- package/dist/index.cjs +87 -15
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +86 -15
- package/dist/inline-parser.cjs +24 -15
- package/dist/inline-parser.d.cts +5 -0
- package/dist/inline-parser.d.ts +5 -0
- package/dist/inline-parser.mjs +24 -15
- package/dist/streaming/inline-streaming.cjs +88 -0
- package/dist/streaming/inline-streaming.d.cts +17 -0
- package/dist/streaming/inline-streaming.d.ts +17 -0
- package/dist/streaming/inline-streaming.mjs +63 -0
- package/dist/types.d.cts +3 -0
- package/dist/types.d.ts +3 -0
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @stream-mdx/core
|
|
2
2
|
|
|
3
|
+
## 0.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 47d1374: Add opt-in streaming format anticipation and an optional Mermaid diagram addon for ` ```mermaid ` code blocks.
|
|
8
|
+
- 7c79f09: Port the docs demo page to match the ql-homepage streaming UI, and fix several streaming parser/rendering edge cases (hard line breaks and display-math handling) while keeping the hosted worker bundle self-contained for static hosting.
|
|
9
|
+
|
|
3
10
|
## 0.0.2
|
|
4
11
|
|
|
5
12
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,7 @@ __export(index_exports, {
|
|
|
74
74
|
normalizeBlockquoteText: () => normalizeBlockquoteText,
|
|
75
75
|
normalizeLang: () => normalizeLang,
|
|
76
76
|
parseCodeFenceInfo: () => parseCodeFenceInfo,
|
|
77
|
+
prepareInlineStreamingContent: () => prepareInlineStreamingContent,
|
|
77
78
|
removeHeadingMarkers: () => removeHeadingMarkers,
|
|
78
79
|
sanitizeCodeHTML: () => sanitizeCodeHTML,
|
|
79
80
|
sanitizeHTML: () => sanitizeHTML,
|
|
@@ -294,7 +295,7 @@ var InlineParser = class {
|
|
|
294
295
|
this.plugins = [];
|
|
295
296
|
this.cache = /* @__PURE__ */ new Map();
|
|
296
297
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
297
|
-
this.registerDefaultPlugins();
|
|
298
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
298
299
|
}
|
|
299
300
|
/**
|
|
300
301
|
* Register a plugin with the parser
|
|
@@ -360,10 +361,27 @@ var InlineParser = class {
|
|
|
360
361
|
* Register default plugins with proper precedence ordering
|
|
361
362
|
* Lower priority numbers = higher precedence (run first)
|
|
362
363
|
*/
|
|
363
|
-
registerDefaultPlugins() {
|
|
364
|
+
registerDefaultPlugins(options) {
|
|
365
|
+
if (options.enableMath) {
|
|
366
|
+
this.registerPlugin({
|
|
367
|
+
id: "math-display",
|
|
368
|
+
priority: 0,
|
|
369
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
370
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
371
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
372
|
+
});
|
|
373
|
+
this.registerPlugin({
|
|
374
|
+
id: "math-inline",
|
|
375
|
+
priority: 1,
|
|
376
|
+
re: /\$([^$\n]+?)\$/g,
|
|
377
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
378
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
379
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
380
|
+
});
|
|
381
|
+
}
|
|
364
382
|
this.registerPlugin({
|
|
365
383
|
id: "escaped-character",
|
|
366
|
-
priority:
|
|
384
|
+
priority: 2,
|
|
367
385
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
368
386
|
toNode: (match) => ({
|
|
369
387
|
kind: "text",
|
|
@@ -372,19 +390,11 @@ var InlineParser = class {
|
|
|
372
390
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
373
391
|
});
|
|
374
392
|
this.registerPlugin({
|
|
375
|
-
id: "
|
|
376
|
-
priority: 1,
|
|
377
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
378
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
379
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
380
|
-
});
|
|
381
|
-
this.registerPlugin({
|
|
382
|
-
id: "math-inline",
|
|
393
|
+
id: "hard-break",
|
|
383
394
|
priority: 2,
|
|
384
|
-
re:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
395
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
396
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
397
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
388
398
|
});
|
|
389
399
|
this.registerPlugin({
|
|
390
400
|
id: "code-spans",
|
|
@@ -2799,6 +2809,67 @@ var CustomStreamingMatcher = class {
|
|
|
2799
2809
|
return false;
|
|
2800
2810
|
}
|
|
2801
2811
|
};
|
|
2812
|
+
|
|
2813
|
+
// src/streaming/inline-streaming.ts
|
|
2814
|
+
function prepareInlineStreamingContent(content, options) {
|
|
2815
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
2816
|
+
const enableMath = options?.math !== false;
|
|
2817
|
+
let dollarCount = 0;
|
|
2818
|
+
let backtickCount = 0;
|
|
2819
|
+
let starCount = 0;
|
|
2820
|
+
let doubleStarCount = 0;
|
|
2821
|
+
let tildePairCount = 0;
|
|
2822
|
+
for (let i = 0; i < content.length; i++) {
|
|
2823
|
+
const code = content.charCodeAt(i);
|
|
2824
|
+
if (code === 36) {
|
|
2825
|
+
dollarCount += 1;
|
|
2826
|
+
continue;
|
|
2827
|
+
}
|
|
2828
|
+
if (code === 96) {
|
|
2829
|
+
backtickCount += 1;
|
|
2830
|
+
continue;
|
|
2831
|
+
}
|
|
2832
|
+
if (code === 42) {
|
|
2833
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
2834
|
+
doubleStarCount += 1;
|
|
2835
|
+
starCount += 2;
|
|
2836
|
+
i += 1;
|
|
2837
|
+
} else {
|
|
2838
|
+
starCount += 1;
|
|
2839
|
+
}
|
|
2840
|
+
continue;
|
|
2841
|
+
}
|
|
2842
|
+
if (code === 126) {
|
|
2843
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
2844
|
+
tildePairCount += 1;
|
|
2845
|
+
i += 1;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
2850
|
+
if (hasIncompleteMath) {
|
|
2851
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
2852
|
+
}
|
|
2853
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
2854
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
2855
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
2856
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
2857
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
2858
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
2859
|
+
if (!hasAnyIncomplete) {
|
|
2860
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
2861
|
+
}
|
|
2862
|
+
if (!enableAnticipation) {
|
|
2863
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
2864
|
+
}
|
|
2865
|
+
let appended = "";
|
|
2866
|
+
if (hasIncompleteCode) appended += "`";
|
|
2867
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
2868
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
2869
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
2870
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
2871
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
2872
|
+
}
|
|
2802
2873
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2803
2874
|
0 && (module.exports = {
|
|
2804
2875
|
CSP_HEADERS,
|
|
@@ -2845,6 +2916,7 @@ var CustomStreamingMatcher = class {
|
|
|
2845
2916
|
normalizeBlockquoteText,
|
|
2846
2917
|
normalizeLang,
|
|
2847
2918
|
parseCodeFenceInfo,
|
|
2919
|
+
prepareInlineStreamingContent,
|
|
2848
2920
|
removeHeadingMarkers,
|
|
2849
2921
|
sanitizeCodeHTML,
|
|
2850
2922
|
sanitizeHTML,
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,7 @@ export { sanitizeHtmlInWorker } from './worker-html-sanitizer.cjs';
|
|
|
9
9
|
export { BackpressureConfig, DEFAULT_BACKPRESSURE_CONFIG, calculateRawCredit, calculateSmoothedCredit, clampCredit, computeHeavyPatchBudget, smoothCredit } from './perf/backpressure.cjs';
|
|
10
10
|
export { CoalesceConfig, DEFAULT_COALESCE_CONFIG, coalescePatches, coalescePatchesLinear, coalescePatchesQuadratic, coalescePatchesWithMetrics } from './perf/patch-coalescing.cjs';
|
|
11
11
|
export { CustomStreamingMatcher, MatchResult } from './streaming/custom-matcher.cjs';
|
|
12
|
+
export { InlineStreamingInlineStatus, InlineStreamingPrepareResult, prepareInlineStreamingContent } from './streaming/inline-streaming.cjs';
|
|
12
13
|
import 'dompurify';
|
|
13
14
|
|
|
14
15
|
declare function cloneBlock(block: Block): Block;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { sanitizeHtmlInWorker } from './worker-html-sanitizer.js';
|
|
|
9
9
|
export { BackpressureConfig, DEFAULT_BACKPRESSURE_CONFIG, calculateRawCredit, calculateSmoothedCredit, clampCredit, computeHeavyPatchBudget, smoothCredit } from './perf/backpressure.js';
|
|
10
10
|
export { CoalesceConfig, DEFAULT_COALESCE_CONFIG, coalescePatches, coalescePatchesLinear, coalescePatchesQuadratic, coalescePatchesWithMetrics } from './perf/patch-coalescing.js';
|
|
11
11
|
export { CustomStreamingMatcher, MatchResult } from './streaming/custom-matcher.js';
|
|
12
|
+
export { InlineStreamingInlineStatus, InlineStreamingPrepareResult, prepareInlineStreamingContent } from './streaming/inline-streaming.js';
|
|
12
13
|
import 'dompurify';
|
|
13
14
|
|
|
14
15
|
declare function cloneBlock(block: Block): Block;
|
package/dist/index.mjs
CHANGED
|
@@ -207,7 +207,7 @@ var InlineParser = class {
|
|
|
207
207
|
this.plugins = [];
|
|
208
208
|
this.cache = /* @__PURE__ */ new Map();
|
|
209
209
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
210
|
-
this.registerDefaultPlugins();
|
|
210
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Register a plugin with the parser
|
|
@@ -273,10 +273,27 @@ var InlineParser = class {
|
|
|
273
273
|
* Register default plugins with proper precedence ordering
|
|
274
274
|
* Lower priority numbers = higher precedence (run first)
|
|
275
275
|
*/
|
|
276
|
-
registerDefaultPlugins() {
|
|
276
|
+
registerDefaultPlugins(options) {
|
|
277
|
+
if (options.enableMath) {
|
|
278
|
+
this.registerPlugin({
|
|
279
|
+
id: "math-display",
|
|
280
|
+
priority: 0,
|
|
281
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
282
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
283
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
284
|
+
});
|
|
285
|
+
this.registerPlugin({
|
|
286
|
+
id: "math-inline",
|
|
287
|
+
priority: 1,
|
|
288
|
+
re: /\$([^$\n]+?)\$/g,
|
|
289
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
290
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
291
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
292
|
+
});
|
|
293
|
+
}
|
|
277
294
|
this.registerPlugin({
|
|
278
295
|
id: "escaped-character",
|
|
279
|
-
priority:
|
|
296
|
+
priority: 2,
|
|
280
297
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
281
298
|
toNode: (match) => ({
|
|
282
299
|
kind: "text",
|
|
@@ -285,19 +302,11 @@ var InlineParser = class {
|
|
|
285
302
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
286
303
|
});
|
|
287
304
|
this.registerPlugin({
|
|
288
|
-
id: "
|
|
289
|
-
priority: 1,
|
|
290
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
291
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
292
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
293
|
-
});
|
|
294
|
-
this.registerPlugin({
|
|
295
|
-
id: "math-inline",
|
|
305
|
+
id: "hard-break",
|
|
296
306
|
priority: 2,
|
|
297
|
-
re:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
307
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
308
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
309
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
301
310
|
});
|
|
302
311
|
this.registerPlugin({
|
|
303
312
|
id: "code-spans",
|
|
@@ -2712,6 +2721,67 @@ var CustomStreamingMatcher = class {
|
|
|
2712
2721
|
return false;
|
|
2713
2722
|
}
|
|
2714
2723
|
};
|
|
2724
|
+
|
|
2725
|
+
// src/streaming/inline-streaming.ts
|
|
2726
|
+
function prepareInlineStreamingContent(content, options) {
|
|
2727
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
2728
|
+
const enableMath = options?.math !== false;
|
|
2729
|
+
let dollarCount = 0;
|
|
2730
|
+
let backtickCount = 0;
|
|
2731
|
+
let starCount = 0;
|
|
2732
|
+
let doubleStarCount = 0;
|
|
2733
|
+
let tildePairCount = 0;
|
|
2734
|
+
for (let i = 0; i < content.length; i++) {
|
|
2735
|
+
const code = content.charCodeAt(i);
|
|
2736
|
+
if (code === 36) {
|
|
2737
|
+
dollarCount += 1;
|
|
2738
|
+
continue;
|
|
2739
|
+
}
|
|
2740
|
+
if (code === 96) {
|
|
2741
|
+
backtickCount += 1;
|
|
2742
|
+
continue;
|
|
2743
|
+
}
|
|
2744
|
+
if (code === 42) {
|
|
2745
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
2746
|
+
doubleStarCount += 1;
|
|
2747
|
+
starCount += 2;
|
|
2748
|
+
i += 1;
|
|
2749
|
+
} else {
|
|
2750
|
+
starCount += 1;
|
|
2751
|
+
}
|
|
2752
|
+
continue;
|
|
2753
|
+
}
|
|
2754
|
+
if (code === 126) {
|
|
2755
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
2756
|
+
tildePairCount += 1;
|
|
2757
|
+
i += 1;
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
2762
|
+
if (hasIncompleteMath) {
|
|
2763
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
2764
|
+
}
|
|
2765
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
2766
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
2767
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
2768
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
2769
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
2770
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
2771
|
+
if (!hasAnyIncomplete) {
|
|
2772
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
2773
|
+
}
|
|
2774
|
+
if (!enableAnticipation) {
|
|
2775
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
2776
|
+
}
|
|
2777
|
+
let appended = "";
|
|
2778
|
+
if (hasIncompleteCode) appended += "`";
|
|
2779
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
2780
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
2781
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
2782
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
2783
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
2784
|
+
}
|
|
2715
2785
|
export {
|
|
2716
2786
|
CSP_HEADERS,
|
|
2717
2787
|
CustomStreamingMatcher,
|
|
@@ -2757,6 +2827,7 @@ export {
|
|
|
2757
2827
|
normalizeBlockquoteText,
|
|
2758
2828
|
normalizeLang,
|
|
2759
2829
|
parseCodeFenceInfo,
|
|
2830
|
+
prepareInlineStreamingContent,
|
|
2760
2831
|
removeHeadingMarkers,
|
|
2761
2832
|
sanitizeCodeHTML,
|
|
2762
2833
|
sanitizeHTML,
|
package/dist/inline-parser.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var InlineParser = class {
|
|
|
30
30
|
this.plugins = [];
|
|
31
31
|
this.cache = /* @__PURE__ */ new Map();
|
|
32
32
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
33
|
-
this.registerDefaultPlugins();
|
|
33
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Register a plugin with the parser
|
|
@@ -96,10 +96,27 @@ var InlineParser = class {
|
|
|
96
96
|
* Register default plugins with proper precedence ordering
|
|
97
97
|
* Lower priority numbers = higher precedence (run first)
|
|
98
98
|
*/
|
|
99
|
-
registerDefaultPlugins() {
|
|
99
|
+
registerDefaultPlugins(options) {
|
|
100
|
+
if (options.enableMath) {
|
|
101
|
+
this.registerPlugin({
|
|
102
|
+
id: "math-display",
|
|
103
|
+
priority: 0,
|
|
104
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
105
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
106
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
107
|
+
});
|
|
108
|
+
this.registerPlugin({
|
|
109
|
+
id: "math-inline",
|
|
110
|
+
priority: 1,
|
|
111
|
+
re: /\$([^$\n]+?)\$/g,
|
|
112
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
113
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
114
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
115
|
+
});
|
|
116
|
+
}
|
|
100
117
|
this.registerPlugin({
|
|
101
118
|
id: "escaped-character",
|
|
102
|
-
priority:
|
|
119
|
+
priority: 2,
|
|
103
120
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
104
121
|
toNode: (match) => ({
|
|
105
122
|
kind: "text",
|
|
@@ -108,19 +125,11 @@ var InlineParser = class {
|
|
|
108
125
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
109
126
|
});
|
|
110
127
|
this.registerPlugin({
|
|
111
|
-
id: "
|
|
112
|
-
priority: 1,
|
|
113
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
114
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
115
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
116
|
-
});
|
|
117
|
-
this.registerPlugin({
|
|
118
|
-
id: "math-inline",
|
|
128
|
+
id: "hard-break",
|
|
119
129
|
priority: 2,
|
|
120
|
-
re:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
130
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
131
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
132
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
124
133
|
});
|
|
125
134
|
this.registerPlugin({
|
|
126
135
|
id: "code-spans",
|
package/dist/inline-parser.d.cts
CHANGED
|
@@ -7,6 +7,11 @@ interface InlineParserOptions {
|
|
|
7
7
|
* parsing many intermediate states.
|
|
8
8
|
*/
|
|
9
9
|
maxCacheEntries?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Enable parsing `$...$` and `$$...$$` math nodes.
|
|
12
|
+
* Defaults to `true`.
|
|
13
|
+
*/
|
|
14
|
+
enableMath?: boolean;
|
|
10
15
|
}
|
|
11
16
|
interface InlineParseOptions {
|
|
12
17
|
/**
|
package/dist/inline-parser.d.ts
CHANGED
|
@@ -7,6 +7,11 @@ interface InlineParserOptions {
|
|
|
7
7
|
* parsing many intermediate states.
|
|
8
8
|
*/
|
|
9
9
|
maxCacheEntries?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Enable parsing `$...$` and `$$...$$` math nodes.
|
|
12
|
+
* Defaults to `true`.
|
|
13
|
+
*/
|
|
14
|
+
enableMath?: boolean;
|
|
10
15
|
}
|
|
11
16
|
interface InlineParseOptions {
|
|
12
17
|
/**
|
package/dist/inline-parser.mjs
CHANGED
|
@@ -4,7 +4,7 @@ var InlineParser = class {
|
|
|
4
4
|
this.plugins = [];
|
|
5
5
|
this.cache = /* @__PURE__ */ new Map();
|
|
6
6
|
this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
|
|
7
|
-
this.registerDefaultPlugins();
|
|
7
|
+
this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Register a plugin with the parser
|
|
@@ -70,10 +70,27 @@ var InlineParser = class {
|
|
|
70
70
|
* Register default plugins with proper precedence ordering
|
|
71
71
|
* Lower priority numbers = higher precedence (run first)
|
|
72
72
|
*/
|
|
73
|
-
registerDefaultPlugins() {
|
|
73
|
+
registerDefaultPlugins(options) {
|
|
74
|
+
if (options.enableMath) {
|
|
75
|
+
this.registerPlugin({
|
|
76
|
+
id: "math-display",
|
|
77
|
+
priority: 0,
|
|
78
|
+
re: /\$\$([\s\S]+?)\$\$/g,
|
|
79
|
+
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
80
|
+
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
81
|
+
});
|
|
82
|
+
this.registerPlugin({
|
|
83
|
+
id: "math-inline",
|
|
84
|
+
priority: 1,
|
|
85
|
+
re: /\$([^$\n]+?)\$/g,
|
|
86
|
+
// Non-greedy to prevent spanning multiple expressions
|
|
87
|
+
toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
|
|
88
|
+
fastCheck: (text) => text.indexOf("$") !== -1
|
|
89
|
+
});
|
|
90
|
+
}
|
|
74
91
|
this.registerPlugin({
|
|
75
92
|
id: "escaped-character",
|
|
76
|
-
priority:
|
|
93
|
+
priority: 2,
|
|
77
94
|
re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
|
|
78
95
|
toNode: (match) => ({
|
|
79
96
|
kind: "text",
|
|
@@ -82,19 +99,11 @@ var InlineParser = class {
|
|
|
82
99
|
fastCheck: (text) => text.indexOf("\\") !== -1
|
|
83
100
|
});
|
|
84
101
|
this.registerPlugin({
|
|
85
|
-
id: "
|
|
86
|
-
priority: 1,
|
|
87
|
-
re: /\$\$([^$]+?)\$\$/g,
|
|
88
|
-
toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
|
|
89
|
-
fastCheck: (text) => text.indexOf("$$") !== -1
|
|
90
|
-
});
|
|
91
|
-
this.registerPlugin({
|
|
92
|
-
id: "math-inline",
|
|
102
|
+
id: "hard-break",
|
|
93
103
|
priority: 2,
|
|
94
|
-
re:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
fastCheck: (text) => text.indexOf("$") !== -1
|
|
104
|
+
re: /\\\r?\n| {2,}\r?\n/g,
|
|
105
|
+
toNode: (_match) => ({ kind: "br" }),
|
|
106
|
+
fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
|
|
98
107
|
});
|
|
99
108
|
this.registerPlugin({
|
|
100
109
|
id: "code-spans",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/streaming/inline-streaming.ts
|
|
21
|
+
var inline_streaming_exports = {};
|
|
22
|
+
__export(inline_streaming_exports, {
|
|
23
|
+
prepareInlineStreamingContent: () => prepareInlineStreamingContent
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(inline_streaming_exports);
|
|
26
|
+
function prepareInlineStreamingContent(content, options) {
|
|
27
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
28
|
+
const enableMath = options?.math !== false;
|
|
29
|
+
let dollarCount = 0;
|
|
30
|
+
let backtickCount = 0;
|
|
31
|
+
let starCount = 0;
|
|
32
|
+
let doubleStarCount = 0;
|
|
33
|
+
let tildePairCount = 0;
|
|
34
|
+
for (let i = 0; i < content.length; i++) {
|
|
35
|
+
const code = content.charCodeAt(i);
|
|
36
|
+
if (code === 36) {
|
|
37
|
+
dollarCount += 1;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (code === 96) {
|
|
41
|
+
backtickCount += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (code === 42) {
|
|
45
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
46
|
+
doubleStarCount += 1;
|
|
47
|
+
starCount += 2;
|
|
48
|
+
i += 1;
|
|
49
|
+
} else {
|
|
50
|
+
starCount += 1;
|
|
51
|
+
}
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (code === 126) {
|
|
55
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
56
|
+
tildePairCount += 1;
|
|
57
|
+
i += 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
62
|
+
if (hasIncompleteMath) {
|
|
63
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
64
|
+
}
|
|
65
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
66
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
67
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
68
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
69
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
70
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
71
|
+
if (!hasAnyIncomplete) {
|
|
72
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
73
|
+
}
|
|
74
|
+
if (!enableAnticipation) {
|
|
75
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
76
|
+
}
|
|
77
|
+
let appended = "";
|
|
78
|
+
if (hasIncompleteCode) appended += "`";
|
|
79
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
80
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
81
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
82
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
83
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
84
|
+
}
|
|
85
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
86
|
+
0 && (module.exports = {
|
|
87
|
+
prepareInlineStreamingContent
|
|
88
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type InlineStreamingInlineStatus = "complete" | "anticipated" | "raw";
|
|
2
|
+
type InlineStreamingPrepareResult = {
|
|
3
|
+
kind: "raw";
|
|
4
|
+
status: "raw";
|
|
5
|
+
reason: "incomplete-math" | "incomplete-formatting";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "parse";
|
|
8
|
+
status: Exclude<InlineStreamingInlineStatus, "raw">;
|
|
9
|
+
content: string;
|
|
10
|
+
appended: string;
|
|
11
|
+
};
|
|
12
|
+
declare function prepareInlineStreamingContent(content: string, options?: {
|
|
13
|
+
formatAnticipation?: boolean;
|
|
14
|
+
math?: boolean;
|
|
15
|
+
}): InlineStreamingPrepareResult;
|
|
16
|
+
|
|
17
|
+
export { type InlineStreamingInlineStatus, type InlineStreamingPrepareResult, prepareInlineStreamingContent };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type InlineStreamingInlineStatus = "complete" | "anticipated" | "raw";
|
|
2
|
+
type InlineStreamingPrepareResult = {
|
|
3
|
+
kind: "raw";
|
|
4
|
+
status: "raw";
|
|
5
|
+
reason: "incomplete-math" | "incomplete-formatting";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "parse";
|
|
8
|
+
status: Exclude<InlineStreamingInlineStatus, "raw">;
|
|
9
|
+
content: string;
|
|
10
|
+
appended: string;
|
|
11
|
+
};
|
|
12
|
+
declare function prepareInlineStreamingContent(content: string, options?: {
|
|
13
|
+
formatAnticipation?: boolean;
|
|
14
|
+
math?: boolean;
|
|
15
|
+
}): InlineStreamingPrepareResult;
|
|
16
|
+
|
|
17
|
+
export { type InlineStreamingInlineStatus, type InlineStreamingPrepareResult, prepareInlineStreamingContent };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// src/streaming/inline-streaming.ts
|
|
2
|
+
function prepareInlineStreamingContent(content, options) {
|
|
3
|
+
const enableAnticipation = Boolean(options?.formatAnticipation);
|
|
4
|
+
const enableMath = options?.math !== false;
|
|
5
|
+
let dollarCount = 0;
|
|
6
|
+
let backtickCount = 0;
|
|
7
|
+
let starCount = 0;
|
|
8
|
+
let doubleStarCount = 0;
|
|
9
|
+
let tildePairCount = 0;
|
|
10
|
+
for (let i = 0; i < content.length; i++) {
|
|
11
|
+
const code = content.charCodeAt(i);
|
|
12
|
+
if (code === 36) {
|
|
13
|
+
dollarCount += 1;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (code === 96) {
|
|
17
|
+
backtickCount += 1;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (code === 42) {
|
|
21
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
|
|
22
|
+
doubleStarCount += 1;
|
|
23
|
+
starCount += 2;
|
|
24
|
+
i += 1;
|
|
25
|
+
} else {
|
|
26
|
+
starCount += 1;
|
|
27
|
+
}
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (code === 126) {
|
|
31
|
+
if (i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
|
|
32
|
+
tildePairCount += 1;
|
|
33
|
+
i += 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const hasIncompleteMath = enableMath && dollarCount % 2 !== 0;
|
|
38
|
+
if (hasIncompleteMath) {
|
|
39
|
+
return { kind: "raw", status: "raw", reason: "incomplete-math" };
|
|
40
|
+
}
|
|
41
|
+
const hasIncompleteCode = backtickCount % 2 !== 0;
|
|
42
|
+
const hasIncompleteStrong = doubleStarCount % 2 !== 0;
|
|
43
|
+
const singleStarCount = starCount - doubleStarCount * 2;
|
|
44
|
+
const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
|
|
45
|
+
const hasIncompleteStrike = tildePairCount % 2 !== 0;
|
|
46
|
+
const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
|
|
47
|
+
if (!hasAnyIncomplete) {
|
|
48
|
+
return { kind: "parse", status: "complete", content, appended: "" };
|
|
49
|
+
}
|
|
50
|
+
if (!enableAnticipation) {
|
|
51
|
+
return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
|
|
52
|
+
}
|
|
53
|
+
let appended = "";
|
|
54
|
+
if (hasIncompleteCode) appended += "`";
|
|
55
|
+
if (hasIncompleteStrike) appended += "~~";
|
|
56
|
+
if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
|
|
57
|
+
else if (hasIncompleteStrong) appended += "**";
|
|
58
|
+
else if (hasIncompleteEmphasis) appended += "*";
|
|
59
|
+
return { kind: "parse", status: "anticipated", content: content + appended, appended };
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
prepareInlineStreamingContent
|
|
63
|
+
};
|
package/dist/types.d.cts
CHANGED
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-mdx/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Core types, snapshot utilities, and perf helpers for the Streaming Markdown V2 stack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -75,6 +75,11 @@
|
|
|
75
75
|
"types": "./dist/streaming/custom-matcher.d.ts",
|
|
76
76
|
"import": "./dist/streaming/custom-matcher.mjs",
|
|
77
77
|
"require": "./dist/streaming/custom-matcher.cjs"
|
|
78
|
+
},
|
|
79
|
+
"./streaming/inline-streaming": {
|
|
80
|
+
"types": "./dist/streaming/inline-streaming.d.ts",
|
|
81
|
+
"import": "./dist/streaming/inline-streaming.mjs",
|
|
82
|
+
"require": "./dist/streaming/inline-streaming.cjs"
|
|
78
83
|
}
|
|
79
84
|
},
|
|
80
85
|
"files": [
|