@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 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: 0,
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: "math-display",
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: /\$([^$\n]+?)\$/g,
385
- // Non-greedy to prevent spanning multiple expressions
386
- toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
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: 0,
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: "math-display",
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: /\$([^$\n]+?)\$/g,
298
- // Non-greedy to prevent spanning multiple expressions
299
- toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
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,
@@ -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: 0,
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: "math-display",
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: /\$([^$\n]+?)\$/g,
121
- // Non-greedy to prevent spanning multiple expressions
122
- toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
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",
@@ -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
  /**
@@ -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
  /**
@@ -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: 0,
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: "math-display",
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: /\$([^$\n]+?)\$/g,
95
- // Non-greedy to prevent spanning multiple expressions
96
- toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
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
@@ -114,6 +114,9 @@ type WorkerIn = {
114
114
  mdx?: boolean;
115
115
  tables?: boolean;
116
116
  callouts?: boolean;
117
+ math?: boolean;
118
+ formatAnticipation?: boolean;
119
+ liveCodeHighlighting?: boolean;
117
120
  };
118
121
  mdx?: {
119
122
  compileMode?: "server" | "worker";
package/dist/types.d.ts CHANGED
@@ -114,6 +114,9 @@ type WorkerIn = {
114
114
  mdx?: boolean;
115
115
  tables?: boolean;
116
116
  callouts?: boolean;
117
+ math?: boolean;
118
+ formatAnticipation?: boolean;
119
+ liveCodeHighlighting?: boolean;
117
120
  };
118
121
  mdx?: {
119
122
  compileMode?: "server" | "worker";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-mdx/core",
3
- "version": "0.0.2",
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": [