@stream-mdx/worker 0.0.3 → 0.1.1

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,26 @@
1
1
  # @stream-mdx/worker
2
2
 
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Refine streaming scheduling and list layout, add worker append batching/debug state support, and refresh docs/README examples.
8
+ - Updated dependencies
9
+ - @stream-mdx/core@0.1.1
10
+ - @stream-mdx/plugins@0.1.1
11
+
12
+ ## 0.1.0
13
+
14
+ ### Minor Changes
15
+
16
+ - 294e557: Release StreamMDX 0.1.0 across all published packages.
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [294e557]
21
+ - @stream-mdx/core@0.1.0
22
+ - @stream-mdx/plugins@0.1.0
23
+
3
24
  ## 0.0.3
4
25
 
5
26
  ### Patch Changes
@@ -30993,6 +30993,12 @@ var {
30993
30993
  createHighlighter
30994
30994
  );
30995
30995
 
30996
+ // ../../node_modules/rehype-parse/index.js
30997
+ var rehype_parse_exports = {};
30998
+ __export(rehype_parse_exports, {
30999
+ default: () => rehypeParse
31000
+ });
31001
+
30996
31002
  // ../../node_modules/devlop/lib/default.js
30997
31003
  function ok() {
30998
31004
  }
@@ -41377,6 +41383,12 @@ function rehypeSanitize(options) {
41377
41383
  };
41378
41384
  }
41379
41385
 
41386
+ // ../../node_modules/rehype-stringify/index.js
41387
+ var rehype_stringify_exports = {};
41388
+ __export(rehype_stringify_exports, {
41389
+ default: () => rehypeStringify
41390
+ });
41391
+
41380
41392
  // ../../node_modules/rehype-stringify/lib/index.js
41381
41393
  function rehypeStringify(options) {
41382
41394
  const self2 = this;
@@ -43371,6 +43383,36 @@ function filterAllowedAttributes(attrs) {
43371
43383
  }
43372
43384
  return filtered;
43373
43385
  }
43386
+ function ensureGlobal(pattern) {
43387
+ if (pattern.global) return pattern;
43388
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
43389
+ return new RegExp(pattern.source, flags);
43390
+ }
43391
+ function findLastMatch(pattern, value) {
43392
+ const re2 = ensureGlobal(pattern);
43393
+ let match = null;
43394
+ let next2;
43395
+ while ((next2 = re2.exec(value)) !== null) {
43396
+ match = next2;
43397
+ }
43398
+ return match;
43399
+ }
43400
+ function findMatchAfter(pattern, value, startIndex) {
43401
+ const re2 = ensureGlobal(pattern);
43402
+ re2.lastIndex = Math.max(0, startIndex);
43403
+ return re2.exec(value);
43404
+ }
43405
+ function isSamePattern(a, b) {
43406
+ return a.source === b.source && a.flags === b.flags;
43407
+ }
43408
+ function countMatches(pattern, value) {
43409
+ const re2 = ensureGlobal(pattern);
43410
+ let count = 0;
43411
+ while (re2.exec(value)) {
43412
+ count += 1;
43413
+ }
43414
+ return count;
43415
+ }
43374
43416
  var InlineParser = class {
43375
43417
  constructor(options = {}) {
43376
43418
  this.plugins = [];
@@ -43418,6 +43460,42 @@ var InlineParser = class {
43418
43460
  }
43419
43461
  return result;
43420
43462
  }
43463
+ /**
43464
+ * Streaming regex anticipation helper. Returns an append string if a plugin
43465
+ * declares an incomplete match at the end of the buffer.
43466
+ */
43467
+ getRegexAnticipationAppend(content4) {
43468
+ if (!content4 || this.plugins.length === 0) {
43469
+ return null;
43470
+ }
43471
+ for (const plugin of this.plugins) {
43472
+ if (!("re" in plugin)) continue;
43473
+ const regexPlugin = plugin;
43474
+ const anticipation = regexPlugin.anticipation;
43475
+ if (!anticipation) continue;
43476
+ const maxScanChars = Number.isFinite(anticipation.maxScanChars ?? Number.NaN) ? Math.max(1, anticipation.maxScanChars ?? 0) : 240;
43477
+ const scan = content4.slice(Math.max(0, content4.length - maxScanChars));
43478
+ if (regexPlugin.fastCheck && !regexPlugin.fastCheck(scan)) {
43479
+ continue;
43480
+ }
43481
+ const lastStart = findLastMatch(anticipation.start, scan);
43482
+ if (!lastStart) continue;
43483
+ if (isSamePattern(anticipation.start, anticipation.end)) {
43484
+ const occurrences = countMatches(anticipation.start, scan);
43485
+ if (occurrences % 2 === 0) {
43486
+ continue;
43487
+ }
43488
+ } else {
43489
+ const startIndex = lastStart.index + lastStart[0].length;
43490
+ const hasEnd = Boolean(findMatchAfter(anticipation.end, scan, startIndex));
43491
+ if (hasEnd) continue;
43492
+ }
43493
+ const appendValue = typeof anticipation.append === "function" ? anticipation.append(lastStart, content4) : anticipation.append;
43494
+ if (!appendValue) continue;
43495
+ return appendValue;
43496
+ }
43497
+ return null;
43498
+ }
43421
43499
  /**
43422
43500
  * Clear the memoization cache
43423
43501
  */
@@ -43546,9 +43624,16 @@ var InlineParser = class {
43546
43624
  this.registerPlugin({
43547
43625
  id: "citations",
43548
43626
  priority: 10,
43549
- re: /\[\^([^\]]+)\]|@cite\{([^}]+)\}/g,
43550
- toNode: (match) => ({ kind: "citation", id: match[1] || match[2] }),
43551
- fastCheck: (text12) => text12.indexOf("@") !== -1 || text12.indexOf("[^") !== -1
43627
+ re: /\[\^([^\]\n]+)\]|@cite\{([^}\n]+)\}|\{cite:([^}\n]+)\}/g,
43628
+ toNode: (match) => ({ kind: "citation", id: match[1] || match[2] || match[3] }),
43629
+ fastCheck: (text12) => text12.indexOf("@cite") !== -1 || text12.indexOf("[^") !== -1 || text12.indexOf("{cite:") !== -1,
43630
+ anticipation: {
43631
+ start: /@cite\{|\{cite:/g,
43632
+ end: /\}/g,
43633
+ full: /@cite\{[^}\n]+?\}|\{cite:[^}\n]+?\}/g,
43634
+ append: "}",
43635
+ maxScanChars: 120
43636
+ }
43552
43637
  });
43553
43638
  this.registerPlugin({
43554
43639
  id: "mentions",
@@ -43612,9 +43697,23 @@ function splitTextByRegexWithPrecedence(text12, regex3, toNode3) {
43612
43697
  }
43613
43698
  return result;
43614
43699
  }
43615
- var { defaultSchema: defaultSchema2 } = rehype_sanitize_exports;
43700
+ var rehypeSanitizeModule = rehype_sanitize_exports;
43701
+ var defaultSchema2 = rehypeSanitizeModule.defaultSchema;
43702
+ var resolvePlugin = (mod) => {
43703
+ if (typeof mod === "function") return mod;
43704
+ if (mod && typeof mod.default === "function") {
43705
+ return mod.default;
43706
+ }
43707
+ if (mod && typeof mod.default?.default === "function") {
43708
+ return mod.default?.default;
43709
+ }
43710
+ return mod;
43711
+ };
43712
+ var rehypeParsePlugin = resolvePlugin(rehype_parse_exports);
43713
+ var rehypeSanitizePlugin = resolvePlugin(rehypeSanitizeModule);
43714
+ var rehypeStringifyPlugin = resolvePlugin(rehype_stringify_exports);
43616
43715
  var SANITIZED_SCHEMA = createSchema();
43617
- var sanitizeProcessor = unified().use(rehypeParse, { fragment: true }).use(rehypeSanitize, SANITIZED_SCHEMA).use(rehypeStringify).freeze();
43716
+ var sanitizeProcessor = unified().use(rehypeParsePlugin, { fragment: true }).use(rehypeSanitizePlugin, SANITIZED_SCHEMA).use(rehypeStringifyPlugin).freeze();
43618
43717
  function sanitizeHtmlInWorker(html9) {
43619
43718
  if (!html9) return "";
43620
43719
  try {
@@ -43728,9 +43827,27 @@ function mergeAttributes(existing, additions) {
43728
43827
  }
43729
43828
  return next2;
43730
43829
  }
43731
- function extractMixedContentSegments(raw2, baseOffset, parseInline) {
43830
+ var DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS = /* @__PURE__ */ new Set([
43831
+ "span",
43832
+ "em",
43833
+ "strong",
43834
+ "code",
43835
+ "kbd",
43836
+ "del",
43837
+ "s",
43838
+ "mark",
43839
+ "sub",
43840
+ "sup",
43841
+ "i",
43842
+ "b",
43843
+ "u",
43844
+ "small",
43845
+ "abbr",
43846
+ "a"
43847
+ ]);
43848
+ function extractMixedContentSegments(raw2, baseOffset, parseInline, options) {
43732
43849
  if (!raw2) return [];
43733
- const initial = splitByTagSegments(raw2, baseOffset, parseInline);
43850
+ const initial = splitByTagSegments(raw2, baseOffset, parseInline, options);
43734
43851
  const expanded = [];
43735
43852
  for (const segment of initial) {
43736
43853
  if (segment.kind === "text") {
@@ -43741,22 +43858,58 @@ function extractMixedContentSegments(raw2, baseOffset, parseInline) {
43741
43858
  }
43742
43859
  return mergeAdjacentTextSegments(expanded, parseInline);
43743
43860
  }
43744
- function splitByTagSegments(source, baseOffset, parseInline) {
43861
+ function splitByTagSegments(source, baseOffset, parseInline, options) {
43745
43862
  const segments = [];
43746
43863
  const lowerSource = source.toLowerCase();
43747
43864
  const tagPattern = /<([A-Za-z][\w:-]*)([^<>]*?)\/?>/g;
43748
43865
  let cursor = 0;
43749
43866
  let match = tagPattern.exec(source);
43750
43867
  const baseIsFinite = typeof baseOffset === "number" && Number.isFinite(baseOffset);
43868
+ const htmlAllowTags = normalizeHtmlAllowlist(options?.html?.allowTags);
43869
+ const htmlAutoClose = options?.html?.autoClose === true;
43870
+ const htmlMaxNewlines = normalizeNewlineLimit(options?.html?.maxNewlines);
43871
+ const mdxAutoClose = options?.mdx?.autoClose === true;
43872
+ const mdxMaxNewlines = normalizeNewlineLimit(options?.mdx?.maxNewlines);
43873
+ const mdxAllowlist = normalizeComponentAllowlist(options?.mdx?.componentAllowlist);
43751
43874
  while (match !== null) {
43752
43875
  const start2 = match.index;
43753
43876
  const tagName = match[1];
43754
43877
  const matchText = match[0];
43755
- const isSelfClosing = matchText.endsWith("/>") || isVoidHtmlTag(tagName);
43878
+ const tagNameLower = tagName.toLowerCase();
43879
+ const isSelfClosing = matchText.endsWith("/>") || isVoidHtmlTag(tagNameLower);
43880
+ const mdxCandidate = isLikelyMdxComponent(tagName);
43881
+ const mdxAllowed = mdxCandidate && (!mdxAllowlist || mdxAllowlist.has(tagName));
43882
+ if (mdxCandidate && mdxAllowlist && !mdxAllowed) {
43883
+ tagPattern.lastIndex = start2 + 1;
43884
+ match = tagPattern.exec(source);
43885
+ continue;
43886
+ }
43756
43887
  let end = tagPattern.lastIndex;
43757
- if (!isSelfClosing && !isLikelyMdxComponent(tagName)) {
43888
+ if (!isSelfClosing && !mdxAllowed) {
43758
43889
  const closingIndex = findClosingHtmlTag(lowerSource, tagName.toLowerCase(), end);
43759
43890
  if (closingIndex === -1) {
43891
+ if (htmlAutoClose && htmlAllowTags.has(tagNameLower)) {
43892
+ const tail = source.slice(end);
43893
+ const newlineCount = countNewlines(tail, htmlMaxNewlines + 1);
43894
+ if (newlineCount <= htmlMaxNewlines) {
43895
+ if (start2 > cursor) {
43896
+ const absoluteFrom = baseIsFinite ? baseOffset + cursor : void 0;
43897
+ const absoluteTo = baseIsFinite ? baseOffset + start2 : void 0;
43898
+ pushTextSegment(segments, source.slice(cursor, start2), absoluteFrom, absoluteTo, parseInline);
43899
+ }
43900
+ const rawSegment2 = source.slice(start2);
43901
+ const closedValue = `${rawSegment2}</${tagName}>`;
43902
+ const segment2 = {
43903
+ kind: "html",
43904
+ value: closedValue,
43905
+ range: createSegmentRange(baseOffset, start2, source.length),
43906
+ sanitized: sanitizeHtmlInWorker(closedValue)
43907
+ };
43908
+ segments.push(segment2);
43909
+ cursor = source.length;
43910
+ break;
43911
+ }
43912
+ }
43760
43913
  tagPattern.lastIndex = start2 + 1;
43761
43914
  match = tagPattern.exec(source);
43762
43915
  continue;
@@ -43768,8 +43921,8 @@ function splitByTagSegments(source, baseOffset, parseInline) {
43768
43921
  const absoluteTo = baseIsFinite ? baseOffset + start2 : void 0;
43769
43922
  pushTextSegment(segments, source.slice(cursor, start2), absoluteFrom, absoluteTo, parseInline);
43770
43923
  }
43771
- const rawSegment = source.slice(start2, end);
43772
- const kind = isLikelyMdxComponent(tagName) ? "mdx" : "html";
43924
+ let rawSegment = source.slice(start2, end);
43925
+ const kind = mdxAllowed ? "mdx" : "html";
43773
43926
  const segment = {
43774
43927
  kind,
43775
43928
  value: rawSegment,
@@ -43778,6 +43931,17 @@ function splitByTagSegments(source, baseOffset, parseInline) {
43778
43931
  if (kind === "html") {
43779
43932
  segment.sanitized = sanitizeHtmlInWorker(rawSegment);
43780
43933
  } else {
43934
+ const tail = source.slice(end);
43935
+ const newlineCount = countNewlines(tail, mdxMaxNewlines + 1);
43936
+ if (mdxAutoClose && newlineCount > mdxMaxNewlines) {
43937
+ tagPattern.lastIndex = start2 + 1;
43938
+ match = tagPattern.exec(source);
43939
+ continue;
43940
+ }
43941
+ if (mdxAutoClose && !rawSegment.endsWith("/>")) {
43942
+ rawSegment = selfCloseTag(rawSegment);
43943
+ segment.value = rawSegment;
43944
+ }
43781
43945
  segment.status = "pending";
43782
43946
  }
43783
43947
  segments.push(segment);
@@ -43902,6 +44066,48 @@ var VOID_HTML_TAGS = /* @__PURE__ */ new Set(["br", "hr", "img", "meta", "input"
43902
44066
  function isVoidHtmlTag(tagName) {
43903
44067
  return VOID_HTML_TAGS.has(tagName.toLowerCase());
43904
44068
  }
44069
+ function normalizeNewlineLimit(value) {
44070
+ if (!Number.isFinite(value ?? Number.NaN)) {
44071
+ return 2;
44072
+ }
44073
+ return Math.max(0, value ?? 0);
44074
+ }
44075
+ function normalizeHtmlAllowlist(value) {
44076
+ if (!value) return DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS;
44077
+ const tags2 = /* @__PURE__ */ new Set();
44078
+ for (const tag of value) {
44079
+ if (tag) {
44080
+ tags2.add(tag.toLowerCase());
44081
+ }
44082
+ }
44083
+ return tags2.size > 0 ? tags2 : DEFAULT_INLINE_HTML_AUTOCLOSE_TAGS;
44084
+ }
44085
+ function normalizeComponentAllowlist(value) {
44086
+ if (!value) return null;
44087
+ const tags2 = /* @__PURE__ */ new Set();
44088
+ for (const tag of value) {
44089
+ if (tag) tags2.add(tag);
44090
+ }
44091
+ return tags2.size > 0 ? tags2 : null;
44092
+ }
44093
+ function countNewlines(value, limit) {
44094
+ let count = 0;
44095
+ for (let i = 0; i < value.length; i++) {
44096
+ if (value.charCodeAt(i) === 10) {
44097
+ count += 1;
44098
+ if (limit !== void 0 && count >= limit) {
44099
+ return count;
44100
+ }
44101
+ }
44102
+ }
44103
+ return count;
44104
+ }
44105
+ function selfCloseTag(rawTag) {
44106
+ if (rawTag.endsWith("/>")) return rawTag;
44107
+ const closeIndex = rawTag.lastIndexOf(">");
44108
+ if (closeIndex === -1) return rawTag;
44109
+ return `${rawTag.slice(0, closeIndex)}/>`;
44110
+ }
43905
44111
  function isLikelyMdxComponent(tagName) {
43906
44112
  const first = tagName.charAt(0);
43907
44113
  return first.toUpperCase() === first && first.toLowerCase() !== first;
@@ -44686,63 +44892,126 @@ function computeHeavyPatchBudget(credit, config = DEFAULT_BACKPRESSURE_CONFIG) {
44686
44892
  return Math.min(config.maxHeavyPatchBudget, budget);
44687
44893
  }
44688
44894
  var USE_LINEAR_COALESCING = typeof process === "undefined" ? true : process.env.V2_USE_LINEAR_COALESCING !== "false" && true;
44895
+ var DEFAULT_FORMAT_ANTICIPATION = {
44896
+ inline: false,
44897
+ mathInline: false,
44898
+ mathBlock: false,
44899
+ html: false,
44900
+ mdx: false,
44901
+ regex: false
44902
+ };
44903
+ function normalizeFormatAnticipation(input) {
44904
+ if (input === true) {
44905
+ return { ...DEFAULT_FORMAT_ANTICIPATION, inline: true };
44906
+ }
44907
+ if (!input) {
44908
+ return { ...DEFAULT_FORMAT_ANTICIPATION };
44909
+ }
44910
+ return {
44911
+ inline: input.inline ?? false,
44912
+ mathInline: input.mathInline ?? false,
44913
+ mathBlock: input.mathBlock ?? false,
44914
+ html: input.html ?? false,
44915
+ mdx: input.mdx ?? false,
44916
+ regex: input.regex ?? false
44917
+ };
44918
+ }
44689
44919
  function prepareInlineStreamingContent(content4, options) {
44690
- const enableAnticipation = Boolean(options?.formatAnticipation);
44691
44920
  const enableMath2 = options?.math !== false;
44692
- let dollarCount = 0;
44693
- let backtickCount = 0;
44694
- let starCount = 0;
44695
- let doubleStarCount = 0;
44696
- let tildePairCount = 0;
44921
+ const anticipation = normalizeFormatAnticipation(options?.formatAnticipation);
44922
+ const enableInlineAnticipation = anticipation.inline;
44923
+ const enableMathInlineAnticipation = anticipation.mathInline;
44924
+ const enableMathBlockAnticipation = anticipation.mathBlock;
44925
+ const stack = [];
44926
+ const toggleToken = (token2) => {
44927
+ const last = stack[stack.length - 1];
44928
+ if (last === token2) {
44929
+ stack.pop();
44930
+ } else {
44931
+ stack.push(token2);
44932
+ }
44933
+ };
44934
+ let mathDisplayOpen = false;
44935
+ let mathDisplayCrossedNewline = false;
44697
44936
  for (let i = 0; i < content4.length; i++) {
44698
44937
  const code4 = content4.charCodeAt(i);
44699
- if (code4 === 36) {
44700
- dollarCount += 1;
44938
+ if (code4 === 10 || code4 === 13) {
44939
+ if (mathDisplayOpen) {
44940
+ mathDisplayCrossedNewline = true;
44941
+ }
44701
44942
  continue;
44702
44943
  }
44703
44944
  if (code4 === 96) {
44704
- backtickCount += 1;
44945
+ toggleToken("code");
44946
+ continue;
44947
+ }
44948
+ if (code4 === 126 && i + 1 < content4.length && content4.charCodeAt(i + 1) === 126) {
44949
+ toggleToken("strike");
44950
+ i += 1;
44705
44951
  continue;
44706
44952
  }
44707
44953
  if (code4 === 42) {
44708
44954
  if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 42) {
44709
- doubleStarCount += 1;
44710
- starCount += 2;
44955
+ toggleToken("strong");
44711
44956
  i += 1;
44712
44957
  } else {
44713
- starCount += 1;
44958
+ toggleToken("em");
44714
44959
  }
44715
44960
  continue;
44716
44961
  }
44717
- if (code4 === 126) {
44718
- if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 126) {
44719
- tildePairCount += 1;
44962
+ if (enableMath2 && code4 === 36) {
44963
+ if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 36) {
44964
+ toggleToken("math-display");
44965
+ if (mathDisplayOpen) {
44966
+ mathDisplayOpen = false;
44967
+ mathDisplayCrossedNewline = false;
44968
+ } else {
44969
+ mathDisplayOpen = true;
44970
+ mathDisplayCrossedNewline = false;
44971
+ }
44720
44972
  i += 1;
44973
+ } else {
44974
+ toggleToken("math-inline");
44721
44975
  }
44722
44976
  }
44723
44977
  }
44724
- const hasIncompleteMath = enableMath2 && dollarCount % 2 !== 0;
44725
- if (hasIncompleteMath) {
44726
- return { kind: "raw", status: "raw", reason: "incomplete-math" };
44727
- }
44728
- const hasIncompleteCode = backtickCount % 2 !== 0;
44729
- const hasIncompleteStrong = doubleStarCount % 2 !== 0;
44730
- const singleStarCount = starCount - doubleStarCount * 2;
44731
- const hasIncompleteEmphasis = singleStarCount % 2 !== 0;
44732
- const hasIncompleteStrike = tildePairCount % 2 !== 0;
44733
- const hasAnyIncomplete = hasIncompleteCode || hasIncompleteStrong || hasIncompleteEmphasis || hasIncompleteStrike;
44734
- if (!hasAnyIncomplete) {
44735
- return { kind: "parse", status: "complete", content: content4, appended: "" };
44978
+ const hasIncompleteFormatting = stack.some((token2) => token2 === "code" || token2 === "strike" || token2 === "strong" || token2 === "em");
44979
+ const hasIncompleteMathInline = stack.includes("math-inline");
44980
+ const hasIncompleteMathDisplay = stack.includes("math-display");
44981
+ const hasIncompleteMath = hasIncompleteMathInline || hasIncompleteMathDisplay;
44982
+ if (enableMath2 && hasIncompleteMath) {
44983
+ if (hasIncompleteMathInline && !enableMathInlineAnticipation) {
44984
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
44985
+ }
44986
+ if (hasIncompleteMathDisplay && (!enableMathBlockAnticipation || mathDisplayCrossedNewline)) {
44987
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
44988
+ }
44736
44989
  }
44737
- if (!enableAnticipation) {
44990
+ if (hasIncompleteFormatting && !enableInlineAnticipation) {
44738
44991
  return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
44739
44992
  }
44740
- let appended = "";
44741
- if (hasIncompleteCode) appended += "`";
44742
- if (hasIncompleteStrike) appended += "~~";
44743
- if (hasIncompleteStrong && hasIncompleteEmphasis) appended += "***";
44744
- else if (hasIncompleteStrong) appended += "**";
44745
- else if (hasIncompleteEmphasis) appended += "*";
44993
+ if (!hasIncompleteFormatting && !hasIncompleteMath) {
44994
+ return { kind: "parse", status: "complete", content: content4, appended: "" };
44995
+ }
44996
+ const appendForToken = (token2) => {
44997
+ switch (token2) {
44998
+ case "code":
44999
+ return "`";
45000
+ case "strike":
45001
+ return "~~";
45002
+ case "strong":
45003
+ return "**";
45004
+ case "em":
45005
+ return "*";
45006
+ case "math-inline":
45007
+ return "$";
45008
+ case "math-display":
45009
+ return "$$";
45010
+ default:
45011
+ return "";
45012
+ }
45013
+ };
45014
+ const appended = stack.slice().reverse().map((token2) => appendForToken(token2)).join("");
44746
45015
  return { kind: "parse", status: "anticipated", content: content4 + appended, appended };
44747
45016
  }
44748
45017
 
@@ -81699,20 +81968,72 @@ var documentPluginState = {};
81699
81968
  var txCounter = 0;
81700
81969
  var workerGrammarEngine = "js";
81701
81970
  var workerCredits = 1;
81971
+ var lastDiffSummary = null;
81972
+ var lastStructuralDiffSummary = null;
81973
+ var maxEmittedBlockCount = 0;
81974
+ var maxDeferredQueueSize = 0;
81975
+ var maxStructuralBlockCount = 0;
81976
+ var lastHighCountNoStructural = null;
81702
81977
  var MAX_DEFERRED_PATCHES = 400;
81703
81978
  var deferredPatchQueue = [];
81704
81979
  var MAX_DEFERRED_FLUSH_PATCHES = 120;
81705
81980
  var CODE_HIGHLIGHT_CACHE = /* @__PURE__ */ new Map();
81706
81981
  var MAX_CODE_HIGHLIGHT_CACHE_ENTRIES = 200;
81707
81982
  var mdxCompileMode = "server";
81708
- var enableFormatAnticipation = false;
81983
+ var formatAnticipationConfig = normalizeFormatAnticipation(false);
81709
81984
  var enableLiveCodeHighlighting = false;
81710
81985
  var enableMath = true;
81986
+ var mdxComponentAllowlist = null;
81711
81987
  var WORKER_MDX_CACHE = /* @__PURE__ */ new Map();
81712
81988
  var WORKER_MDX_INFLIGHT = /* @__PURE__ */ new Map();
81713
81989
  var MAX_WORKER_MDX_CACHE_ENTRIES = 128;
81714
81990
  var loggedMdxSkipCount = 0;
81715
81991
  var MAX_MDX_SKIP_LOGS = 20;
81992
+ var MIXED_CONTENT_AUTOCLOSE_NEWLINES = 2;
81993
+ var DEFAULT_APPEND_CHUNK_SIZE = 1400;
81994
+ var DEFAULT_APPEND_BATCH_MS = 12;
81995
+ var MIN_APPEND_CHUNK_SIZE = 256;
81996
+ var MAX_APPEND_CHUNK_SIZE = 12e3;
81997
+ var MIN_APPEND_BATCH_MS = 4;
81998
+ var MAX_APPEND_BATCH_MS = 50;
81999
+ var APPEND_NEWLINE_GRACE = 200;
82000
+ function clampInt(value, min, max) {
82001
+ if (!Number.isFinite(value)) return min;
82002
+ return Math.min(max, Math.max(min, Math.floor(value)));
82003
+ }
82004
+ function readNumericEnv(key2) {
82005
+ try {
82006
+ if (typeof process !== "undefined" && process.env && process.env[key2]) {
82007
+ const parsed = Number(process.env[key2]);
82008
+ if (Number.isFinite(parsed)) {
82009
+ return parsed;
82010
+ }
82011
+ }
82012
+ } catch {
82013
+ }
82014
+ return null;
82015
+ }
82016
+ var APPEND_CHUNK_SIZE = clampInt(
82017
+ readNumericEnv("NEXT_PUBLIC_STREAMING_APPEND_CHUNK") ?? DEFAULT_APPEND_CHUNK_SIZE,
82018
+ MIN_APPEND_CHUNK_SIZE,
82019
+ MAX_APPEND_CHUNK_SIZE
82020
+ );
82021
+ var APPEND_BATCH_MS = clampInt(
82022
+ readNumericEnv("NEXT_PUBLIC_STREAMING_APPEND_BATCH_MS") ?? DEFAULT_APPEND_BATCH_MS,
82023
+ MIN_APPEND_BATCH_MS,
82024
+ MAX_APPEND_BATCH_MS
82025
+ );
82026
+ function sliceAppendChunk(text12, maxChars) {
82027
+ if (text12.length <= maxChars) {
82028
+ return { chunk: text12, rest: "" };
82029
+ }
82030
+ const newlineIndex = text12.lastIndexOf("\n", maxChars);
82031
+ const cut = newlineIndex > 0 && maxChars - newlineIndex <= APPEND_NEWLINE_GRACE ? newlineIndex + 1 : maxChars;
82032
+ return { chunk: text12.slice(0, cut), rest: text12.slice(cut) };
82033
+ }
82034
+ function waitForNextTick() {
82035
+ return new Promise((resolve) => setTimeout(resolve, 0));
82036
+ }
81716
82037
  function isDebugEnabled(flag) {
81717
82038
  try {
81718
82039
  if (typeof process !== "undefined" && process.env) {
@@ -81731,6 +82052,8 @@ function isDebugEnabled(flag) {
81731
82052
  }
81732
82053
  var DEBUG_MDX = isDebugEnabled("mdx");
81733
82054
  var sharedTextEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
82055
+ var shouldTrackInlineStatus = () => formatAnticipationConfig.inline || formatAnticipationConfig.mathInline || formatAnticipationConfig.mathBlock;
82056
+ var shouldAllowMixedStreaming = () => formatAnticipationConfig.html || formatAnticipationConfig.mdx;
81734
82057
  function now() {
81735
82058
  return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
81736
82059
  }
@@ -81918,7 +82241,23 @@ function partitionPatchesForCredits(patches, maxImmediate) {
81918
82241
  const immediate = [];
81919
82242
  const deferred = [];
81920
82243
  let heavyBudget = computeHeavyPatchBudget(workerCredits);
82244
+ let nonStructuralImmediate = 0;
82245
+ const isStructuralPatch = (patch5) => {
82246
+ switch (patch5.op) {
82247
+ case "insertChild":
82248
+ case "deleteChild":
82249
+ case "replaceChild":
82250
+ case "reorder":
82251
+ return true;
82252
+ default:
82253
+ return false;
82254
+ }
82255
+ };
81921
82256
  for (const patch5 of combined) {
82257
+ if (isStructuralPatch(patch5)) {
82258
+ immediate.push(patch5);
82259
+ continue;
82260
+ }
81922
82261
  const heavy = isHeavyPatch(patch5);
81923
82262
  if (heavy) {
81924
82263
  if (heavyBudget <= 0) {
@@ -81930,14 +82269,14 @@ function partitionPatchesForCredits(patches, maxImmediate) {
81930
82269
  heavyBudget -= 1;
81931
82270
  }
81932
82271
  }
82272
+ if (typeof maxImmediate === "number" && nonStructuralImmediate >= maxImmediate) {
82273
+ deferred.push(patch5);
82274
+ continue;
82275
+ }
81933
82276
  immediate.push(patch5);
82277
+ nonStructuralImmediate += 1;
81934
82278
  }
81935
- if (typeof maxImmediate === "number" && immediate.length > maxImmediate) {
81936
- const overflow = immediate.splice(maxImmediate);
81937
- deferredPatchQueue = overflow.concat(deferred);
81938
- } else {
81939
- deferredPatchQueue = deferred;
81940
- }
82279
+ deferredPatchQueue = deferred;
81941
82280
  return immediate;
81942
82281
  }
81943
82282
  function flushDeferredPatches() {
@@ -81998,13 +82337,23 @@ function mapToHighlightRecord(map3) {
81998
82337
  return result;
81999
82338
  }
82000
82339
  function parseInlineStreaming(content4) {
82001
- const prepared = prepareInlineStreamingContent(content4, { formatAnticipation: enableFormatAnticipation, math: enableMath });
82340
+ const prepared = prepareInlineStreamingContent(content4, { formatAnticipation: formatAnticipationConfig, math: enableMath });
82002
82341
  if (prepared.kind === "raw") {
82003
82342
  return { inline: [{ kind: "text", text: content4 }], status: prepared.status };
82004
82343
  }
82344
+ let preparedContent = prepared.content;
82345
+ let appended = prepared.appended;
82346
+ if (formatAnticipationConfig.regex) {
82347
+ const regexAppend = inlineParser.getRegexAnticipationAppend(content4);
82348
+ if (regexAppend) {
82349
+ preparedContent += regexAppend;
82350
+ appended += regexAppend;
82351
+ }
82352
+ }
82353
+ const status = appended.length > 0 ? "anticipated" : prepared.status;
82005
82354
  return {
82006
- inline: inlineParser.parse(prepared.content, { cache: false }),
82007
- status: prepared.status
82355
+ inline: inlineParser.parse(preparedContent, { cache: false }),
82356
+ status
82008
82357
  };
82009
82358
  }
82010
82359
  async function initialize(initialContent = "", prewarmLangs = [], docPlugins, mdxOptions) {
@@ -82032,8 +82381,13 @@ async function initialize(initialContent = "", prewarmLangs = [], docPlugins, md
82032
82381
  liveCodeHighlighting: docPlugins?.liveCodeHighlighting ?? false
82033
82382
  };
82034
82383
  enableMath = enable.math;
82035
- enableFormatAnticipation = enable.formatAnticipation;
82384
+ formatAnticipationConfig = normalizeFormatAnticipation(enable.formatAnticipation);
82036
82385
  enableLiveCodeHighlighting = enable.liveCodeHighlighting;
82386
+ if (Array.isArray(docPlugins?.mdxComponentNames) && docPlugins?.mdxComponentNames.length > 0) {
82387
+ mdxComponentAllowlist = new Set(docPlugins.mdxComponentNames);
82388
+ } else {
82389
+ mdxComponentAllowlist = null;
82390
+ }
82037
82391
  inlineParser = new InlineParser({ enableMath });
82038
82392
  documentPluginState.inlineParser = inlineParser;
82039
82393
  if (enable.footnotes) registerFootnotesPlugin();
@@ -82066,25 +82420,35 @@ async function initialize(initialContent = "", prewarmLangs = [], docPlugins, md
82066
82420
  }
82067
82421
  }
82068
82422
  async function handleAppend(text12) {
82069
- performanceTimer.mark("append-operation");
82070
- const metricsCollector = new WorkerMetricsCollector(workerGrammarEngine);
82071
- setActiveMetricsCollector(metricsCollector);
82072
- await appendAndReparse(text12, metricsCollector);
82073
- const hadPatchMetrics = metricsCollector.patchCount > 0;
82074
- const totalTime = performanceTimer.measure("append-operation");
82075
- if (getActiveMetricsCollector() === metricsCollector) {
82076
- setActiveMetricsCollector(null);
82077
- }
82078
- if (!hadPatchMetrics && totalTime !== null && Number.isFinite(totalTime)) {
82079
- postMessage({
82080
- type: "METRICS",
82081
- metrics: {
82082
- parseMs: roundMetric(totalTime),
82083
- parseTime: roundMetric(totalTime),
82084
- blocksProduced: blocks.length,
82085
- grammarEngine: workerGrammarEngine
82086
- }
82087
- });
82423
+ let remaining = text12;
82424
+ let batchStartedAt = now();
82425
+ while (remaining.length > 0) {
82426
+ const { chunk, rest } = sliceAppendChunk(remaining, APPEND_CHUNK_SIZE);
82427
+ remaining = rest;
82428
+ performanceTimer.mark("append-operation");
82429
+ const metricsCollector = new WorkerMetricsCollector(workerGrammarEngine);
82430
+ setActiveMetricsCollector(metricsCollector);
82431
+ await appendAndReparse(chunk, metricsCollector);
82432
+ const hadPatchMetrics = metricsCollector.patchCount > 0;
82433
+ const totalTime = performanceTimer.measure("append-operation");
82434
+ if (getActiveMetricsCollector() === metricsCollector) {
82435
+ setActiveMetricsCollector(null);
82436
+ }
82437
+ if (!hadPatchMetrics && totalTime !== null && Number.isFinite(totalTime)) {
82438
+ postMessage({
82439
+ type: "METRICS",
82440
+ metrics: {
82441
+ parseMs: roundMetric(totalTime),
82442
+ parseTime: roundMetric(totalTime),
82443
+ blocksProduced: blocks.length,
82444
+ grammarEngine: workerGrammarEngine
82445
+ }
82446
+ });
82447
+ }
82448
+ if (remaining.length > 0 && now() - batchStartedAt >= APPEND_BATCH_MS) {
82449
+ await waitForNextTick();
82450
+ batchStartedAt = now();
82451
+ }
82088
82452
  }
82089
82453
  }
82090
82454
  async function parseAll(content4, options = {}) {
@@ -82107,9 +82471,24 @@ async function appendAndReparse(appendedText, metrics) {
82107
82471
  metrics?.markParseStart();
82108
82472
  const newContent = currentContent + appendedText;
82109
82473
  const changeRanges = computeChangedRanges(currentContent, newContent);
82110
- const newTree = lastTree ? parser.parse(newContent, lastTree.fragments) : parser.parse(newContent);
82474
+ let newTree = lastTree ? parser.parse(newContent, lastTree.fragments) : parser.parse(newContent);
82111
82475
  let changedBlocks = await extractBlocks(newTree, newContent);
82112
82476
  changedBlocks = runDocumentPlugins(changedBlocks, newContent);
82477
+ const lastRange = changedBlocks.length > 0 ? changedBlocks[changedBlocks.length - 1]?.payload?.range : void 0;
82478
+ const lastTo = typeof lastRange?.to === "number" ? lastRange.to : 0;
82479
+ if (lastTo < newContent.length - 1) {
82480
+ const tail = newContent.slice(lastTo).trim();
82481
+ if (tail.length > 0) {
82482
+ const fullTree = parser.parse(newContent);
82483
+ let fullBlocks = await extractBlocks(fullTree, newContent);
82484
+ fullBlocks = runDocumentPlugins(fullBlocks, newContent);
82485
+ const fullLast = fullBlocks.length > 0 ? fullBlocks[fullBlocks.length - 1]?.payload?.range?.to ?? 0 : 0;
82486
+ if (fullLast >= newContent.length - 1 || fullBlocks.length >= changedBlocks.length) {
82487
+ newTree = fullTree;
82488
+ changedBlocks = fullBlocks;
82489
+ }
82490
+ }
82491
+ }
82113
82492
  const prevBlocks = blocks;
82114
82493
  blocks = changedBlocks;
82115
82494
  lastTree = newTree;
@@ -82221,13 +82600,13 @@ async function enrichBlock(block) {
82221
82600
  if (block.isFinalized) {
82222
82601
  block.payload.raw = normalizedHeading;
82223
82602
  block.payload.inline = inlineParser.parse(normalizedHeading);
82224
- if (enableFormatAnticipation && block.payload.meta) {
82603
+ if (shouldTrackInlineStatus() && block.payload.meta) {
82225
82604
  block.payload.meta.inlineStatus = void 0;
82226
82605
  }
82227
82606
  } else {
82228
82607
  const parsed = parseInlineStreaming(normalizedHeading);
82229
82608
  block.payload.inline = parsed.inline;
82230
- if (enableFormatAnticipation && block.payload.meta) {
82609
+ if (shouldTrackInlineStatus() && block.payload.meta) {
82231
82610
  block.payload.meta.inlineStatus = parsed.status;
82232
82611
  }
82233
82612
  }
@@ -82238,7 +82617,11 @@ async function enrichBlock(block) {
82238
82617
  block.payload.raw = normalized;
82239
82618
  const streamingParsed = !block.isFinalized ? parseInlineStreaming(normalized) : null;
82240
82619
  const inlineParse = block.isFinalized ? (value) => inlineParser.parse(value) : (value) => parseInlineStreaming(value).inline;
82241
- const segments = extractMixedContentSegments(normalized, void 0, inlineParse);
82620
+ const mixedOptions = !block.isFinalized && shouldAllowMixedStreaming() ? {
82621
+ html: formatAnticipationConfig.html ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES } : void 0,
82622
+ mdx: formatAnticipationConfig.mdx ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES, componentAllowlist: mdxComponentAllowlist ?? void 0 } : void 0
82623
+ } : void 0;
82624
+ const segments = extractMixedContentSegments(normalized, void 0, inlineParse, mixedOptions);
82242
82625
  const currentMeta = block.payload.meta ?? {};
82243
82626
  const nextMeta = {
82244
82627
  ...currentMeta,
@@ -82249,7 +82632,7 @@ async function enrichBlock(block) {
82249
82632
  } else {
82250
82633
  nextMeta.mixedSegments = void 0;
82251
82634
  }
82252
- if (enableFormatAnticipation) {
82635
+ if (shouldTrackInlineStatus()) {
82253
82636
  nextMeta.inlineStatus = block.isFinalized ? void 0 : streamingParsed?.status;
82254
82637
  }
82255
82638
  if (Object.keys(nextMeta).length > 0) {
@@ -82272,7 +82655,8 @@ async function enrichBlock(block) {
82272
82655
  const currentMeta = block.payload.meta ?? {};
82273
82656
  const nextMeta = { ...currentMeta };
82274
82657
  let metaChanged = false;
82275
- if (enableFormatAnticipation) {
82658
+ const allowMixedStreaming = shouldAllowMixedStreaming();
82659
+ if (shouldTrackInlineStatus()) {
82276
82660
  const desired = block.isFinalized ? void 0 : streamingParsed?.status;
82277
82661
  if (desired !== void 0) {
82278
82662
  if (!Object.prototype.hasOwnProperty.call(nextMeta, "inlineStatus") || nextMeta.inlineStatus !== desired) {
@@ -82298,17 +82682,36 @@ async function enrichBlock(block) {
82298
82682
  const shouldExtractSegments = typeof rawParagraph === "string" && (rawParagraph.includes("<") || rawParagraph.includes("{"));
82299
82683
  if (shouldExtractSegments) {
82300
82684
  const baseOffset = typeof block.payload.range?.from === "number" ? block.payload.range.from : void 0;
82301
- const segments = extractMixedContentSegments(rawParagraph, baseOffset, (value) => inlineParse(value));
82685
+ const mixedOptions = !block.isFinalized && shouldAllowMixedStreaming() ? {
82686
+ html: formatAnticipationConfig.html ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES } : void 0,
82687
+ mdx: formatAnticipationConfig.mdx ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES, componentAllowlist: mdxComponentAllowlist ?? void 0 } : void 0
82688
+ } : void 0;
82689
+ const segments = extractMixedContentSegments(rawParagraph, baseOffset, (value) => inlineParse(value), mixedOptions);
82302
82690
  if (segments.length > 0) {
82303
82691
  nextMeta.mixedSegments = segments;
82304
82692
  metaChanged = true;
82693
+ if (allowMixedStreaming) {
82694
+ nextMeta.allowMixedStreaming = true;
82695
+ metaChanged = true;
82696
+ } else if (Object.prototype.hasOwnProperty.call(nextMeta, "allowMixedStreaming")) {
82697
+ nextMeta.allowMixedStreaming = void 0;
82698
+ metaChanged = true;
82699
+ }
82305
82700
  } else if (Object.prototype.hasOwnProperty.call(nextMeta, "mixedSegments")) {
82306
82701
  nextMeta.mixedSegments = void 0;
82307
82702
  metaChanged = true;
82703
+ if (Object.prototype.hasOwnProperty.call(nextMeta, "allowMixedStreaming")) {
82704
+ nextMeta.allowMixedStreaming = void 0;
82705
+ metaChanged = true;
82706
+ }
82308
82707
  }
82309
82708
  } else if (Object.prototype.hasOwnProperty.call(nextMeta, "mixedSegments")) {
82310
82709
  nextMeta.mixedSegments = void 0;
82311
82710
  metaChanged = true;
82711
+ if (Object.prototype.hasOwnProperty.call(nextMeta, "allowMixedStreaming")) {
82712
+ nextMeta.allowMixedStreaming = void 0;
82713
+ metaChanged = true;
82714
+ }
82312
82715
  }
82313
82716
  if (metaChanged) {
82314
82717
  if (Object.keys(nextMeta).length > 0) {
@@ -82906,6 +83309,50 @@ async function emitBlockDiffPatches(previousBlocks, nextBlocks, changedRanges, m
82906
83309
  });
82907
83310
  }
82908
83311
  const immediatePatches = partitionPatchesForCredits(combined, paragraphLimit === null ? void 0 : paragraphLimit);
83312
+ if (deferredPatchQueue.length > maxDeferredQueueSize) {
83313
+ maxDeferredQueueSize = deferredPatchQueue.length;
83314
+ }
83315
+ let structuralCount = 0;
83316
+ for (const patch5 of patches) {
83317
+ if (patch5.op === "insertChild" || patch5.op === "deleteChild" || patch5.op === "replaceChild" || patch5.op === "reorder") {
83318
+ structuralCount += 1;
83319
+ }
83320
+ }
83321
+ lastDiffSummary = {
83322
+ prevCount: previousBlocks.length,
83323
+ nextCount: nextBlocks.length,
83324
+ prefix,
83325
+ removeCount,
83326
+ addCount,
83327
+ structuralPatches: structuralCount,
83328
+ contentPatches: contentPatches.length,
83329
+ immediatePatches: immediatePatches.length,
83330
+ deferredQueue: deferredPatchQueue.length
83331
+ };
83332
+ if (addCount > 0 || removeCount > 0 || structuralCount > 0 || deferredPatchQueue.length > 0) {
83333
+ lastStructuralDiffSummary = { ...lastDiffSummary };
83334
+ }
83335
+ if (immediatePatches.length > 0) {
83336
+ maxEmittedBlockCount = Math.max(maxEmittedBlockCount, nextBlocks.length);
83337
+ }
83338
+ if (structuralCount > 0) {
83339
+ maxStructuralBlockCount = Math.max(maxStructuralBlockCount, nextBlocks.length);
83340
+ }
83341
+ if (nextBlocks.length >= 60 && removeCount === 0 && addCount === 0) {
83342
+ const sliceStart = Math.max(0, Math.min(55, nextBlocks.length - 1));
83343
+ const sliceEnd = Math.min(nextBlocks.length, sliceStart + 8);
83344
+ const toPreview = (block) => ({
83345
+ id: block.id,
83346
+ type: block.type,
83347
+ raw: typeof block.payload.raw === "string" ? block.payload.raw.slice(0, 80) : ""
83348
+ });
83349
+ lastHighCountNoStructural = {
83350
+ nextCount: nextBlocks.length,
83351
+ sliceStart,
83352
+ prevSlice: previousBlocks.slice(sliceStart, sliceEnd).map(toPreview),
83353
+ nextSlice: nextBlocks.slice(sliceStart, sliceEnd).map(toPreview)
83354
+ };
83355
+ }
82909
83356
  if (immediatePatches.length === 0) {
82910
83357
  if (metrics) {
82911
83358
  metrics.finalizePatch(txCounter, 0, deferredPatchQueue.length, 0);
@@ -83414,6 +83861,19 @@ async function finalizeAllBlocks() {
83414
83861
  dispatchPatchBatch(finalizeSetProps, metricsCollector);
83415
83862
  }
83416
83863
  }
83864
+ if (deferredPatchQueue.length > 0) {
83865
+ const previousCredits = workerCredits;
83866
+ workerCredits = 1;
83867
+ const maxIterations = Math.ceil(deferredPatchQueue.length / MAX_DEFERRED_FLUSH_PATCHES) + 8;
83868
+ for (let i = 0; i < maxIterations && deferredPatchQueue.length > 0; i++) {
83869
+ const before = deferredPatchQueue.length;
83870
+ flushDeferredPatches();
83871
+ if (deferredPatchQueue.length >= before) {
83872
+ break;
83873
+ }
83874
+ }
83875
+ workerCredits = previousCredits;
83876
+ }
83417
83877
  if (getActiveMetricsCollector() === metricsCollector) {
83418
83878
  setActiveMetricsCollector(null);
83419
83879
  }
@@ -83461,6 +83921,104 @@ async function processWorkerMessage(msg) {
83461
83921
  case "FINALIZE":
83462
83922
  await finalizeAllBlocks();
83463
83923
  return;
83924
+ case "DEBUG_STATE": {
83925
+ const blockTypeCounts = {};
83926
+ for (const block of blocks) {
83927
+ const key2 = block.type ?? "unknown";
83928
+ blockTypeCounts[key2] = (blockTypeCounts[key2] || 0) + 1;
83929
+ }
83930
+ let lastBlockType;
83931
+ let lastBlockRange;
83932
+ let lastBlockRawTail;
83933
+ const headingTexts = [];
83934
+ const tailBlocks = [];
83935
+ const headBlocks = [];
83936
+ const duplicateBlockIds = [];
83937
+ const seenBlockIds = /* @__PURE__ */ new Set();
83938
+ const headingIndices = {};
83939
+ for (const block of blocks) {
83940
+ if (seenBlockIds.has(block.id)) {
83941
+ if (duplicateBlockIds.length < 8) {
83942
+ duplicateBlockIds.push(block.id);
83943
+ }
83944
+ } else {
83945
+ seenBlockIds.add(block.id);
83946
+ }
83947
+ }
83948
+ if (blocks.length > 0) {
83949
+ const lastBlock = blocks[blocks.length - 1];
83950
+ lastBlockType = lastBlock.type;
83951
+ const range2 = lastBlock.payload.range;
83952
+ if (range2 && typeof range2.from === "number" && typeof range2.to === "number") {
83953
+ lastBlockRange = { from: range2.from, to: range2.to };
83954
+ }
83955
+ const raw2 = typeof lastBlock.payload.raw === "string" ? lastBlock.payload.raw : "";
83956
+ lastBlockRawTail = raw2 ? raw2.slice(Math.max(0, raw2.length - 240)) : void 0;
83957
+ for (const block of blocks) {
83958
+ if (block.type === "heading" && typeof block.payload.raw === "string") {
83959
+ headingTexts.push(block.payload.raw);
83960
+ }
83961
+ }
83962
+ const targets = ["HTML and MDX Testing", "Inline Code", "Code Blocks", "Media", "Tables", "Footnotes"];
83963
+ for (let i = 0; i < blocks.length; i++) {
83964
+ const block = blocks[i];
83965
+ if (block.type === "heading" && typeof block.payload.raw === "string") {
83966
+ if (targets.includes(block.payload.raw)) {
83967
+ headingIndices[block.payload.raw] = i;
83968
+ }
83969
+ }
83970
+ }
83971
+ const tailStart = Math.max(0, blocks.length - 8);
83972
+ for (let i = tailStart; i < blocks.length; i++) {
83973
+ const block = blocks[i];
83974
+ const raw3 = typeof block.payload.raw === "string" ? block.payload.raw : "";
83975
+ tailBlocks.push({
83976
+ id: block.id,
83977
+ type: block.type,
83978
+ raw: raw3.slice(0, 120)
83979
+ });
83980
+ }
83981
+ const headEnd = Math.min(8, blocks.length);
83982
+ for (let i = 0; i < headEnd; i++) {
83983
+ const block = blocks[i];
83984
+ const raw3 = typeof block.payload.raw === "string" ? block.payload.raw : "";
83985
+ headBlocks.push({
83986
+ id: block.id,
83987
+ type: block.type,
83988
+ raw: raw3.slice(0, 120)
83989
+ });
83990
+ }
83991
+ }
83992
+ const contentTail = currentContent.slice(Math.max(0, currentContent.length - 500));
83993
+ postMessage({
83994
+ type: "DEBUG_STATE",
83995
+ state: {
83996
+ contentLength: currentContent.length,
83997
+ contentTail,
83998
+ blockCount: blocks.length,
83999
+ blockTypeCounts,
84000
+ lastBlockType,
84001
+ lastBlockRange,
84002
+ lastBlockRawTail,
84003
+ headingTexts,
84004
+ headBlocks,
84005
+ tailBlocks,
84006
+ headingIndices,
84007
+ lastDiffSummary,
84008
+ lastStructuralDiffSummary,
84009
+ maxEmittedBlockCount,
84010
+ maxDeferredQueueSize,
84011
+ maxStructuralBlockCount,
84012
+ lastHighCountNoStructural,
84013
+ duplicateBlockIds,
84014
+ duplicateBlockCount: duplicateBlockIds.length,
84015
+ hasInlineCodeHeading: currentContent.includes("# Inline Code"),
84016
+ hasCodeBlocksHeading: currentContent.includes("# Code Blocks"),
84017
+ hasMediaHeading: currentContent.includes("# Media")
84018
+ }
84019
+ });
84020
+ return;
84021
+ }
83464
84022
  case "MDX_COMPILED":
83465
84023
  handleMdxStatus(msg.blockId, {
83466
84024
  compiledRef: { id: msg.compiledId },
@@ -1,4 +1,4 @@
1
- import { WorkerOut } from '@stream-mdx/core';
1
+ import { WorkerOut, FormatAnticipationConfig } from '@stream-mdx/core';
2
2
 
3
3
  type DefaultWorkerMode = "auto" | "hosted" | "blob";
4
4
  interface CreateDefaultWorkerOptions {
@@ -54,8 +54,9 @@ declare class MarkdownWorkerClient {
54
54
  tables?: boolean;
55
55
  callouts?: boolean;
56
56
  math?: boolean;
57
- formatAnticipation?: boolean;
57
+ formatAnticipation?: FormatAnticipationConfig;
58
58
  liveCodeHighlighting?: boolean;
59
+ mdxComponentNames?: string[];
59
60
  }, mdxOptions?: {
60
61
  compileMode?: "server" | "worker";
61
62
  }): void;
@@ -1,4 +1,4 @@
1
- import { WorkerOut } from '@stream-mdx/core';
1
+ import { WorkerOut, FormatAnticipationConfig } from '@stream-mdx/core';
2
2
 
3
3
  type DefaultWorkerMode = "auto" | "hosted" | "blob";
4
4
  interface CreateDefaultWorkerOptions {
@@ -54,8 +54,9 @@ declare class MarkdownWorkerClient {
54
54
  tables?: boolean;
55
55
  callouts?: boolean;
56
56
  math?: boolean;
57
- formatAnticipation?: boolean;
57
+ formatAnticipation?: FormatAnticipationConfig;
58
58
  liveCodeHighlighting?: boolean;
59
+ mdxComponentNames?: string[];
59
60
  }, mdxOptions?: {
60
61
  compileMode?: "server" | "worker";
61
62
  }): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-mdx/worker",
3
- "version": "0.0.3",
3
+ "version": "0.1.1",
4
4
  "description": "Worker client utilities and shared worker helpers for the Streaming Markdown V2 pipeline",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -55,7 +55,7 @@
55
55
  "scripts": {
56
56
  "build": "tsup",
57
57
  "build:hosted": "tsup --config tsup.hosted-worker.config.ts",
58
- "test": "tsx __tests__/*.test.ts",
58
+ "test": "tsx ../../scripts/run-tests.ts __tests__",
59
59
  "clean": "rm -rf dist",
60
60
  "prepack": "npm run build && npm run build:hosted"
61
61
  },
@@ -63,8 +63,8 @@
63
63
  "@lezer/common": "^1.2.3",
64
64
  "@lezer/lr": "^1.4.2",
65
65
  "@lezer/markdown": "^1.3.0",
66
- "@stream-mdx/core": "0.0.3",
67
- "@stream-mdx/plugins": "0.0.3",
66
+ "@stream-mdx/core": "0.1.1",
67
+ "@stream-mdx/plugins": "0.1.1",
68
68
  "@mdx-js/mdx": "^3.1.0",
69
69
  "@shikijs/engine-javascript": "^1.29.2",
70
70
  "@shikijs/engine-oniguruma": "^1.29.2",