@stream-mdx/core 0.0.2 → 0.1.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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # @stream-mdx/core
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 294e557: Release StreamMDX 0.1.0 across all published packages.
8
+
9
+ ## 0.0.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 47d1374: Add opt-in streaming format anticipation and an optional Mermaid diagram addon for ` ```mermaid ` code blocks.
14
+ - 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.
15
+
3
16
  ## 0.0.2
4
17
 
5
18
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -72,8 +72,10 @@ __export(index_exports, {
72
72
  inlineNodesToPlainText: () => inlineNodesToPlainText,
73
73
  isLikelyMdxComponent: () => isLikelyMdxComponent,
74
74
  normalizeBlockquoteText: () => normalizeBlockquoteText,
75
+ normalizeFormatAnticipation: () => normalizeFormatAnticipation,
75
76
  normalizeLang: () => normalizeLang,
76
77
  parseCodeFenceInfo: () => parseCodeFenceInfo,
78
+ prepareInlineStreamingContent: () => prepareInlineStreamingContent,
77
79
  removeHeadingMarkers: () => removeHeadingMarkers,
78
80
  sanitizeCodeHTML: () => sanitizeCodeHTML,
79
81
  sanitizeHTML: () => sanitizeHTML,
@@ -289,12 +291,42 @@ function filterAllowedAttributes(attrs) {
289
291
  }
290
292
 
291
293
  // src/inline-parser.ts
294
+ function ensureGlobal(pattern) {
295
+ if (pattern.global) return pattern;
296
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
297
+ return new RegExp(pattern.source, flags);
298
+ }
299
+ function findLastMatch(pattern, value) {
300
+ const re = ensureGlobal(pattern);
301
+ let match = null;
302
+ let next;
303
+ while ((next = re.exec(value)) !== null) {
304
+ match = next;
305
+ }
306
+ return match;
307
+ }
308
+ function findMatchAfter(pattern, value, startIndex) {
309
+ const re = ensureGlobal(pattern);
310
+ re.lastIndex = Math.max(0, startIndex);
311
+ return re.exec(value);
312
+ }
313
+ function isSamePattern(a, b) {
314
+ return a.source === b.source && a.flags === b.flags;
315
+ }
316
+ function countMatches(pattern, value) {
317
+ const re = ensureGlobal(pattern);
318
+ let count = 0;
319
+ while (re.exec(value)) {
320
+ count += 1;
321
+ }
322
+ return count;
323
+ }
292
324
  var InlineParser = class {
293
325
  constructor(options = {}) {
294
326
  this.plugins = [];
295
327
  this.cache = /* @__PURE__ */ new Map();
296
328
  this.maxCacheEntries = Number.isFinite(options.maxCacheEntries ?? Number.NaN) ? Math.max(0, options.maxCacheEntries ?? 0) : 2e3;
297
- this.registerDefaultPlugins();
329
+ this.registerDefaultPlugins({ enableMath: options.enableMath !== false });
298
330
  }
299
331
  /**
300
332
  * Register a plugin with the parser
@@ -336,6 +368,42 @@ var InlineParser = class {
336
368
  }
337
369
  return result;
338
370
  }
371
+ /**
372
+ * Streaming regex anticipation helper. Returns an append string if a plugin
373
+ * declares an incomplete match at the end of the buffer.
374
+ */
375
+ getRegexAnticipationAppend(content) {
376
+ if (!content || this.plugins.length === 0) {
377
+ return null;
378
+ }
379
+ for (const plugin of this.plugins) {
380
+ if (!("re" in plugin)) continue;
381
+ const regexPlugin = plugin;
382
+ const anticipation = regexPlugin.anticipation;
383
+ if (!anticipation) continue;
384
+ const maxScanChars = Number.isFinite(anticipation.maxScanChars ?? Number.NaN) ? Math.max(1, anticipation.maxScanChars ?? 0) : 240;
385
+ const scan = content.slice(Math.max(0, content.length - maxScanChars));
386
+ if (regexPlugin.fastCheck && !regexPlugin.fastCheck(scan)) {
387
+ continue;
388
+ }
389
+ const lastStart = findLastMatch(anticipation.start, scan);
390
+ if (!lastStart) continue;
391
+ if (isSamePattern(anticipation.start, anticipation.end)) {
392
+ const occurrences = countMatches(anticipation.start, scan);
393
+ if (occurrences % 2 === 0) {
394
+ continue;
395
+ }
396
+ } else {
397
+ const startIndex = lastStart.index + lastStart[0].length;
398
+ const hasEnd = Boolean(findMatchAfter(anticipation.end, scan, startIndex));
399
+ if (hasEnd) continue;
400
+ }
401
+ const appendValue = typeof anticipation.append === "function" ? anticipation.append(lastStart, content) : anticipation.append;
402
+ if (!appendValue) continue;
403
+ return appendValue;
404
+ }
405
+ return null;
406
+ }
339
407
  /**
340
408
  * Clear the memoization cache
341
409
  */
@@ -360,10 +428,27 @@ var InlineParser = class {
360
428
  * Register default plugins with proper precedence ordering
361
429
  * Lower priority numbers = higher precedence (run first)
362
430
  */
363
- registerDefaultPlugins() {
431
+ registerDefaultPlugins(options) {
432
+ if (options.enableMath) {
433
+ this.registerPlugin({
434
+ id: "math-display",
435
+ priority: 0,
436
+ re: /\$\$([\s\S]+?)\$\$/g,
437
+ toNode: (match) => ({ kind: "math-display", tex: match[1].trim() }),
438
+ fastCheck: (text) => text.indexOf("$$") !== -1
439
+ });
440
+ this.registerPlugin({
441
+ id: "math-inline",
442
+ priority: 1,
443
+ re: /\$([^$\n]+?)\$/g,
444
+ // Non-greedy to prevent spanning multiple expressions
445
+ toNode: (match) => ({ kind: "math-inline", tex: match[1].trim() }),
446
+ fastCheck: (text) => text.indexOf("$") !== -1
447
+ });
448
+ }
364
449
  this.registerPlugin({
365
450
  id: "escaped-character",
366
- priority: 0,
451
+ priority: 2,
367
452
  re: /\\([\\`*_{}\[\]()#+\-.!>])/g,
368
453
  toNode: (match) => ({
369
454
  kind: "text",
@@ -372,19 +457,11 @@ var InlineParser = class {
372
457
  fastCheck: (text) => text.indexOf("\\") !== -1
373
458
  });
374
459
  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",
460
+ id: "hard-break",
383
461
  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
462
+ re: /\\\r?\n| {2,}\r?\n/g,
463
+ toNode: (_match) => ({ kind: "br" }),
464
+ fastCheck: (text) => text.indexOf("\n") !== -1 || text.indexOf("\r") !== -1
388
465
  });
389
466
  this.registerPlugin({
390
467
  id: "code-spans",
@@ -455,9 +532,16 @@ var InlineParser = class {
455
532
  this.registerPlugin({
456
533
  id: "citations",
457
534
  priority: 10,
458
- re: /\[\^([^\]]+)\]|@cite\{([^}]+)\}/g,
459
- toNode: (match) => ({ kind: "citation", id: match[1] || match[2] }),
460
- fastCheck: (text) => text.indexOf("@") !== -1 || text.indexOf("[^") !== -1
535
+ re: /\[\^([^\]\n]+)\]|@cite\{([^}\n]+)\}|\{cite:([^}\n]+)\}/g,
536
+ toNode: (match) => ({ kind: "citation", id: match[1] || match[2] || match[3] }),
537
+ fastCheck: (text) => text.indexOf("@cite") !== -1 || text.indexOf("[^") !== -1 || text.indexOf("{cite:") !== -1,
538
+ anticipation: {
539
+ start: /@cite\{|\{cite:/g,
540
+ end: /\}/g,
541
+ full: /@cite\{[^}\n]+?\}|\{cite:[^}\n]+?\}/g,
542
+ append: "}",
543
+ maxScanChars: 120
544
+ }
461
545
  });
462
546
  this.registerPlugin({
463
547
  id: "mentions",
@@ -557,9 +641,23 @@ var rehypeParse = __toESM(require("rehype-parse"), 1);
557
641
  var rehypeSanitize = __toESM(require("rehype-sanitize"), 1);
558
642
  var rehypeStringify = __toESM(require("rehype-stringify"), 1);
559
643
  var import_unified = require("unified");
560
- var { defaultSchema } = rehypeSanitize;
644
+ var rehypeSanitizeModule = rehypeSanitize;
645
+ var defaultSchema = rehypeSanitizeModule.defaultSchema;
646
+ var resolvePlugin = (mod) => {
647
+ if (typeof mod === "function") return mod;
648
+ if (mod && typeof mod.default === "function") {
649
+ return mod.default;
650
+ }
651
+ if (mod && typeof mod.default?.default === "function") {
652
+ return mod.default?.default;
653
+ }
654
+ return mod;
655
+ };
656
+ var rehypeParsePlugin = resolvePlugin(rehypeParse);
657
+ var rehypeSanitizePlugin = resolvePlugin(rehypeSanitizeModule);
658
+ var rehypeStringifyPlugin = resolvePlugin(rehypeStringify);
561
659
  var SANITIZED_SCHEMA = createSchema();
562
- var sanitizeProcessor = (0, import_unified.unified)().use(rehypeParse.default, { fragment: true }).use(rehypeSanitize.default, SANITIZED_SCHEMA).use(rehypeStringify.default).freeze();
660
+ var sanitizeProcessor = (0, import_unified.unified)().use(rehypeParsePlugin, { fragment: true }).use(rehypeSanitizePlugin, SANITIZED_SCHEMA).use(rehypeStringifyPlugin).freeze();
563
661
  function sanitizeHtmlInWorker(html) {
564
662
  if (!html) return "";
565
663
  try {
@@ -675,9 +773,27 @@ function mergeAttributes(existing, additions) {
675
773
  }
676
774
 
677
775
  // src/mixed-content.ts
678
- function extractMixedContentSegments(raw, baseOffset, parseInline) {
776
+ var DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS = /* @__PURE__ */ new Set([
777
+ "span",
778
+ "em",
779
+ "strong",
780
+ "code",
781
+ "kbd",
782
+ "del",
783
+ "s",
784
+ "mark",
785
+ "sub",
786
+ "sup",
787
+ "i",
788
+ "b",
789
+ "u",
790
+ "small",
791
+ "abbr",
792
+ "a"
793
+ ]);
794
+ function extractMixedContentSegments(raw, baseOffset, parseInline, options) {
679
795
  if (!raw) return [];
680
- const initial = splitByTagSegments(raw, baseOffset, parseInline);
796
+ const initial = splitByTagSegments(raw, baseOffset, parseInline, options);
681
797
  const expanded = [];
682
798
  for (const segment of initial) {
683
799
  if (segment.kind === "text") {
@@ -688,22 +804,58 @@ function extractMixedContentSegments(raw, baseOffset, parseInline) {
688
804
  }
689
805
  return mergeAdjacentTextSegments(expanded, parseInline);
690
806
  }
691
- function splitByTagSegments(source, baseOffset, parseInline) {
807
+ function splitByTagSegments(source, baseOffset, parseInline, options) {
692
808
  const segments = [];
693
809
  const lowerSource = source.toLowerCase();
694
810
  const tagPattern = /<([A-Za-z][\w:-]*)([^<>]*?)\/?>/g;
695
811
  let cursor = 0;
696
812
  let match = tagPattern.exec(source);
697
813
  const baseIsFinite = typeof baseOffset === "number" && Number.isFinite(baseOffset);
814
+ const htmlAllowTags = normalizeHtmlAllowlist(options?.html?.allowTags);
815
+ const htmlAutoClose = options?.html?.autoClose === true;
816
+ const htmlMaxNewlines = normalizeNewlineLimit(options?.html?.maxNewlines);
817
+ const mdxAutoClose = options?.mdx?.autoClose === true;
818
+ const mdxMaxNewlines = normalizeNewlineLimit(options?.mdx?.maxNewlines);
819
+ const mdxAllowlist = normalizeComponentAllowlist(options?.mdx?.componentAllowlist);
698
820
  while (match !== null) {
699
821
  const start = match.index;
700
822
  const tagName = match[1];
701
823
  const matchText = match[0];
702
- const isSelfClosing = matchText.endsWith("/>") || isVoidHtmlTag(tagName);
824
+ const tagNameLower = tagName.toLowerCase();
825
+ const isSelfClosing = matchText.endsWith("/>") || isVoidHtmlTag(tagNameLower);
826
+ const mdxCandidate = isLikelyMdxComponent(tagName);
827
+ const mdxAllowed = mdxCandidate && (!mdxAllowlist || mdxAllowlist.has(tagName));
828
+ if (mdxCandidate && mdxAllowlist && !mdxAllowed) {
829
+ tagPattern.lastIndex = start + 1;
830
+ match = tagPattern.exec(source);
831
+ continue;
832
+ }
703
833
  let end = tagPattern.lastIndex;
704
- if (!isSelfClosing && !isLikelyMdxComponent(tagName)) {
834
+ if (!isSelfClosing && !mdxAllowed) {
705
835
  const closingIndex = findClosingHtmlTag(lowerSource, tagName.toLowerCase(), end);
706
836
  if (closingIndex === -1) {
837
+ if (htmlAutoClose && htmlAllowTags.has(tagNameLower)) {
838
+ const tail = source.slice(end);
839
+ const newlineCount = countNewlines(tail, htmlMaxNewlines + 1);
840
+ if (newlineCount <= htmlMaxNewlines) {
841
+ if (start > cursor) {
842
+ const absoluteFrom = baseIsFinite ? baseOffset + cursor : void 0;
843
+ const absoluteTo = baseIsFinite ? baseOffset + start : void 0;
844
+ pushTextSegment(segments, source.slice(cursor, start), absoluteFrom, absoluteTo, parseInline);
845
+ }
846
+ const rawSegment2 = source.slice(start);
847
+ const closedValue = `${rawSegment2}</${tagName}>`;
848
+ const segment2 = {
849
+ kind: "html",
850
+ value: closedValue,
851
+ range: createSegmentRange(baseOffset, start, source.length),
852
+ sanitized: sanitizeHtmlInWorker(closedValue)
853
+ };
854
+ segments.push(segment2);
855
+ cursor = source.length;
856
+ break;
857
+ }
858
+ }
707
859
  tagPattern.lastIndex = start + 1;
708
860
  match = tagPattern.exec(source);
709
861
  continue;
@@ -715,8 +867,8 @@ function splitByTagSegments(source, baseOffset, parseInline) {
715
867
  const absoluteTo = baseIsFinite ? baseOffset + start : void 0;
716
868
  pushTextSegment(segments, source.slice(cursor, start), absoluteFrom, absoluteTo, parseInline);
717
869
  }
718
- const rawSegment = source.slice(start, end);
719
- const kind = isLikelyMdxComponent(tagName) ? "mdx" : "html";
870
+ let rawSegment = source.slice(start, end);
871
+ const kind = mdxAllowed ? "mdx" : "html";
720
872
  const segment = {
721
873
  kind,
722
874
  value: rawSegment,
@@ -725,6 +877,17 @@ function splitByTagSegments(source, baseOffset, parseInline) {
725
877
  if (kind === "html") {
726
878
  segment.sanitized = sanitizeHtmlInWorker(rawSegment);
727
879
  } else {
880
+ const tail = source.slice(end);
881
+ const newlineCount = countNewlines(tail, mdxMaxNewlines + 1);
882
+ if (mdxAutoClose && newlineCount > mdxMaxNewlines) {
883
+ tagPattern.lastIndex = start + 1;
884
+ match = tagPattern.exec(source);
885
+ continue;
886
+ }
887
+ if (mdxAutoClose && !rawSegment.endsWith("/>")) {
888
+ rawSegment = selfCloseTag(rawSegment);
889
+ segment.value = rawSegment;
890
+ }
728
891
  segment.status = "pending";
729
892
  }
730
893
  segments.push(segment);
@@ -849,6 +1012,48 @@ var VOID_HTML_TAGS = /* @__PURE__ */ new Set(["br", "hr", "img", "meta", "input"
849
1012
  function isVoidHtmlTag(tagName) {
850
1013
  return VOID_HTML_TAGS.has(tagName.toLowerCase());
851
1014
  }
1015
+ function normalizeNewlineLimit(value) {
1016
+ if (!Number.isFinite(value ?? Number.NaN)) {
1017
+ return 2;
1018
+ }
1019
+ return Math.max(0, value ?? 0);
1020
+ }
1021
+ function normalizeHtmlAllowlist(value) {
1022
+ if (!value) return DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS;
1023
+ const tags = /* @__PURE__ */ new Set();
1024
+ for (const tag of value) {
1025
+ if (tag) {
1026
+ tags.add(tag.toLowerCase());
1027
+ }
1028
+ }
1029
+ return tags.size > 0 ? tags : DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS;
1030
+ }
1031
+ function normalizeComponentAllowlist(value) {
1032
+ if (!value) return null;
1033
+ const tags = /* @__PURE__ */ new Set();
1034
+ for (const tag of value) {
1035
+ if (tag) tags.add(tag);
1036
+ }
1037
+ return tags.size > 0 ? tags : null;
1038
+ }
1039
+ function countNewlines(value, limit) {
1040
+ let count = 0;
1041
+ for (let i = 0; i < value.length; i++) {
1042
+ if (value.charCodeAt(i) === 10) {
1043
+ count += 1;
1044
+ if (limit !== void 0 && count >= limit) {
1045
+ return count;
1046
+ }
1047
+ }
1048
+ }
1049
+ return count;
1050
+ }
1051
+ function selfCloseTag(rawTag) {
1052
+ if (rawTag.endsWith("/>")) return rawTag;
1053
+ const closeIndex = rawTag.lastIndexOf(">");
1054
+ if (closeIndex === -1) return rawTag;
1055
+ return `${rawTag.slice(0, closeIndex)}/>`;
1056
+ }
852
1057
  function isLikelyMdxComponent(tagName) {
853
1058
  const first = tagName.charAt(0);
854
1059
  return first.toUpperCase() === first && first.toLowerCase() !== first;
@@ -2799,6 +3004,130 @@ var CustomStreamingMatcher = class {
2799
3004
  return false;
2800
3005
  }
2801
3006
  };
3007
+
3008
+ // src/streaming/inline-streaming.ts
3009
+ var DEFAULT_FORMAT_ANTICIPATION = {
3010
+ inline: false,
3011
+ mathInline: false,
3012
+ mathBlock: false,
3013
+ html: false,
3014
+ mdx: false,
3015
+ regex: false
3016
+ };
3017
+ function normalizeFormatAnticipation(input) {
3018
+ if (input === true) {
3019
+ return { ...DEFAULT_FORMAT_ANTICIPATION, inline: true };
3020
+ }
3021
+ if (!input) {
3022
+ return { ...DEFAULT_FORMAT_ANTICIPATION };
3023
+ }
3024
+ return {
3025
+ inline: input.inline ?? false,
3026
+ mathInline: input.mathInline ?? false,
3027
+ mathBlock: input.mathBlock ?? false,
3028
+ html: input.html ?? false,
3029
+ mdx: input.mdx ?? false,
3030
+ regex: input.regex ?? false
3031
+ };
3032
+ }
3033
+ function prepareInlineStreamingContent(content, options) {
3034
+ const enableMath = options?.math !== false;
3035
+ const anticipation = normalizeFormatAnticipation(options?.formatAnticipation);
3036
+ const enableInlineAnticipation = anticipation.inline;
3037
+ const enableMathInlineAnticipation = anticipation.mathInline;
3038
+ const enableMathBlockAnticipation = anticipation.mathBlock;
3039
+ const stack = [];
3040
+ const toggleToken = (token) => {
3041
+ const last = stack[stack.length - 1];
3042
+ if (last === token) {
3043
+ stack.pop();
3044
+ } else {
3045
+ stack.push(token);
3046
+ }
3047
+ };
3048
+ let mathDisplayOpen = false;
3049
+ let mathDisplayCrossedNewline = false;
3050
+ for (let i = 0; i < content.length; i++) {
3051
+ const code = content.charCodeAt(i);
3052
+ if (code === 10 || code === 13) {
3053
+ if (mathDisplayOpen) {
3054
+ mathDisplayCrossedNewline = true;
3055
+ }
3056
+ continue;
3057
+ }
3058
+ if (code === 96) {
3059
+ toggleToken("code");
3060
+ continue;
3061
+ }
3062
+ if (code === 126 && i + 1 < content.length && content.charCodeAt(i + 1) === 126) {
3063
+ toggleToken("strike");
3064
+ i += 1;
3065
+ continue;
3066
+ }
3067
+ if (code === 42) {
3068
+ if (i + 1 < content.length && content.charCodeAt(i + 1) === 42) {
3069
+ toggleToken("strong");
3070
+ i += 1;
3071
+ } else {
3072
+ toggleToken("em");
3073
+ }
3074
+ continue;
3075
+ }
3076
+ if (enableMath && code === 36) {
3077
+ if (i + 1 < content.length && content.charCodeAt(i + 1) === 36) {
3078
+ toggleToken("math-display");
3079
+ if (mathDisplayOpen) {
3080
+ mathDisplayOpen = false;
3081
+ mathDisplayCrossedNewline = false;
3082
+ } else {
3083
+ mathDisplayOpen = true;
3084
+ mathDisplayCrossedNewline = false;
3085
+ }
3086
+ i += 1;
3087
+ } else {
3088
+ toggleToken("math-inline");
3089
+ }
3090
+ }
3091
+ }
3092
+ const hasIncompleteFormatting = stack.some((token) => token === "code" || token === "strike" || token === "strong" || token === "em");
3093
+ const hasIncompleteMathInline = stack.includes("math-inline");
3094
+ const hasIncompleteMathDisplay = stack.includes("math-display");
3095
+ const hasIncompleteMath = hasIncompleteMathInline || hasIncompleteMathDisplay;
3096
+ if (enableMath && hasIncompleteMath) {
3097
+ if (hasIncompleteMathInline && !enableMathInlineAnticipation) {
3098
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
3099
+ }
3100
+ if (hasIncompleteMathDisplay && (!enableMathBlockAnticipation || mathDisplayCrossedNewline)) {
3101
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
3102
+ }
3103
+ }
3104
+ if (hasIncompleteFormatting && !enableInlineAnticipation) {
3105
+ return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
3106
+ }
3107
+ if (!hasIncompleteFormatting && !hasIncompleteMath) {
3108
+ return { kind: "parse", status: "complete", content, appended: "" };
3109
+ }
3110
+ const appendForToken = (token) => {
3111
+ switch (token) {
3112
+ case "code":
3113
+ return "`";
3114
+ case "strike":
3115
+ return "~~";
3116
+ case "strong":
3117
+ return "**";
3118
+ case "em":
3119
+ return "*";
3120
+ case "math-inline":
3121
+ return "$";
3122
+ case "math-display":
3123
+ return "$$";
3124
+ default:
3125
+ return "";
3126
+ }
3127
+ };
3128
+ const appended = stack.slice().reverse().map((token) => appendForToken(token)).join("");
3129
+ return { kind: "parse", status: "anticipated", content: content + appended, appended };
3130
+ }
2802
3131
  // Annotate the CommonJS export names for ESM import in node:
2803
3132
  0 && (module.exports = {
2804
3133
  CSP_HEADERS,
@@ -2843,8 +3172,10 @@ var CustomStreamingMatcher = class {
2843
3172
  inlineNodesToPlainText,
2844
3173
  isLikelyMdxComponent,
2845
3174
  normalizeBlockquoteText,
3175
+ normalizeFormatAnticipation,
2846
3176
  normalizeLang,
2847
3177
  parseCodeFenceInfo,
3178
+ prepareInlineStreamingContent,
2848
3179
  removeHeadingMarkers,
2849
3180
  sanitizeCodeHTML,
2850
3181
  sanitizeHTML,
package/dist/index.d.cts CHANGED
@@ -1,14 +1,15 @@
1
1
  import { Block, NodeSnapshot, InlineNode, Patch } from './types.cjs';
2
- export { ASTInlinePlugin, CoalescingMetrics, CompiledMdxModule, InlineHtmlDescriptor, InlinePlugin, LANGUAGE_ALIASES, MixedContentSegment, NodePath, PATCH_ROOT_ID, PatchMetrics, PerformanceMetrics, ProtectedRange, ProtectedRangeKind, RegexInlinePlugin, SetPropsBatchEntry, WorkerErrorPayload, WorkerIn, WorkerOut, WorkerPhase } from './types.cjs';
2
+ export { ASTInlinePlugin, CoalescingMetrics, CompiledMdxModule, FormatAnticipationConfig, InlineHtmlDescriptor, InlinePlugin, LANGUAGE_ALIASES, MixedContentSegment, NodePath, PATCH_ROOT_ID, PatchMetrics, PerformanceMetrics, ProtectedRange, ProtectedRangeKind, RegexAnticipationPattern, RegexInlinePlugin, SetPropsBatchEntry, WorkerErrorPayload, WorkerIn, WorkerOut, WorkerPhase } from './types.cjs';
3
3
  export { HighlightedLine, dedentIndentedCode, extractCodeLines, extractCodeWrapperAttributes, extractHighlightedLines, stripCodeFence } from './code-highlighting.cjs';
4
4
  export { PerformanceTimer, StringBuffer, applyUpdate, debounce, detectMDX, generateBlockId, getBlockKey, normalizeBlockquoteText, normalizeLang, parseCodeFenceInfo, removeHeadingMarkers } from './utils.cjs';
5
- export { extractMixedContentSegments, findClosingHtmlTag, isLikelyMdxComponent } from './mixed-content.cjs';
5
+ export { MixedContentAutoCloseHtmlOptions, MixedContentAutoCloseMdxOptions, MixedContentOptions, extractMixedContentSegments, findClosingHtmlTag, isLikelyMdxComponent } from './mixed-content.cjs';
6
6
  export { CSP_HEADERS, SanitizationPolicy, createSanitizationConfig, createTrustedHTML, initializeSecurity, initializeTrustedTypesPolicy, sanitizeCodeHTML, sanitizeHTML, sanitizeMathHTML, sanitizeURL } from './security.cjs';
7
7
  export { InlineParseOptions, InlineParser, InlineParserOptions, applyASTPlugin, applyRegexPlugin } from './inline-parser.cjs';
8
8
  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, NormalizedFormatAnticipation, normalizeFormatAnticipation, 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
@@ -1,14 +1,15 @@
1
1
  import { Block, NodeSnapshot, InlineNode, Patch } from './types.js';
2
- export { ASTInlinePlugin, CoalescingMetrics, CompiledMdxModule, InlineHtmlDescriptor, InlinePlugin, LANGUAGE_ALIASES, MixedContentSegment, NodePath, PATCH_ROOT_ID, PatchMetrics, PerformanceMetrics, ProtectedRange, ProtectedRangeKind, RegexInlinePlugin, SetPropsBatchEntry, WorkerErrorPayload, WorkerIn, WorkerOut, WorkerPhase } from './types.js';
2
+ export { ASTInlinePlugin, CoalescingMetrics, CompiledMdxModule, FormatAnticipationConfig, InlineHtmlDescriptor, InlinePlugin, LANGUAGE_ALIASES, MixedContentSegment, NodePath, PATCH_ROOT_ID, PatchMetrics, PerformanceMetrics, ProtectedRange, ProtectedRangeKind, RegexAnticipationPattern, RegexInlinePlugin, SetPropsBatchEntry, WorkerErrorPayload, WorkerIn, WorkerOut, WorkerPhase } from './types.js';
3
3
  export { HighlightedLine, dedentIndentedCode, extractCodeLines, extractCodeWrapperAttributes, extractHighlightedLines, stripCodeFence } from './code-highlighting.js';
4
4
  export { PerformanceTimer, StringBuffer, applyUpdate, debounce, detectMDX, generateBlockId, getBlockKey, normalizeBlockquoteText, normalizeLang, parseCodeFenceInfo, removeHeadingMarkers } from './utils.js';
5
- export { extractMixedContentSegments, findClosingHtmlTag, isLikelyMdxComponent } from './mixed-content.js';
5
+ export { MixedContentAutoCloseHtmlOptions, MixedContentAutoCloseMdxOptions, MixedContentOptions, extractMixedContentSegments, findClosingHtmlTag, isLikelyMdxComponent } from './mixed-content.js';
6
6
  export { CSP_HEADERS, SanitizationPolicy, createSanitizationConfig, createTrustedHTML, initializeSecurity, initializeTrustedTypesPolicy, sanitizeCodeHTML, sanitizeHTML, sanitizeMathHTML, sanitizeURL } from './security.js';
7
7
  export { InlineParseOptions, InlineParser, InlineParserOptions, applyASTPlugin, applyRegexPlugin } from './inline-parser.js';
8
8
  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, NormalizedFormatAnticipation, normalizeFormatAnticipation, prepareInlineStreamingContent } from './streaming/inline-streaming.js';
12
13
  import 'dompurify';
13
14
 
14
15
  declare function cloneBlock(block: Block): Block;