@stream-mdx/worker 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17946,7 +17946,7 @@ function getGroupContents(expression, contentsStartPos) {
17946
17946
  return expression.slice(contentsStartPos, contentsEndPos);
17947
17947
  }
17948
17948
 
17949
- // ../../node_modules/regex/src/subclass.js
17949
+ // node_modules/regex/src/subclass.js
17950
17950
  var emulationGroupMarker = "$E$";
17951
17951
  var RegExpSubclass = class _RegExpSubclass extends RegExp {
17952
17952
  /**
@@ -18059,13 +18059,13 @@ function unmarkEmulationGroups(expression) {
18059
18059
  };
18060
18060
  }
18061
18061
 
18062
- // ../../node_modules/regex/src/utils-internals.js
18062
+ // node_modules/regex/src/utils-internals.js
18063
18063
  var noncapturingDelim = String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!]|\(DEFINE\))`;
18064
18064
  function spliceStr(str, pos, oldValue, newValue) {
18065
18065
  return str.slice(0, pos) + newValue + str.slice(pos + oldValue.length);
18066
18066
  }
18067
18067
 
18068
- // ../../node_modules/regex/src/atomic.js
18068
+ // node_modules/regex/src/atomic.js
18069
18069
  var atomicPluginToken = new RegExp(String.raw`(?<noncapturingStart>${noncapturingDelim})|(?<capturingStart>\((?:\?<[^>]+>)?)|\\?.`, "gsu");
18070
18070
  function atomic(expression, data2) {
18071
18071
  if (!/\(\?>/.test(expression)) {
@@ -18206,7 +18206,7 @@ function possessive(expression) {
18206
18206
  return expression;
18207
18207
  }
18208
18208
 
18209
- // ../../node_modules/regex-recursion/src/index.js
18209
+ // node_modules/regex-recursion/src/index.js
18210
18210
  var r2 = String.raw;
18211
18211
  var gRToken = r2`\\g<(?<gRNameOrNum>[^>&]+)&R=(?<gRDepth>[^>]+)>`;
18212
18212
  var recursiveToken = r2`\(\?R=(?<rDepth>[^\)]+)\)|${gRToken}`;
@@ -18356,7 +18356,7 @@ function emulationGroupMarkerLength(expression, index2) {
18356
18356
  return match ? match[0].length : 0;
18357
18357
  }
18358
18358
 
18359
- // ../../node_modules/oniguruma-to-es/dist/esm/index.js
18359
+ // node_modules/oniguruma-to-es/dist/esm/index.js
18360
18360
  var cp = String.fromCodePoint;
18361
18361
  var r3 = String.raw;
18362
18362
  var envSupportsFlagGroups = (() => {
@@ -21379,7 +21379,7 @@ function toRegExp(pattern, options) {
21379
21379
  return new RegExp(result.pattern, result.flags);
21380
21380
  }
21381
21381
 
21382
- // ../../node_modules/@shikijs/engine-javascript/dist/shared/engine-javascript.hzpS1_41.mjs
21382
+ // node_modules/@shikijs/engine-javascript/dist/shared/engine-javascript.hzpS1_41.mjs
21383
21383
  var MAX = 4294967295;
21384
21384
  var JavaScriptScanner = class {
21385
21385
  constructor(patterns, options = {}) {
@@ -21472,7 +21472,7 @@ var JavaScriptScanner = class {
21472
21472
  }
21473
21473
  };
21474
21474
 
21475
- // ../../node_modules/@shikijs/engine-javascript/dist/engine-compile.mjs
21475
+ // node_modules/@shikijs/engine-javascript/dist/engine-compile.mjs
21476
21476
  function defaultJavaScriptRegexConstructor(pattern, options) {
21477
21477
  return toRegExp(
21478
21478
  pattern,
@@ -43324,6 +43324,22 @@ function manualExtractHighlightedLines(html9, fallbackLength) {
43324
43324
  }
43325
43325
  return normalizeHighlightedLines(lines, fallbackLength);
43326
43326
  }
43327
+ function getDefaultCodeWrapperAttributes(lang236, themes = { dark: "github-dark", light: "github-light" }) {
43328
+ const language = lang236 && typeof lang236 === "string" && lang236.length > 0 ? lang236 : "text";
43329
+ const themeLabel = `${themes.dark} ${themes.light}`;
43330
+ return {
43331
+ preAttrs: {
43332
+ class: `shiki shiki-themes ${themeLabel}`,
43333
+ "data-language": language,
43334
+ style: "--shiki-dark-bg: transparent; --shiki-light-bg: transparent"
43335
+ },
43336
+ codeAttrs: {
43337
+ "data-language": language,
43338
+ "data-theme": themeLabel,
43339
+ style: "display: grid;"
43340
+ }
43341
+ };
43342
+ }
43327
43343
  function dedentIndentedCode(raw2) {
43328
43344
  if (!raw2) return "";
43329
43345
  const normalized = normalizeNewlines(raw2);
@@ -43697,6 +43713,128 @@ function splitTextByRegexWithPrecedence(text12, regex3, toNode3) {
43697
43713
  }
43698
43714
  return result;
43699
43715
  }
43716
+ var DEFAULT_FORMAT_ANTICIPATION = {
43717
+ inline: false,
43718
+ mathInline: false,
43719
+ mathBlock: false,
43720
+ html: false,
43721
+ mdx: false,
43722
+ regex: false
43723
+ };
43724
+ function normalizeFormatAnticipation(input) {
43725
+ if (input === true) {
43726
+ return { ...DEFAULT_FORMAT_ANTICIPATION, inline: true };
43727
+ }
43728
+ if (!input) {
43729
+ return { ...DEFAULT_FORMAT_ANTICIPATION };
43730
+ }
43731
+ return {
43732
+ inline: input.inline ?? false,
43733
+ mathInline: input.mathInline ?? false,
43734
+ mathBlock: input.mathBlock ?? false,
43735
+ html: input.html ?? false,
43736
+ mdx: input.mdx ?? false,
43737
+ regex: input.regex ?? false
43738
+ };
43739
+ }
43740
+ function prepareInlineStreamingContent(content4, options) {
43741
+ const enableMath2 = options?.math !== false;
43742
+ const anticipation = normalizeFormatAnticipation(options?.formatAnticipation);
43743
+ const enableInlineAnticipation = anticipation.inline;
43744
+ const enableMathInlineAnticipation = anticipation.mathInline;
43745
+ const enableMathBlockAnticipation = anticipation.mathBlock;
43746
+ const stack = [];
43747
+ const toggleToken = (token2) => {
43748
+ const last = stack[stack.length - 1];
43749
+ if (last === token2) {
43750
+ stack.pop();
43751
+ } else {
43752
+ stack.push(token2);
43753
+ }
43754
+ };
43755
+ let mathDisplayOpen = false;
43756
+ let mathDisplayCrossedNewline = false;
43757
+ for (let i = 0; i < content4.length; i++) {
43758
+ const code4 = content4.charCodeAt(i);
43759
+ if (code4 === 10 || code4 === 13) {
43760
+ if (mathDisplayOpen) {
43761
+ mathDisplayCrossedNewline = true;
43762
+ }
43763
+ continue;
43764
+ }
43765
+ if (code4 === 96) {
43766
+ toggleToken("code");
43767
+ continue;
43768
+ }
43769
+ if (code4 === 126 && i + 1 < content4.length && content4.charCodeAt(i + 1) === 126) {
43770
+ toggleToken("strike");
43771
+ i += 1;
43772
+ continue;
43773
+ }
43774
+ if (code4 === 42) {
43775
+ if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 42) {
43776
+ toggleToken("strong");
43777
+ i += 1;
43778
+ } else {
43779
+ toggleToken("em");
43780
+ }
43781
+ continue;
43782
+ }
43783
+ if (enableMath2 && code4 === 36) {
43784
+ if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 36) {
43785
+ toggleToken("math-display");
43786
+ if (mathDisplayOpen) {
43787
+ mathDisplayOpen = false;
43788
+ mathDisplayCrossedNewline = false;
43789
+ } else {
43790
+ mathDisplayOpen = true;
43791
+ mathDisplayCrossedNewline = false;
43792
+ }
43793
+ i += 1;
43794
+ } else {
43795
+ toggleToken("math-inline");
43796
+ }
43797
+ }
43798
+ }
43799
+ const hasIncompleteFormatting = stack.some((token2) => token2 === "code" || token2 === "strike" || token2 === "strong" || token2 === "em");
43800
+ const hasIncompleteMathInline = stack.includes("math-inline");
43801
+ const hasIncompleteMathDisplay = stack.includes("math-display");
43802
+ const hasIncompleteMath = hasIncompleteMathInline || hasIncompleteMathDisplay;
43803
+ if (enableMath2 && hasIncompleteMath) {
43804
+ if (hasIncompleteMathInline && !enableMathInlineAnticipation) {
43805
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
43806
+ }
43807
+ if (hasIncompleteMathDisplay && (!enableMathBlockAnticipation || mathDisplayCrossedNewline)) {
43808
+ return { kind: "raw", status: "raw", reason: "incomplete-math" };
43809
+ }
43810
+ }
43811
+ if (hasIncompleteFormatting && !enableInlineAnticipation) {
43812
+ return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
43813
+ }
43814
+ if (!hasIncompleteFormatting && !hasIncompleteMath) {
43815
+ return { kind: "parse", status: "complete", content: content4, appended: "" };
43816
+ }
43817
+ const appendForToken = (token2) => {
43818
+ switch (token2) {
43819
+ case "code":
43820
+ return "`";
43821
+ case "strike":
43822
+ return "~~";
43823
+ case "strong":
43824
+ return "**";
43825
+ case "em":
43826
+ return "*";
43827
+ case "math-inline":
43828
+ return "$";
43829
+ case "math-display":
43830
+ return "$$";
43831
+ default:
43832
+ return "";
43833
+ }
43834
+ };
43835
+ const appended = stack.slice().reverse().map((token2) => appendForToken(token2)).join("");
43836
+ return { kind: "parse", status: "anticipated", content: content4 + appended, appended };
43837
+ }
43700
43838
  var rehypeSanitizeModule = rehype_sanitize_exports;
43701
43839
  var defaultSchema2 = rehypeSanitizeModule.defaultSchema;
43702
43840
  var resolvePlugin = (mod) => {
@@ -43871,6 +44009,8 @@ function splitByTagSegments(source, baseOffset, parseInline, options) {
43871
44009
  const mdxAutoClose = options?.mdx?.autoClose === true;
43872
44010
  const mdxMaxNewlines = normalizeNewlineLimit(options?.mdx?.maxNewlines);
43873
44011
  const mdxAllowlist = normalizeComponentAllowlist(options?.mdx?.componentAllowlist);
44012
+ const protectedRanges = options?.protectedRanges ?? [];
44013
+ const protectedKinds = protectedRanges.length ? new Set(options?.protectedRangeKinds ?? ["math-inline", "math-display", "code-inline", "code-block", "autolink"]) : null;
43874
44014
  while (match !== null) {
43875
44015
  const start2 = match.index;
43876
44016
  const tagName = match[1];
@@ -43885,6 +44025,18 @@ function splitByTagSegments(source, baseOffset, parseInline, options) {
43885
44025
  continue;
43886
44026
  }
43887
44027
  let end = tagPattern.lastIndex;
44028
+ if (protectedKinds && protectedRanges.length > 0) {
44029
+ const absoluteStart = baseIsFinite ? baseOffset + start2 : start2;
44030
+ const absoluteEnd = baseIsFinite ? baseOffset + end : end;
44031
+ const covered = protectedRanges.some(
44032
+ (range2) => protectedKinds.has(range2.kind) && typeof range2.from === "number" && typeof range2.to === "number" && range2.from <= absoluteStart && range2.to >= absoluteEnd
44033
+ );
44034
+ if (covered) {
44035
+ tagPattern.lastIndex = start2 + 1;
44036
+ match = tagPattern.exec(source);
44037
+ continue;
44038
+ }
44039
+ }
43888
44040
  if (!isSelfClosing && !mdxAllowed) {
43889
44041
  const closingIndex = findClosingHtmlTag(lowerSource, tagName.toLowerCase(), end);
43890
44042
  if (closingIndex === -1) {
@@ -44164,23 +44316,33 @@ function normalizeLang(raw2) {
44164
44316
  }
44165
44317
  function detectMDX(content4, options) {
44166
44318
  const inlineCodeRanges = collectInlineCodeRanges(content4);
44319
+ const protectedRanges = options?.protectedRanges ?? [];
44320
+ const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
44321
+ const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block", "html-inline", "html-block", "autolink"]) : null;
44167
44322
  const componentPattern = /<([A-Z][\w-]*)(\s|\/?>)/g;
44168
44323
  let componentMatch = componentPattern.exec(content4);
44169
44324
  while (componentMatch !== null) {
44170
44325
  const start2 = componentMatch.index;
44171
44326
  const end = start2 + componentMatch[0].length;
44172
- if (!isWithinRanges(start2, end, inlineCodeRanges)) {
44173
- return true;
44327
+ if (isWithinRanges(start2, end, inlineCodeRanges)) {
44328
+ componentMatch = componentPattern.exec(content4);
44329
+ continue;
44330
+ }
44331
+ if (protectedKinds) {
44332
+ const absoluteStart = baseOffset + start2;
44333
+ const absoluteEnd = baseOffset + end;
44334
+ const covered = protectedRanges.some((range2) => protectedKinds.has(range2.kind) && range2.from <= absoluteStart && range2.to >= absoluteEnd);
44335
+ if (covered) {
44336
+ componentMatch = componentPattern.exec(content4);
44337
+ continue;
44338
+ }
44174
44339
  }
44175
- componentMatch = componentPattern.exec(content4);
44340
+ return true;
44176
44341
  }
44177
44342
  if (/(^|\n)\s*(import|export)\s/.test(content4)) {
44178
44343
  return true;
44179
44344
  }
44180
44345
  const expressionPattern = /\{[^{}]+\}/g;
44181
- const protectedRanges = options?.protectedRanges ?? [];
44182
- const baseOffset = typeof options?.baseOffset === "number" ? options.baseOffset : 0;
44183
- const protectedKinds = protectedRanges.length ? /* @__PURE__ */ new Set(["math-inline", "math-display", "code-inline", "code-block"]) : null;
44184
44346
  for (let match = expressionPattern.exec(content4); match !== null; match = expressionPattern.exec(content4)) {
44185
44347
  const index2 = match.index;
44186
44348
  const prev = index2 > 0 ? content4[index2 - 1] : "";
@@ -44397,7 +44559,12 @@ function buildListItemSnapshot(block, listItemNode, ordered, index2, id, baseOff
44397
44559
  }
44398
44560
  if (name3 === "Paragraph") {
44399
44561
  const paragraphRaw = raw2.slice(cursor.from, cursor.to);
44400
- const paragraphData = processListItemParagraph(paragraphRaw);
44562
+ const meta2 = block.payload.meta ?? {};
44563
+ const paragraphData = processListItemParagraph(paragraphRaw, {
44564
+ formatAnticipation: meta2.formatAnticipation,
44565
+ math: meta2.mathEnabled,
44566
+ streaming: !block.isFinalized
44567
+ });
44401
44568
  const parsedInline = paragraphData.inline;
44402
44569
  if (!paragraphHandled) {
44403
44570
  inlineNodes = parsedInline;
@@ -44429,7 +44596,10 @@ function buildListItemSnapshot(block, listItemNode, ordered, index2, id, baseOff
44429
44596
  } else if (name3 === "BulletList" || name3 === "OrderedList") {
44430
44597
  const nestedId = `${id}::list:${subListIndex++}`;
44431
44598
  const nestedOrdered = name3 === "OrderedList";
44432
- childSnapshots.push(buildListNodeSnapshot(block, cursor.node, nestedOrdered, nestedId, baseOffset, raw2));
44599
+ const nestedSnapshot = buildListNodeSnapshot(block, cursor.node, nestedOrdered, nestedId, baseOffset, raw2);
44600
+ if (Array.isArray(nestedSnapshot.children) && nestedSnapshot.children.length > 0) {
44601
+ childSnapshots.push(nestedSnapshot);
44602
+ }
44433
44603
  } else if (name3 === "Blockquote") {
44434
44604
  const quoteId = `${id}::blockquote:${blockquoteIndex++}`;
44435
44605
  childSnapshots.push(buildBlockquoteSnapshot(block, cursor.node, quoteId, baseOffset, raw2));
@@ -44465,11 +44635,31 @@ function buildListItemSnapshot(block, listItemNode, ordered, index2, id, baseOff
44465
44635
  };
44466
44636
  return itemSnapshot;
44467
44637
  }
44468
- function processListItemParagraph(raw2) {
44638
+ function parseListInline(raw2, options) {
44639
+ if (!options?.streaming || !options.formatAnticipation) {
44640
+ return listInlineParser.parse(raw2);
44641
+ }
44642
+ const prepared = prepareInlineStreamingContent(raw2, { formatAnticipation: options.formatAnticipation, math: options.math });
44643
+ if (prepared.kind === "raw") {
44644
+ return [{ kind: "text", text: raw2 }];
44645
+ }
44646
+ let preparedContent = prepared.content;
44647
+ let appended = prepared.appended;
44648
+ const normalized = normalizeFormatAnticipation(options.formatAnticipation);
44649
+ if (normalized.regex) {
44650
+ const regexAppend = listInlineParser.getRegexAnticipationAppend(raw2);
44651
+ if (regexAppend) {
44652
+ preparedContent += regexAppend;
44653
+ appended += regexAppend;
44654
+ }
44655
+ }
44656
+ return listInlineParser.parse(preparedContent, { cache: false });
44657
+ }
44658
+ function processListItemParagraph(raw2, options) {
44469
44659
  const normalized = normalizeParagraphText(raw2);
44470
44660
  const { content: content4, task } = stripTaskMarker(normalized);
44471
- const inline = listInlineParser.parse(content4);
44472
- const segments = extractMixedContentSegments(content4, void 0, (value) => listInlineParser.parse(value));
44661
+ const inline = parseListInline(content4, options);
44662
+ const segments = extractMixedContentSegments(content4, void 0, (value) => parseListInline(value, options));
44473
44663
  return {
44474
44664
  inline,
44475
44665
  segments,
@@ -44754,28 +44944,82 @@ function enrichTableSnapshot(block, snapshot) {
44754
44944
  function enrichCodeSnapshot(block, snapshot) {
44755
44945
  const source = typeof block.payload.meta?.code === "string" ? block.payload.meta?.code : block.payload.raw ?? "";
44756
44946
  const lines = extractCodeLines(source);
44947
+ const meta2 = block.payload.meta;
44757
44948
  const highlightedHtml = block.payload.highlightedHtml ?? "";
44758
- const highlightedLines = extractHighlightedLines(highlightedHtml, lines.length);
44759
- const { preAttrs, codeAttrs } = extractCodeWrapperAttributes(highlightedHtml);
44760
- const lang236 = typeof block.payload.meta?.lang === "string" ? String(block.payload.meta?.lang) : void 0;
44949
+ const hasBlockHighlight = typeof block.payload.highlightedHtml === "string" && block.payload.highlightedHtml.length > 0;
44950
+ const metaLines = Array.isArray(meta2?.highlightedLines) ? meta2?.highlightedLines : null;
44951
+ const includeLineHtml = metaLines ? true : !hasBlockHighlight || lines.length >= 200;
44952
+ const highlightedLines = metaLines ? normalizeHighlightedLines(metaLines, lines.length) : extractHighlightedLines(highlightedHtml, lines.length);
44953
+ const metaTokenLines = Array.isArray(meta2?.tokenLines) ? meta2?.tokenLines : null;
44954
+ const tokenLines = metaTokenLines ? normalizeTokenLines(metaTokenLines, lines.length) : null;
44955
+ const metaDiffKind = Array.isArray(meta2?.diffKind) ? meta2?.diffKind : null;
44956
+ const diffKindLines = metaDiffKind ? normalizeOptionalArray(metaDiffKind, lines.length) : null;
44957
+ const metaOldNo = Array.isArray(meta2?.oldNo) ? meta2?.oldNo : null;
44958
+ const oldNoLines = metaOldNo ? normalizeOptionalArray(metaOldNo, lines.length) : null;
44959
+ const metaNewNo = Array.isArray(meta2?.newNo) ? meta2?.newNo : null;
44960
+ const newNoLines = metaNewNo ? normalizeOptionalArray(metaNewNo, lines.length) : null;
44961
+ const lang236 = typeof meta2?.lang === "string" ? String(meta2.lang) : void 0;
44962
+ let { preAttrs, codeAttrs } = extractCodeWrapperAttributes(highlightedHtml);
44963
+ if (!preAttrs || !codeAttrs) {
44964
+ const defaults = getDefaultCodeWrapperAttributes(lang236);
44965
+ preAttrs = preAttrs ?? defaults.preAttrs;
44966
+ codeAttrs = codeAttrs ?? defaults.codeAttrs;
44967
+ }
44761
44968
  snapshot.props = {
44762
44969
  ...snapshot.props ?? {},
44763
44970
  lang: lang236,
44764
44971
  preAttrs,
44765
44972
  codeAttrs
44766
44973
  };
44767
- snapshot.children = lines.map((line, index2) => ({
44768
- id: `${block.id}::line:${index2}`,
44769
- type: "code-line",
44770
- props: {
44974
+ snapshot.children = lines.map((line, index2) => {
44975
+ const props = {
44771
44976
  index: index2,
44772
44977
  text: line,
44773
- html: highlightedLines[index2] ?? null
44774
- },
44775
- children: []
44776
- }));
44978
+ html: includeLineHtml ? highlightedLines[index2] ?? null : null
44979
+ };
44980
+ if (tokenLines) {
44981
+ props.tokens = tokenLines[index2] ?? null;
44982
+ }
44983
+ if (diffKindLines) {
44984
+ props.diffKind = diffKindLines[index2] ?? null;
44985
+ }
44986
+ if (oldNoLines) {
44987
+ props.oldNo = oldNoLines[index2] ?? null;
44988
+ }
44989
+ if (newNoLines) {
44990
+ props.newNo = newNoLines[index2] ?? null;
44991
+ }
44992
+ return {
44993
+ id: `${block.id}::line:${index2}`,
44994
+ type: "code-line",
44995
+ props,
44996
+ children: []
44997
+ };
44998
+ });
44777
44999
  return snapshot;
44778
45000
  }
45001
+ function normalizeTokenLines(lines, fallbackLength) {
45002
+ if (!lines || lines.length === 0) {
45003
+ return new Array(Math.max(0, fallbackLength)).fill(null);
45004
+ }
45005
+ const length = Math.max(fallbackLength, lines.length);
45006
+ const result = new Array(length).fill(null);
45007
+ for (let i = 0; i < lines.length; i++) {
45008
+ result[i] = lines[i] ?? null;
45009
+ }
45010
+ return result;
45011
+ }
45012
+ function normalizeOptionalArray(lines, fallbackLength) {
45013
+ if (!lines || lines.length === 0) {
45014
+ return new Array(Math.max(0, fallbackLength)).fill(null);
45015
+ }
45016
+ const length = Math.max(fallbackLength, lines.length);
45017
+ const result = new Array(length).fill(null);
45018
+ for (let i = 0; i < lines.length; i++) {
45019
+ result[i] = lines[i] ?? null;
45020
+ }
45021
+ return result;
45022
+ }
44779
45023
  function cloneInlineNodes(nodes) {
44780
45024
  return nodes.map((node2) => {
44781
45025
  if ("children" in node2 && Array.isArray(node2.children)) {
@@ -44892,128 +45136,6 @@ function computeHeavyPatchBudget(credit, config = DEFAULT_BACKPRESSURE_CONFIG) {
44892
45136
  return Math.min(config.maxHeavyPatchBudget, budget);
44893
45137
  }
44894
45138
  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
- }
44919
- function prepareInlineStreamingContent(content4, options) {
44920
- const enableMath2 = options?.math !== false;
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;
44936
- for (let i = 0; i < content4.length; i++) {
44937
- const code4 = content4.charCodeAt(i);
44938
- if (code4 === 10 || code4 === 13) {
44939
- if (mathDisplayOpen) {
44940
- mathDisplayCrossedNewline = true;
44941
- }
44942
- continue;
44943
- }
44944
- if (code4 === 96) {
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;
44951
- continue;
44952
- }
44953
- if (code4 === 42) {
44954
- if (i + 1 < content4.length && content4.charCodeAt(i + 1) === 42) {
44955
- toggleToken("strong");
44956
- i += 1;
44957
- } else {
44958
- toggleToken("em");
44959
- }
44960
- continue;
44961
- }
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
- }
44972
- i += 1;
44973
- } else {
44974
- toggleToken("math-inline");
44975
- }
44976
- }
44977
- }
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
- }
44989
- }
44990
- if (hasIncompleteFormatting && !enableInlineAnticipation) {
44991
- return { kind: "raw", status: "raw", reason: "incomplete-formatting" };
44992
- }
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("");
45015
- return { kind: "parse", status: "anticipated", content: content4 + appended, appended };
45016
- }
45017
45139
 
45018
45140
  // ../markdown-v2-core/dist/perf/patch-batching.mjs
45019
45141
  var LIGHT_APPEND_LINE_THRESHOLD = 4;
@@ -45679,9 +45801,26 @@ var MDXDetectionPlugin = {
45679
45801
  if (block.type !== "paragraph" && block.type !== "html") continue;
45680
45802
  const raw2 = block.payload.raw;
45681
45803
  const blockRange = block.payload.range;
45682
- const baseOffset = typeof blockRange?.from === "number" ? blockRange.from : 0;
45683
- const relevantProtected = filterProtectedRanges(ctx.protectedRanges, baseOffset, baseOffset + raw2.length);
45684
- if (detectMDX(raw2, { protectedRanges: relevantProtected, baseOffset })) {
45804
+ const baseOffset = typeof blockRange?.from === "number" ? blockRange.from : null;
45805
+ let protectedBase = baseOffset ?? 0;
45806
+ let relevantProtected = filterProtectedRanges(ctx.protectedRanges, protectedBase, protectedBase + raw2.length);
45807
+ if (relevantProtected.length === 0) {
45808
+ const metaProtected = Array.isArray(block.payload.meta?.protectedRanges) ? block.payload.meta.protectedRanges ?? [] : [];
45809
+ if (metaProtected.length > 0) {
45810
+ if (baseOffset === null) {
45811
+ protectedBase = 0;
45812
+ relevantProtected = metaProtected;
45813
+ } else {
45814
+ protectedBase = baseOffset;
45815
+ relevantProtected = metaProtected.map((range2) => ({
45816
+ ...range2,
45817
+ from: baseOffset + range2.from,
45818
+ to: baseOffset + range2.to
45819
+ }));
45820
+ }
45821
+ }
45822
+ }
45823
+ if (detectMDX(raw2, { protectedRanges: relevantProtected, baseOffset: protectedBase })) {
45685
45824
  block.payload.meta = { ...block.payload.meta || {}, originalType: block.type };
45686
45825
  block.type = "mdx";
45687
45826
  if ("sanitizedHtml" in block.payload) {
@@ -45774,6 +45913,7 @@ var BLOCK_NODE_TYPES = /* @__PURE__ */ new Set([
45774
45913
  "OrderedList",
45775
45914
  "HTMLBlock",
45776
45915
  "ThematicBreak",
45916
+ "HorizontalRule",
45777
45917
  "ATXHeading",
45778
45918
  "SetextHeading"
45779
45919
  ]);
@@ -45813,6 +45953,7 @@ function mapLezerNodeToBlockType(nodeType) {
45813
45953
  case "HTMLBlock":
45814
45954
  return "html";
45815
45955
  case "ThematicBreak":
45956
+ case "HorizontalRule":
45816
45957
  return "hr";
45817
45958
  default:
45818
45959
  return "paragraph";
@@ -45861,6 +46002,36 @@ function computeParagraphPatchLimit(patches, {
45861
46002
  return Math.min(scaledLimit, patches.length);
45862
46003
  }
45863
46004
 
46005
+ // src/lazy-tokenization.ts
46006
+ var PRIORITY_ORDER = {
46007
+ visible: 2,
46008
+ prefetch: 1
46009
+ };
46010
+ function clampLazyRange(startLine, endLine, totalLines) {
46011
+ const clampedStart = Math.max(0, Math.min(Math.floor(startLine), totalLines));
46012
+ const clampedEnd = Math.max(clampedStart, Math.min(Math.floor(endLine), totalLines));
46013
+ return { startLine: clampedStart, endLine: clampedEnd };
46014
+ }
46015
+ function compareLazyPriority(a, b) {
46016
+ return (PRIORITY_ORDER[a] ?? 0) - (PRIORITY_ORDER[b] ?? 0);
46017
+ }
46018
+ function mergeLazyRequests(existing, next2) {
46019
+ const priority = compareLazyPriority(existing.priority, next2.priority) >= 0 ? existing.priority : next2.priority;
46020
+ const startLine = Math.min(existing.startLine, next2.startLine);
46021
+ const endLine = Math.max(existing.endLine, next2.endLine);
46022
+ const useNextTimestamp = compareLazyPriority(next2.priority, existing.priority) >= 0;
46023
+ return {
46024
+ blockId: existing.blockId,
46025
+ startLine,
46026
+ endLine,
46027
+ priority,
46028
+ requestedAt: useNextTimestamp ? next2.requestedAt : existing.requestedAt
46029
+ };
46030
+ }
46031
+ function lazyRequestRangeSize(request) {
46032
+ return Math.max(0, request.endLine - request.startLine);
46033
+ }
46034
+
45864
46035
  // ../../node_modules/markdown-extensions/index.js
45865
46036
  var markdownExtension = [
45866
46037
  "md",
@@ -81979,9 +82150,24 @@ var deferredPatchQueue = [];
81979
82150
  var MAX_DEFERRED_FLUSH_PATCHES = 120;
81980
82151
  var CODE_HIGHLIGHT_CACHE = /* @__PURE__ */ new Map();
81981
82152
  var MAX_CODE_HIGHLIGHT_CACHE_ENTRIES = 200;
82153
+ var incrementalHighlightStates = /* @__PURE__ */ new Map();
82154
+ var lazyTokenizationStates = /* @__PURE__ */ new Map();
82155
+ var lazyTokenizationQueue = /* @__PURE__ */ new Map();
82156
+ var lazyTokenizationScheduled = false;
82157
+ var lazyTokenizationProcessing = false;
82158
+ var DEFAULT_LAZY_TOKENIZATION_THRESHOLD = 200;
82159
+ var MIN_LAZY_TOKENIZATION_THRESHOLD = 50;
82160
+ var MAX_LAZY_TOKENIZATION_THRESHOLD = 1e4;
82161
+ var lazyTokenizationEnabled = true;
82162
+ var lazyTokenizationThresholdLines = DEFAULT_LAZY_TOKENIZATION_THRESHOLD;
82163
+ var CODE_HIGHLIGHT_THEMES = { dark: "github-dark", light: "github-light" };
81982
82164
  var mdxCompileMode = "server";
81983
82165
  var formatAnticipationConfig = normalizeFormatAnticipation(false);
81984
- var enableLiveCodeHighlighting = false;
82166
+ var codeHighlightingMode = "final";
82167
+ var highlightOutputMode = "html";
82168
+ var emitHighlightTokens = true;
82169
+ var emitDiffBlocks = false;
82170
+ var liveTokenizationEnabled = true;
81985
82171
  var enableMath = true;
81986
82172
  var mdxComponentAllowlist = null;
81987
82173
  var WORKER_MDX_CACHE = /* @__PURE__ */ new Map();
@@ -82083,6 +82269,12 @@ var WorkerMetricsCollector = class {
82083
82269
  this.appendLineBatchCount = 0;
82084
82270
  this.appendLineTotalLines = 0;
82085
82271
  this.appendLineMaxLines = 0;
82272
+ this.lazyTokenizationRequests = 0;
82273
+ this.lazyTokenizationRangeTotal = 0;
82274
+ this.lazyTokenizationRangeMax = 0;
82275
+ this.lazyTokenizationLatencyTotal = 0;
82276
+ this.lazyTokenizationLatencyMax = 0;
82277
+ this.lazyTokenizationMaxQueue = 0;
82086
82278
  this.grammarEngine = grammarEngine;
82087
82279
  this.startedAt = now();
82088
82280
  }
@@ -82137,6 +82329,29 @@ var WorkerMetricsCollector = class {
82137
82329
  this.appendLineMaxLines = normalized;
82138
82330
  }
82139
82331
  }
82332
+ recordLazyTokenization(rangeLines, latencyMs, queueDepth) {
82333
+ if (Number.isFinite(rangeLines ?? Number.NaN)) {
82334
+ const normalized = Math.max(0, Math.floor(Number(rangeLines)));
82335
+ this.lazyTokenizationRequests += 1;
82336
+ this.lazyTokenizationRangeTotal += normalized;
82337
+ if (normalized > this.lazyTokenizationRangeMax) {
82338
+ this.lazyTokenizationRangeMax = normalized;
82339
+ }
82340
+ }
82341
+ if (Number.isFinite(latencyMs ?? Number.NaN)) {
82342
+ const normalizedLatency = Math.max(0, Number(latencyMs));
82343
+ this.lazyTokenizationLatencyTotal += normalizedLatency;
82344
+ if (normalizedLatency > this.lazyTokenizationLatencyMax) {
82345
+ this.lazyTokenizationLatencyMax = normalizedLatency;
82346
+ }
82347
+ }
82348
+ if (Number.isFinite(queueDepth ?? Number.NaN)) {
82349
+ const normalizedQueue = Math.max(0, Math.floor(Number(queueDepth)));
82350
+ if (normalizedQueue > this.lazyTokenizationMaxQueue) {
82351
+ this.lazyTokenizationMaxQueue = normalizedQueue;
82352
+ }
82353
+ }
82354
+ }
82140
82355
  markDiffStart() {
82141
82356
  this.diffStart = now();
82142
82357
  }
@@ -82199,7 +82414,15 @@ var WorkerMetricsCollector = class {
82199
82414
  highlightByLanguage: mapToHighlightRecord(this.highlightByLanguage),
82200
82415
  appendLineBatches: this.appendLineBatchCount || void 0,
82201
82416
  appendLineTotalLines: this.appendLineTotalLines || void 0,
82202
- appendLineMaxLines: this.appendLineMaxLines || void 0
82417
+ appendLineMaxLines: this.appendLineMaxLines || void 0,
82418
+ lazyTokenization: this.lazyTokenizationRequests > 0 ? {
82419
+ requests: this.lazyTokenizationRequests,
82420
+ avgRangeLines: roundMetric(this.lazyTokenizationRangeTotal / this.lazyTokenizationRequests),
82421
+ maxRangeLines: this.lazyTokenizationRangeMax,
82422
+ avgLatencyMs: roundMetric(this.lazyTokenizationLatencyTotal / this.lazyTokenizationRequests),
82423
+ maxLatencyMs: roundMetric(this.lazyTokenizationLatencyMax),
82424
+ maxQueue: this.lazyTokenizationMaxQueue
82425
+ } : void 0
82203
82426
  };
82204
82427
  }
82205
82428
  };
@@ -82362,6 +82585,11 @@ async function initialize(initialContent = "", prewarmLangs = [], docPlugins, md
82362
82585
  lastTree = null;
82363
82586
  currentContent = "";
82364
82587
  deferredPatchQueue = [];
82588
+ resetIncrementalHighlightState();
82589
+ lazyTokenizationStates.clear();
82590
+ lazyTokenizationQueue.clear();
82591
+ lazyTokenizationScheduled = false;
82592
+ lazyTokenizationProcessing = false;
82365
82593
  mdxCompileMode = mdxOptions?.compileMode ?? "server";
82366
82594
  try {
82367
82595
  if (DEBUG_MDX) {
@@ -82378,11 +82606,35 @@ async function initialize(initialContent = "", prewarmLangs = [], docPlugins, md
82378
82606
  callouts: docPlugins?.callouts ?? false,
82379
82607
  math: docPlugins?.math ?? true,
82380
82608
  formatAnticipation: docPlugins?.formatAnticipation ?? false,
82381
- liveCodeHighlighting: docPlugins?.liveCodeHighlighting ?? false
82609
+ codeHighlighting: docPlugins?.codeHighlighting,
82610
+ liveCodeHighlighting: docPlugins?.liveCodeHighlighting ?? false,
82611
+ liveTokenization: docPlugins?.liveTokenization ?? true,
82612
+ emitHighlightTokens: docPlugins?.emitHighlightTokens ?? true,
82613
+ emitDiffBlocks: docPlugins?.emitDiffBlocks ?? false
82382
82614
  };
82383
82615
  enableMath = enable.math;
82384
82616
  formatAnticipationConfig = normalizeFormatAnticipation(enable.formatAnticipation);
82385
- enableLiveCodeHighlighting = enable.liveCodeHighlighting;
82617
+ if (enable.codeHighlighting === "incremental" || enable.codeHighlighting === "live" || enable.codeHighlighting === "final") {
82618
+ codeHighlightingMode = enable.codeHighlighting;
82619
+ } else {
82620
+ codeHighlightingMode = enable.liveCodeHighlighting ? "live" : "final";
82621
+ }
82622
+ if (docPlugins?.outputMode === "html" || docPlugins?.outputMode === "tokens" || docPlugins?.outputMode === "both") {
82623
+ highlightOutputMode = docPlugins.outputMode;
82624
+ } else {
82625
+ highlightOutputMode = "html";
82626
+ }
82627
+ emitHighlightTokens = enable.emitHighlightTokens;
82628
+ emitDiffBlocks = enable.emitDiffBlocks;
82629
+ liveTokenizationEnabled = enable.liveTokenization;
82630
+ if (docPlugins?.lazyTokenization) {
82631
+ lazyTokenizationEnabled = docPlugins.lazyTokenization.enabled ?? true;
82632
+ const desiredThreshold = docPlugins.lazyTokenization.thresholdLines ?? DEFAULT_LAZY_TOKENIZATION_THRESHOLD;
82633
+ lazyTokenizationThresholdLines = clampInt(desiredThreshold, MIN_LAZY_TOKENIZATION_THRESHOLD, MAX_LAZY_TOKENIZATION_THRESHOLD);
82634
+ } else {
82635
+ lazyTokenizationEnabled = true;
82636
+ lazyTokenizationThresholdLines = DEFAULT_LAZY_TOKENIZATION_THRESHOLD;
82637
+ }
82386
82638
  if (Array.isArray(docPlugins?.mdxComponentNames) && docPlugins?.mdxComponentNames.length > 0) {
82387
82639
  mdxComponentAllowlist = new Set(docPlugins.mdxComponentNames);
82388
82640
  } else {
@@ -82396,7 +82648,7 @@ async function initialize(initialContent = "", prewarmLangs = [], docPlugins, md
82396
82648
  if (enable.html) globalDocumentPluginRegistry.register(HTMLBlockPlugin);
82397
82649
  if (enable.mdx) globalDocumentPluginRegistry.register(MDXDetectionPlugin);
82398
82650
  performanceTimer.mark("highlighter-init");
82399
- const coreLangs = ["javascript", "typescript", "json", "text", "markdown"];
82651
+ const coreLangs = ["javascript", "typescript", "json", "text", "markdown", "diff"];
82400
82652
  const initialLangs = [...coreLangs, ...prewarmLangs];
82401
82653
  highlighter = await createHighlighter({
82402
82654
  engine: createJavaScriptRegexEngine(),
@@ -82493,6 +82745,7 @@ async function appendAndReparse(appendedText, metrics) {
82493
82745
  blocks = changedBlocks;
82494
82746
  lastTree = newTree;
82495
82747
  currentContent = newContent;
82748
+ pruneLazyTokenizationStates(blocks);
82496
82749
  performanceTimer.measure("incremental-parse");
82497
82750
  metrics?.markParseEnd();
82498
82751
  metrics?.setBlocksProduced(blocks.length);
@@ -82671,22 +82924,35 @@ async function enrichBlock(block) {
82671
82924
  nextMeta.inlineStatus = void 0;
82672
82925
  metaChanged = true;
82673
82926
  }
82674
- const mathRanges = enableMath ? collectMathProtectedRanges(rawParagraph) : [];
82675
- if (mathRanges.length > 0) {
82676
- nextMeta.protectedRanges = mathRanges;
82677
- metaChanged = true;
82678
- } else if (Object.prototype.hasOwnProperty.call(nextMeta, "protectedRanges")) {
82679
- nextMeta.protectedRanges = void 0;
82680
- metaChanged = true;
82927
+ const baseOffset = typeof block.payload.range?.from === "number" ? block.payload.range.from : void 0;
82928
+ const protectedRanges = [];
82929
+ if (enableMath) {
82930
+ protectedRanges.push(...collectMathProtectedRanges(rawParagraph));
82931
+ }
82932
+ const autolinkRanges = collectAutolinkProtectedRanges(rawParagraph);
82933
+ if (autolinkRanges.length > 0) {
82934
+ protectedRanges.push(...autolinkRanges);
82681
82935
  }
82682
82936
  const shouldExtractSegments = typeof rawParagraph === "string" && (rawParagraph.includes("<") || rawParagraph.includes("{"));
82683
82937
  if (shouldExtractSegments) {
82684
- const baseOffset = typeof block.payload.range?.from === "number" ? block.payload.range.from : void 0;
82685
82938
  const mixedOptions = !block.isFinalized && shouldAllowMixedStreaming() ? {
82686
82939
  html: formatAnticipationConfig.html ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES } : void 0,
82687
82940
  mdx: formatAnticipationConfig.mdx ? { autoClose: true, maxNewlines: MIXED_CONTENT_AUTOCLOSE_NEWLINES, componentAllowlist: mdxComponentAllowlist ?? void 0 } : void 0
82688
82941
  } : void 0;
82689
- const segments = extractMixedContentSegments(rawParagraph, baseOffset, (value) => inlineParse(value), mixedOptions);
82942
+ const protectedRangesAbsolute = typeof baseOffset === "number" && protectedRanges.length > 0 ? protectedRanges.map((range2) => ({
82943
+ ...range2,
82944
+ from: baseOffset + range2.from,
82945
+ to: baseOffset + range2.to
82946
+ })) : void 0;
82947
+ const mixedSegmentOptions = mixedOptions || protectedRangesAbsolute ? {
82948
+ ...mixedOptions,
82949
+ protectedRanges: protectedRangesAbsolute
82950
+ } : void 0;
82951
+ const segments = extractMixedContentSegments(rawParagraph, baseOffset, (value) => inlineParse(value), mixedSegmentOptions);
82952
+ const htmlRanges = collectHtmlProtectedRangesFromSegments(segments, baseOffset);
82953
+ if (htmlRanges.length > 0) {
82954
+ protectedRanges.push(...htmlRanges);
82955
+ }
82690
82956
  if (segments.length > 0) {
82691
82957
  nextMeta.mixedSegments = segments;
82692
82958
  metaChanged = true;
@@ -82713,6 +82979,13 @@ async function enrichBlock(block) {
82713
82979
  metaChanged = true;
82714
82980
  }
82715
82981
  }
82982
+ if (protectedRanges.length > 0) {
82983
+ nextMeta.protectedRanges = protectedRanges;
82984
+ metaChanged = true;
82985
+ } else if (Object.prototype.hasOwnProperty.call(nextMeta, "protectedRanges")) {
82986
+ nextMeta.protectedRanges = void 0;
82987
+ metaChanged = true;
82988
+ }
82716
82989
  if (metaChanged) {
82717
82990
  if (Object.keys(nextMeta).length > 0) {
82718
82991
  block.payload.meta = nextMeta;
@@ -82728,9 +83001,14 @@ async function enrichBlock(block) {
82728
83001
  await enrichCodeBlock(block);
82729
83002
  break;
82730
83003
  case "html": {
82731
- const sanitized = sanitizeHtmlInWorker(block.payload.raw);
83004
+ const rawHtml = typeof block.payload.raw === "string" ? block.payload.raw : "";
83005
+ const sanitized = sanitizeHtmlInWorker(rawHtml);
82732
83006
  block.payload.sanitizedHtml = sanitized;
82733
- block.payload.meta = { ...block.payload.meta || {}, sanitized: true };
83007
+ const nextMeta = { ...block.payload.meta || {}, sanitized: true };
83008
+ if (rawHtml) {
83009
+ nextMeta.protectedRanges = [{ from: 0, to: rawHtml.length, kind: "html-block" }];
83010
+ }
83011
+ block.payload.meta = nextMeta;
82734
83012
  break;
82735
83013
  }
82736
83014
  case "list":
@@ -82750,8 +83028,12 @@ async function enrichBlock(block) {
82750
83028
  const mdxOptions = normalizedRanges && normalizedRanges.length > 0 ? { protectedRanges: normalizedRanges, baseOffset } : baseOffset ? { baseOffset } : void 0;
82751
83029
  const mdxDetectStart = now();
82752
83030
  let shouldConvertToMDX = detectMDX(block.payload.raw, mdxOptions);
83031
+ if (!shouldConvertToMDX && block.type === "html") {
83032
+ const fallbackOptions = baseOffset ? { baseOffset } : void 0;
83033
+ shouldConvertToMDX = detectMDX(block.payload.raw, fallbackOptions);
83034
+ }
82753
83035
  metrics?.recordMdxDetect(now() - mdxDetectStart);
82754
- if (shouldConvertToMDX && protectedRanges && protectedRanges.length > 0) {
83036
+ if (shouldConvertToMDX && protectedRanges && protectedRanges.length > 0 && block.type !== "html") {
82755
83037
  const exprPattern = /\{[^{}]+\}/g;
82756
83038
  let match;
82757
83039
  while (true) {
@@ -82838,65 +83120,1092 @@ function collectMathProtectedRanges(content4) {
82838
83120
  }
82839
83121
  return ranges;
82840
83122
  }
83123
+ function collectAutolinkProtectedRanges(content4) {
83124
+ if (!content4) return [];
83125
+ const ranges = [];
83126
+ const autolinkPattern = /<((?:https?:\/\/|mailto:)[^>\s]+)>/gi;
83127
+ let match = autolinkPattern.exec(content4);
83128
+ while (match !== null) {
83129
+ ranges.push({ from: match.index, to: match.index + match[0].length, kind: "autolink" });
83130
+ match = autolinkPattern.exec(content4);
83131
+ }
83132
+ return ranges;
83133
+ }
83134
+ function collectHtmlProtectedRangesFromSegments(segments, baseOffset) {
83135
+ if (!segments || segments.length === 0) return [];
83136
+ if (typeof baseOffset !== "number" || !Number.isFinite(baseOffset)) {
83137
+ return [];
83138
+ }
83139
+ const ranges = [];
83140
+ for (const segment of segments) {
83141
+ if (segment.kind !== "html") continue;
83142
+ const range2 = segment.range;
83143
+ if (!range2) continue;
83144
+ const from = range2.from - baseOffset;
83145
+ const to = range2.to - baseOffset;
83146
+ if (!Number.isFinite(from) || !Number.isFinite(to) || to <= from) continue;
83147
+ ranges.push({ from, to, kind: "html-inline" });
83148
+ }
83149
+ return ranges;
83150
+ }
83151
+ var FONT_STYLE_ITALIC = 1;
83152
+ var FONT_STYLE_BOLD = 2;
83153
+ var FONT_STYLE_UNDERLINE = 4;
83154
+ var FONT_STYLE_STRIKETHROUGH = 8;
83155
+ function escapeHtmlText(text12) {
83156
+ return text12.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
83157
+ }
83158
+ function renderShikiToken(token2) {
83159
+ const dark = token2.variants.dark;
83160
+ const light = token2.variants.light;
83161
+ const styles2 = [];
83162
+ if (dark?.color) {
83163
+ styles2.push(`--shiki-dark:${dark.color}`);
83164
+ }
83165
+ if (light?.color) {
83166
+ styles2.push(`--shiki-light:${light.color}`);
83167
+ }
83168
+ const fontStyle = light?.fontStyle ?? dark?.fontStyle;
83169
+ if (typeof fontStyle === "number" && fontStyle > 0) {
83170
+ if (fontStyle & FONT_STYLE_ITALIC) {
83171
+ styles2.push("font-style: italic");
83172
+ }
83173
+ if (fontStyle & FONT_STYLE_BOLD) {
83174
+ styles2.push("font-weight: bold");
83175
+ }
83176
+ const decorations2 = [];
83177
+ if (fontStyle & FONT_STYLE_UNDERLINE) {
83178
+ decorations2.push("underline");
83179
+ }
83180
+ if (fontStyle & FONT_STYLE_STRIKETHROUGH) {
83181
+ decorations2.push("line-through");
83182
+ }
83183
+ if (decorations2.length > 0) {
83184
+ styles2.push(`text-decoration: ${decorations2.join(" ")}`);
83185
+ }
83186
+ }
83187
+ const styleAttr = styles2.length > 0 ? ` style="${styles2.join(";")}"` : "";
83188
+ return `<span${styleAttr}>${escapeHtmlText(token2.content)}</span>`;
83189
+ }
83190
+ function getTokenFontStyle(token2) {
83191
+ const dark = token2.variants?.dark?.fontStyle ?? 0;
83192
+ const light = token2.variants?.light?.fontStyle ?? 0;
83193
+ return (typeof dark === "number" ? dark : 0) | (typeof light === "number" ? light : 0);
83194
+ }
83195
+ function mergeWhitespaceTokens2(tokens) {
83196
+ return tokens.map((line) => {
83197
+ const merged = [];
83198
+ let carryContent = "";
83199
+ let carryOffset = 0;
83200
+ let carryVariants = null;
83201
+ line.forEach((token2, idx) => {
83202
+ const fontStyle = getTokenFontStyle(token2);
83203
+ const couldMerge = (fontStyle & FONT_STYLE_UNDERLINE) === 0;
83204
+ if (couldMerge && /^\s+$/.test(token2.content) && line[idx + 1]) {
83205
+ if (!carryContent) {
83206
+ carryOffset = token2.offset ?? 0;
83207
+ carryVariants = token2.variants;
83208
+ }
83209
+ carryContent += token2.content;
83210
+ return;
83211
+ }
83212
+ if (carryContent) {
83213
+ if (couldMerge) {
83214
+ merged.push({ ...token2, offset: carryOffset, content: carryContent + token2.content });
83215
+ } else {
83216
+ merged.push({ content: carryContent, offset: carryOffset, variants: carryVariants ?? token2.variants });
83217
+ merged.push(token2);
83218
+ }
83219
+ carryContent = "";
83220
+ carryOffset = 0;
83221
+ carryVariants = null;
83222
+ return;
83223
+ }
83224
+ merged.push(token2);
83225
+ });
83226
+ return merged;
83227
+ });
83228
+ }
83229
+ function renderShikiLines(tokens) {
83230
+ const merged = mergeWhitespaceTokens2(tokens);
83231
+ return merged.map((lineTokens) => lineTokens.map(renderShikiToken).join(""));
83232
+ }
83233
+ function detectDiffLanguage(lang236, meta2) {
83234
+ const normalized = (lang236 || "").trim().toLowerCase();
83235
+ if (!normalized) {
83236
+ return { isDiff: false, diffLang: "diff", baseLang: null };
83237
+ }
83238
+ let baseLang = null;
83239
+ if (normalized === "diff" || normalized === "udiff" || normalized === "diff-unified") {
83240
+ baseLang = null;
83241
+ } else if (normalized.startsWith("diff-")) {
83242
+ baseLang = normalized.slice("diff-".length) || null;
83243
+ } else if (normalized.endsWith("-diff")) {
83244
+ baseLang = normalized.slice(0, Math.max(0, normalized.length - "-diff".length)) || null;
83245
+ } else {
83246
+ return { isDiff: false, diffLang: "diff", baseLang: null };
83247
+ }
83248
+ if (!baseLang) {
83249
+ const metaLang = typeof meta2.lang === "string" ? meta2.lang : typeof meta2.language === "string" ? meta2.language : typeof meta2.base === "string" ? meta2.base : null;
83250
+ if (metaLang) {
83251
+ baseLang = metaLang;
83252
+ } else {
83253
+ const metaKeys = Object.keys(meta2);
83254
+ if (metaKeys.length > 0) {
83255
+ baseLang = metaKeys[0] ?? null;
83256
+ }
83257
+ }
83258
+ }
83259
+ return {
83260
+ isDiff: true,
83261
+ diffLang: "diff",
83262
+ baseLang: baseLang ? normalizeLang(String(baseLang)) : null
83263
+ };
83264
+ }
83265
+ function parseDiffHunkHeader(line) {
83266
+ const match = line.match(/^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/);
83267
+ if (!match) return null;
83268
+ return {
83269
+ oldStart: Number.parseInt(match[1] ?? "0", 10),
83270
+ newStart: Number.parseInt(match[3] ?? "0", 10)
83271
+ };
83272
+ }
83273
+ function isDiffMetaLine(line) {
83274
+ if (!line) return false;
83275
+ return line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("new file") || line.startsWith("deleted file") || line.startsWith("similarity index") || line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("mode ") || line.startsWith("\\\\ No newline");
83276
+ }
83277
+ function parseUnifiedDiffLine(line, cursor) {
83278
+ if (line.startsWith("@@")) {
83279
+ const header = parseDiffHunkHeader(line);
83280
+ if (header) {
83281
+ cursor.oldLine = header.oldStart;
83282
+ cursor.newLine = header.newStart;
83283
+ }
83284
+ return { text: line, kind: "hunk", prefix: "", content: line, oldNo: null, newNo: null };
83285
+ }
83286
+ if (line.startsWith("--- ") || line.startsWith("+++ ") || isDiffMetaLine(line)) {
83287
+ return { text: line, kind: "meta", prefix: "", content: line, oldNo: null, newNo: null };
83288
+ }
83289
+ if (line.startsWith("+")) {
83290
+ if (line.startsWith("+++")) {
83291
+ return { text: line, kind: "meta", prefix: "", content: line, oldNo: null, newNo: null };
83292
+ }
83293
+ const newNo = cursor.newLine;
83294
+ if (cursor.newLine !== null) cursor.newLine += 1;
83295
+ return { text: line, kind: "add", prefix: "+", content: line.slice(1), oldNo: null, newNo };
83296
+ }
83297
+ if (line.startsWith("-")) {
83298
+ if (line.startsWith("---")) {
83299
+ return { text: line, kind: "meta", prefix: "", content: line, oldNo: null, newNo: null };
83300
+ }
83301
+ const oldNo = cursor.oldLine;
83302
+ if (cursor.oldLine !== null) cursor.oldLine += 1;
83303
+ return { text: line, kind: "remove", prefix: "-", content: line.slice(1), oldNo, newNo: null };
83304
+ }
83305
+ if (line.startsWith(" ")) {
83306
+ const oldNo = cursor.oldLine;
83307
+ const newNo = cursor.newLine;
83308
+ if (cursor.oldLine !== null) cursor.oldLine += 1;
83309
+ if (cursor.newLine !== null) cursor.newLine += 1;
83310
+ return { text: line, kind: "context", prefix: " ", content: line.slice(1), oldNo, newNo };
83311
+ }
83312
+ return { text: line, kind: "meta", prefix: "", content: line, oldNo: null, newNo: null };
83313
+ }
83314
+ function normalizeDiffPath(value) {
83315
+ if (!value) return null;
83316
+ let path3 = value.trim();
83317
+ if (!path3 || path3 === "/dev/null") return null;
83318
+ if (path3.startsWith('"') && path3.endsWith('"') || path3.startsWith("'") && path3.endsWith("'")) {
83319
+ path3 = path3.slice(1, -1);
83320
+ }
83321
+ if (path3.startsWith("a/") || path3.startsWith("b/")) {
83322
+ path3 = path3.slice(2);
83323
+ }
83324
+ return path3 || null;
83325
+ }
83326
+ function extractDiffFilePath(line) {
83327
+ if (line.startsWith("diff --git")) {
83328
+ const match = line.match(/^diff --git\\s+(\\S+)\\s+(\\S+)/);
83329
+ if (match) {
83330
+ return normalizeDiffPath(match[2] ?? match[1] ?? null);
83331
+ }
83332
+ }
83333
+ if (line.startsWith("+++ ") || line.startsWith("--- ")) {
83334
+ const path3 = normalizeDiffPath(line.slice(4));
83335
+ return path3;
83336
+ }
83337
+ if (line.startsWith("rename to ")) {
83338
+ return normalizeDiffPath(line.slice("rename to ".length));
83339
+ }
83340
+ return null;
83341
+ }
83342
+ function looksLikeUnifiedDiff(lines) {
83343
+ if (lines.length === 0) return false;
83344
+ for (const line of lines) {
83345
+ if (line.startsWith("diff --git") || line.startsWith("@@") || line.startsWith("+++ ") || line.startsWith("--- ")) {
83346
+ return true;
83347
+ }
83348
+ }
83349
+ return false;
83350
+ }
83351
+ function guessLanguageFromPath(filePath) {
83352
+ if (!filePath) return null;
83353
+ const parts = filePath.split(/[\\\\/]/);
83354
+ const file = parts[parts.length - 1] ?? "";
83355
+ const idx = file.lastIndexOf(".");
83356
+ if (idx <= 0 || idx >= file.length - 1) return null;
83357
+ const ext = file.slice(idx + 1);
83358
+ return normalizeLang(ext);
83359
+ }
83360
+ function guessLanguageFromDiffLines(lines) {
83361
+ for (const line of lines) {
83362
+ const filePath = extractDiffFilePath(line);
83363
+ if (filePath) {
83364
+ const guessed = guessLanguageFromPath(filePath);
83365
+ if (guessed) return guessed;
83366
+ }
83367
+ }
83368
+ return null;
83369
+ }
83370
+ function toDiffLineKind(kind) {
83371
+ if (kind === "remove") return "del";
83372
+ return kind;
83373
+ }
83374
+ function toThemedLine(tokenLine, theme) {
83375
+ if (!tokenLine) return null;
83376
+ return tokenLine.spans.map((span) => {
83377
+ const style2 = span.s ?? span.v?.[theme];
83378
+ const color3 = typeof style2?.fg === "string" ? style2.fg : null;
83379
+ const fontStyle = typeof style2?.fs === "number" ? style2.fs : null;
83380
+ return {
83381
+ content: span.t,
83382
+ color: color3,
83383
+ fontStyle
83384
+ };
83385
+ });
83386
+ }
83387
+ function stripPrefixFromThemedLine(tokens, prefix) {
83388
+ if (!tokens || !prefix) return tokens;
83389
+ if (tokens.length === 0) return tokens;
83390
+ const first = tokens[0];
83391
+ if (first.content === prefix) {
83392
+ return tokens.slice(1);
83393
+ }
83394
+ if (first.content.startsWith(prefix)) {
83395
+ const trimmed = first.content.slice(prefix.length);
83396
+ const next2 = trimmed ? [{ ...first, content: trimmed }, ...tokens.slice(1)] : tokens.slice(1);
83397
+ return next2;
83398
+ }
83399
+ return tokens;
83400
+ }
83401
+ function buildDiffBlocksFromLines(lines, rawLines, tokenLines, defaultLanguage) {
83402
+ const blocks2 = [];
83403
+ let current2 = null;
83404
+ let currentRaw = [];
83405
+ let additions = 0;
83406
+ let deletions = 0;
83407
+ const finalize = () => {
83408
+ if (!current2) return;
83409
+ current2.additions = additions;
83410
+ current2.deletions = deletions;
83411
+ if (currentRaw.length > 0) {
83412
+ current2.unified = currentRaw.join("\n");
83413
+ }
83414
+ blocks2.push(current2);
83415
+ current2 = null;
83416
+ currentRaw = [];
83417
+ additions = 0;
83418
+ deletions = 0;
83419
+ };
83420
+ for (let i = 0; i < lines.length; i++) {
83421
+ const line = lines[i];
83422
+ const raw2 = rawLines[i] ?? line.text;
83423
+ const filePath = extractDiffFilePath(raw2);
83424
+ if (raw2.startsWith("diff --git")) {
83425
+ finalize();
83426
+ }
83427
+ if (!current2) {
83428
+ current2 = {
83429
+ kind: "diff",
83430
+ filePath: filePath ?? null,
83431
+ language: filePath ? guessLanguageFromPath(filePath) ?? defaultLanguage : defaultLanguage,
83432
+ lines: [],
83433
+ additions: null,
83434
+ deletions: null,
83435
+ unified: null
83436
+ };
83437
+ } else if (filePath && !current2.filePath) {
83438
+ current2.filePath = filePath;
83439
+ if (!current2.language) {
83440
+ current2.language = guessLanguageFromPath(filePath) ?? defaultLanguage;
83441
+ }
83442
+ }
83443
+ if (line.kind === "add") additions += 1;
83444
+ if (line.kind === "remove") deletions += 1;
83445
+ let themed = tokenLines ? toThemedLine(tokenLines[i] ?? null, "dark") : null;
83446
+ if (line.kind === "add" || line.kind === "remove" || line.kind === "context") {
83447
+ themed = stripPrefixFromThemedLine(themed, line.prefix);
83448
+ }
83449
+ const entry = {
83450
+ kind: toDiffLineKind(line.kind),
83451
+ oldNo: line.oldNo ?? null,
83452
+ newNo: line.newNo ?? null,
83453
+ raw: raw2,
83454
+ tokens: themed ?? null
83455
+ };
83456
+ current2.lines.push(entry);
83457
+ currentRaw.push(raw2);
83458
+ }
83459
+ finalize();
83460
+ return blocks2;
83461
+ }
83462
+ function tokenizeDiffRun(lines, language, grammarState) {
83463
+ if (!highlighter) {
83464
+ return { tokens: [], nextGrammarState: grammarState };
83465
+ }
83466
+ const content4 = lines.map((line) => line.content).join("\\n");
83467
+ if (!content4 && lines.length > 0) {
83468
+ return { tokens: lines.map(() => []), nextGrammarState: grammarState };
83469
+ }
83470
+ const tokens = highlighter.codeToTokensWithThemes(content4, {
83471
+ lang: language,
83472
+ themes: CODE_HIGHLIGHT_THEMES,
83473
+ grammarState
83474
+ });
83475
+ const nextGrammarState = highlighter.getLastGrammarState(tokens);
83476
+ return { tokens, nextGrammarState };
83477
+ }
83478
+ function buildDiffTokenLines(lines, language, grammarState) {
83479
+ const output = [];
83480
+ let idx = 0;
83481
+ let nextOldState = grammarState.old;
83482
+ let nextNewState = grammarState.new;
83483
+ while (idx < lines.length) {
83484
+ const line = lines[idx];
83485
+ if (line.kind === "meta" || line.kind === "hunk") {
83486
+ output.push({ spans: [{ t: line.text }] });
83487
+ idx += 1;
83488
+ continue;
83489
+ }
83490
+ const runKind = line.kind;
83491
+ const run = [];
83492
+ while (idx < lines.length && lines[idx].kind === runKind) {
83493
+ run.push(lines[idx]);
83494
+ idx += 1;
83495
+ }
83496
+ try {
83497
+ if (runKind === "add") {
83498
+ const { tokens, nextGrammarState } = tokenizeDiffRun(run, language, nextNewState);
83499
+ nextNewState = nextGrammarState;
83500
+ const tokenLines = renderTokenLines(tokens);
83501
+ for (let i = 0; i < run.length; i++) {
83502
+ const prefixSpan = { t: run[i].prefix };
83503
+ const lineTokens = tokenLines[i] ?? null;
83504
+ if (!lineTokens || lineTokens.spans.length === 0) {
83505
+ const fullText = `${run[i].prefix}${run[i].content}`;
83506
+ output.push(fullText.length > 0 ? { spans: [{ t: fullText }] } : { spans: [] });
83507
+ } else {
83508
+ output.push({ spans: [prefixSpan, ...lineTokens.spans] });
83509
+ }
83510
+ }
83511
+ continue;
83512
+ }
83513
+ if (runKind === "remove") {
83514
+ const { tokens, nextGrammarState } = tokenizeDiffRun(run, language, nextOldState);
83515
+ nextOldState = nextGrammarState;
83516
+ const tokenLines = renderTokenLines(tokens);
83517
+ for (let i = 0; i < run.length; i++) {
83518
+ const prefixSpan = { t: run[i].prefix };
83519
+ const lineTokens = tokenLines[i] ?? null;
83520
+ if (!lineTokens || lineTokens.spans.length === 0) {
83521
+ const fullText = `${run[i].prefix}${run[i].content}`;
83522
+ output.push(fullText.length > 0 ? { spans: [{ t: fullText }] } : { spans: [] });
83523
+ } else {
83524
+ output.push({ spans: [prefixSpan, ...lineTokens.spans] });
83525
+ }
83526
+ }
83527
+ continue;
83528
+ }
83529
+ if (runKind === "context") {
83530
+ const { tokens, nextGrammarState } = tokenizeDiffRun(run, language, nextNewState);
83531
+ nextNewState = nextGrammarState;
83532
+ if (run.length > 0) {
83533
+ const oldResult = tokenizeDiffRun(run, language, nextOldState);
83534
+ nextOldState = oldResult.nextGrammarState;
83535
+ }
83536
+ const tokenLines = renderTokenLines(tokens);
83537
+ for (let i = 0; i < run.length; i++) {
83538
+ const prefixSpan = { t: run[i].prefix };
83539
+ const lineTokens = tokenLines[i] ?? null;
83540
+ if (!lineTokens || lineTokens.spans.length === 0) {
83541
+ const fullText = `${run[i].prefix}${run[i].content}`;
83542
+ output.push(fullText.length > 0 ? { spans: [{ t: fullText }] } : { spans: [] });
83543
+ } else {
83544
+ output.push({ spans: [prefixSpan, ...lineTokens.spans] });
83545
+ }
83546
+ }
83547
+ continue;
83548
+ }
83549
+ } catch (error) {
83550
+ console.warn("Diff tokenization failed for", language, error);
83551
+ }
83552
+ for (let i = 0; i < run.length; i++) {
83553
+ const fullText = run[i].text;
83554
+ output.push(fullText.length > 0 ? { spans: [{ t: fullText }] } : { spans: [] });
83555
+ }
83556
+ }
83557
+ return { tokenLines: output, grammarState: { old: nextOldState, new: nextNewState } };
83558
+ }
83559
+ function toTokenStyle(style2) {
83560
+ if (!style2) return void 0;
83561
+ const fg = typeof style2.color === "string" ? style2.color : void 0;
83562
+ const fs = typeof style2.fontStyle === "number" && style2.fontStyle > 0 ? style2.fontStyle : void 0;
83563
+ if (!fg && fs === void 0) return void 0;
83564
+ return { fg, fs };
83565
+ }
83566
+ function toTokenSpan(token2) {
83567
+ const dark = toTokenStyle(token2.variants.dark);
83568
+ const light = toTokenStyle(token2.variants.light);
83569
+ const span = { t: token2.content };
83570
+ if (dark || light) {
83571
+ span.v = {};
83572
+ if (dark) span.v.dark = dark;
83573
+ if (light) span.v.light = light;
83574
+ }
83575
+ return span;
83576
+ }
83577
+ function renderTokenLines(tokens) {
83578
+ return tokens.map((lineTokens) => ({
83579
+ spans: lineTokens.map((token2) => toTokenSpan(token2))
83580
+ }));
83581
+ }
83582
+ function resetIncrementalHighlightState(blockId) {
83583
+ if (blockId) {
83584
+ incrementalHighlightStates.delete(blockId);
83585
+ return;
83586
+ }
83587
+ incrementalHighlightStates.clear();
83588
+ }
83589
+ function getIncrementalHighlightState(blockId, lang236) {
83590
+ const existing = incrementalHighlightStates.get(blockId);
83591
+ if (!existing || existing.lang !== lang236) {
83592
+ const fresh = {
83593
+ lang: lang236,
83594
+ tokenLang: void 0,
83595
+ processedLength: 0,
83596
+ pendingLine: "",
83597
+ highlightedLines: [],
83598
+ tokenLines: [],
83599
+ diffKind: [],
83600
+ oldNo: [],
83601
+ newNo: [],
83602
+ diffCursor: void 0,
83603
+ diffGrammar: void 0,
83604
+ grammarState: void 0
83605
+ };
83606
+ incrementalHighlightStates.set(blockId, fresh);
83607
+ return fresh;
83608
+ }
83609
+ return existing;
83610
+ }
83611
+ async function resolveHighlightLanguage(requestedLanguage) {
83612
+ if (!highlighter) return "text";
83613
+ const loadedLangs = highlighter.getLoadedLanguages();
83614
+ if (!loadedLangs.includes(requestedLanguage)) {
83615
+ try {
83616
+ await highlighter.loadLanguage(requestedLanguage);
83617
+ } catch (loadError) {
83618
+ console.warn(`Failed to load language ${requestedLanguage}, falling back to text:`, loadError);
83619
+ }
83620
+ }
83621
+ const nextLangs = highlighter.getLoadedLanguages();
83622
+ return nextLangs.includes(requestedLanguage) ? requestedLanguage : "text";
83623
+ }
83624
+ function makeLazySignature(codeBody, lang236, tokenLang, diffEnabled) {
83625
+ const head2 = codeBody.slice(0, 32);
83626
+ const tail = codeBody.slice(Math.max(0, codeBody.length - 32));
83627
+ return `${lang236}|${tokenLang}|${diffEnabled ? "diff" : "plain"}|${codeBody.length}|${head2}|${tail}`;
83628
+ }
83629
+ function getOrInitLazyState(blockId, signature, lineCount, lang236, tokenLang, diffEnabled) {
83630
+ const existing = lazyTokenizationStates.get(blockId);
83631
+ if (existing && existing.signature === signature && existing.highlightedLines.length === lineCount) {
83632
+ return existing;
83633
+ }
83634
+ const fresh = {
83635
+ signature,
83636
+ lang: lang236,
83637
+ tokenLang,
83638
+ processedLines: 0,
83639
+ highlightedLines: new Array(lineCount).fill(null),
83640
+ tokenLines: new Array(lineCount).fill(null),
83641
+ diffKind: new Array(lineCount).fill(null),
83642
+ oldNo: new Array(lineCount).fill(null),
83643
+ newNo: new Array(lineCount).fill(null),
83644
+ diffCursor: diffEnabled ? { oldLine: null, newLine: null } : void 0,
83645
+ diffGrammar: diffEnabled ? {} : void 0,
83646
+ grammarState: void 0
83647
+ };
83648
+ lazyTokenizationStates.set(blockId, fresh);
83649
+ return fresh;
83650
+ }
83651
+ function shouldLazyTokenizeBlock(lineCount, hasHighlighter, hasHighlightableContent) {
83652
+ if (!lazyTokenizationEnabled) return false;
83653
+ if (!hasHighlighter || !hasHighlightableContent) return false;
83654
+ return lineCount >= lazyTokenizationThresholdLines;
83655
+ }
83656
+ function pruneLazyTokenizationStates(nextBlocks) {
83657
+ if (lazyTokenizationStates.size === 0) return;
83658
+ const ids = new Set(nextBlocks.map((block) => block.id));
83659
+ for (const key2 of lazyTokenizationStates.keys()) {
83660
+ if (!ids.has(key2)) {
83661
+ lazyTokenizationStates.delete(key2);
83662
+ }
83663
+ }
83664
+ }
83665
+ function enqueueLazyTokenization(request) {
83666
+ if (!lazyTokenizationEnabled) return;
83667
+ const existing = lazyTokenizationQueue.get(request.blockId);
83668
+ const next2 = existing ? mergeLazyRequests(existing, request) : request;
83669
+ lazyTokenizationQueue.set(request.blockId, next2);
83670
+ if (!lazyTokenizationScheduled) {
83671
+ lazyTokenizationScheduled = true;
83672
+ setTimeout(() => {
83673
+ lazyTokenizationScheduled = false;
83674
+ void processLazyTokenizationQueue();
83675
+ }, 0);
83676
+ }
83677
+ }
83678
+ function selectNextLazyRequest() {
83679
+ let selected = null;
83680
+ for (const request of lazyTokenizationQueue.values()) {
83681
+ if (!selected) {
83682
+ selected = request;
83683
+ continue;
83684
+ }
83685
+ const priorityDiff = compareLazyPriority(request.priority, selected.priority);
83686
+ if (priorityDiff > 0) {
83687
+ selected = request;
83688
+ continue;
83689
+ }
83690
+ if (priorityDiff === 0 && request.requestedAt < selected.requestedAt) {
83691
+ selected = request;
83692
+ }
83693
+ }
83694
+ return selected;
83695
+ }
83696
+ async function processLazyTokenizationQueue() {
83697
+ if (lazyTokenizationProcessing) return;
83698
+ lazyTokenizationProcessing = true;
83699
+ try {
83700
+ while (lazyTokenizationQueue.size > 0) {
83701
+ const next2 = selectNextLazyRequest();
83702
+ if (!next2) break;
83703
+ lazyTokenizationQueue.delete(next2.blockId);
83704
+ await handleLazyTokenizationRequest(next2);
83705
+ }
83706
+ } finally {
83707
+ lazyTokenizationProcessing = false;
83708
+ }
83709
+ }
83710
+ async function handleLazyTokenizationRequest(request) {
83711
+ if (!lazyTokenizationEnabled || !highlighter) return;
83712
+ const index2 = blocks.findIndex((block2) => block2.id === request.blockId);
83713
+ if (index2 === -1) return;
83714
+ const block = blocks[index2];
83715
+ if (block.type !== "code" || !block.isFinalized) return;
83716
+ const raw2 = block.payload.raw ?? "";
83717
+ const { code: code4, info, hadFence } = stripCodeFence(raw2);
83718
+ const { lang: lang236, meta: meta2 } = parseCodeFenceInfo(info);
83719
+ const codeBody = hadFence ? code4 : dedentIndentedCode(raw2);
83720
+ const codeLines = extractCodeLines(raw2);
83721
+ let diffInfo = detectDiffLanguage(lang236, meta2);
83722
+ if (!diffInfo.isDiff && emitDiffBlocks && looksLikeUnifiedDiff(codeLines)) {
83723
+ diffInfo = {
83724
+ isDiff: true,
83725
+ diffLang: "diff",
83726
+ baseLang: guessLanguageFromDiffLines(codeLines)
83727
+ };
83728
+ }
83729
+ const requestedLanguage = diffInfo.isDiff ? diffInfo.diffLang : lang236 || "text";
83730
+ const tokenLanguage = diffInfo.isDiff ? diffInfo.baseLang ?? "text" : requestedLanguage;
83731
+ const hasHighlightableContent = codeBody.trim().length > 0;
83732
+ if (!shouldLazyTokenizeBlock(codeLines.length, Boolean(highlighter), hasHighlightableContent)) {
83733
+ return;
83734
+ }
83735
+ const wantsHtml = highlightOutputMode === "html" || highlightOutputMode === "both";
83736
+ const wantsTokens = (highlightOutputMode === "tokens" || highlightOutputMode === "both") && emitHighlightTokens;
83737
+ const diffEnabled = diffInfo.isDiff && wantsTokens;
83738
+ if (!wantsHtml && !wantsTokens) return;
83739
+ const { startLine, endLine } = clampLazyRange(request.startLine, request.endLine, codeLines.length);
83740
+ if (endLine <= startLine) return;
83741
+ let resolvedLanguage = requestedLanguage;
83742
+ let resolvedTokenLanguage = tokenLanguage;
83743
+ if (wantsHtml) {
83744
+ resolvedLanguage = await resolveHighlightLanguage(requestedLanguage);
83745
+ }
83746
+ if (wantsTokens) {
83747
+ resolvedTokenLanguage = await resolveHighlightLanguage(tokenLanguage);
83748
+ }
83749
+ const signature = makeLazySignature(codeBody, resolvedLanguage, resolvedTokenLanguage, diffEnabled);
83750
+ const state = getOrInitLazyState(block.id, signature, codeLines.length, resolvedLanguage, resolvedTokenLanguage, diffEnabled);
83751
+ if (state.processedLines < 0 || state.processedLines > codeLines.length) {
83752
+ state.processedLines = 0;
83753
+ }
83754
+ const targetEnd = Math.min(endLine, codeLines.length);
83755
+ if (targetEnd <= state.processedLines) {
83756
+ return;
83757
+ }
83758
+ const metricsCollector = new WorkerMetricsCollector(workerGrammarEngine);
83759
+ setActiveMetricsCollector(metricsCollector);
83760
+ metricsCollector.setBlocksProduced(blocks.length);
83761
+ const prevSnapshot = await blockToNodeSnapshot(block);
83762
+ const tokenizationStart = now();
83763
+ const segmentLines = codeLines.slice(state.processedLines, targetEnd);
83764
+ if (segmentLines.length > 0) {
83765
+ if (wantsHtml || wantsTokens && !diffEnabled) {
83766
+ try {
83767
+ const sharedLanguage = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
83768
+ const tokens = highlighter.codeToTokensWithThemes(segmentLines.join("\n"), {
83769
+ lang: sharedLanguage,
83770
+ themes: CODE_HIGHLIGHT_THEMES,
83771
+ grammarState: state.grammarState
83772
+ });
83773
+ if (wantsHtml) {
83774
+ const htmlLines = renderShikiLines(tokens);
83775
+ for (let i = 0; i < htmlLines.length; i += 1) {
83776
+ state.highlightedLines[state.processedLines + i] = htmlLines[i] ?? null;
83777
+ }
83778
+ }
83779
+ if (wantsTokens && !diffEnabled) {
83780
+ const tokenLines = renderTokenLines(tokens);
83781
+ for (let i = 0; i < tokenLines.length; i += 1) {
83782
+ state.tokenLines[state.processedLines + i] = tokenLines[i] ?? null;
83783
+ }
83784
+ }
83785
+ state.grammarState = highlighter.getLastGrammarState(tokens);
83786
+ } catch (error) {
83787
+ console.warn("Lazy tokenization failed for", requestedLanguage, error);
83788
+ if (wantsHtml) {
83789
+ for (let i = 0; i < segmentLines.length; i += 1) {
83790
+ state.highlightedLines[state.processedLines + i] = null;
83791
+ }
83792
+ }
83793
+ if (wantsTokens && !diffEnabled) {
83794
+ for (let i = 0; i < segmentLines.length; i += 1) {
83795
+ state.tokenLines[state.processedLines + i] = null;
83796
+ }
83797
+ }
83798
+ }
83799
+ }
83800
+ if (wantsTokens && diffEnabled) {
83801
+ const cursor = state.diffCursor ?? { oldLine: null, newLine: null };
83802
+ const diffLines = segmentLines.map((line) => parseUnifiedDiffLine(line, cursor));
83803
+ for (let i = 0; i < diffLines.length; i += 1) {
83804
+ const line = diffLines[i];
83805
+ const idx = state.processedLines + i;
83806
+ state.diffKind[idx] = line.kind;
83807
+ state.oldNo[idx] = line.oldNo ?? null;
83808
+ state.newNo[idx] = line.newNo ?? null;
83809
+ }
83810
+ try {
83811
+ const { tokenLines, grammarState } = buildDiffTokenLines(diffLines, resolvedTokenLanguage, state.diffGrammar ?? {});
83812
+ for (let i = 0; i < tokenLines.length; i += 1) {
83813
+ state.tokenLines[state.processedLines + i] = tokenLines[i] ?? null;
83814
+ }
83815
+ state.diffGrammar = grammarState;
83816
+ } catch (error) {
83817
+ console.warn("Lazy diff tokenization failed for", tokenLanguage, error);
83818
+ for (let i = 0; i < diffLines.length; i += 1) {
83819
+ const idx = state.processedLines + i;
83820
+ const line = diffLines[i];
83821
+ state.tokenLines[idx] = line.text.length > 0 ? { spans: [{ t: line.text }] } : { spans: [] };
83822
+ }
83823
+ }
83824
+ state.diffCursor = cursor;
83825
+ }
83826
+ }
83827
+ state.processedLines = targetEnd;
83828
+ const tokenizationDuration = now() - tokenizationStart;
83829
+ metricsCollector.recordShiki(tokenizationDuration);
83830
+ metricsCollector.recordHighlightForLanguage(resolvedLanguage, tokenizationDuration);
83831
+ metricsCollector.recordLazyTokenization(
83832
+ lazyRequestRangeSize({ ...request, startLine, endLine }),
83833
+ now() - request.requestedAt,
83834
+ lazyTokenizationQueue.size
83835
+ );
83836
+ const updated = cloneBlock(block);
83837
+ updated.payload.highlightedHtml = void 0;
83838
+ const effectiveLang = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
83839
+ const nextMeta = { ...updated.payload.meta ?? {}, ...meta2, lang: effectiveLang };
83840
+ nextMeta.lazyTokenization = true;
83841
+ nextMeta.lazyTokenizedUntil = state.processedLines;
83842
+ if (wantsHtml) {
83843
+ nextMeta.highlightedLines = state.highlightedLines;
83844
+ } else if ("highlightedLines" in nextMeta) {
83845
+ delete nextMeta.highlightedLines;
83846
+ }
83847
+ if (wantsTokens) {
83848
+ nextMeta.tokenLines = state.tokenLines;
83849
+ if (diffEnabled) {
83850
+ nextMeta.diffKind = state.diffKind;
83851
+ nextMeta.oldNo = state.oldNo;
83852
+ nextMeta.newNo = state.newNo;
83853
+ } else {
83854
+ if ("diffKind" in nextMeta) delete nextMeta.diffKind;
83855
+ if ("oldNo" in nextMeta) delete nextMeta.oldNo;
83856
+ if ("newNo" in nextMeta) delete nextMeta.newNo;
83857
+ }
83858
+ } else if ("tokenLines" in nextMeta) {
83859
+ delete nextMeta.tokenLines;
83860
+ if ("diffKind" in nextMeta) delete nextMeta.diffKind;
83861
+ if ("oldNo" in nextMeta) delete nextMeta.oldNo;
83862
+ if ("newNo" in nextMeta) delete nextMeta.newNo;
83863
+ }
83864
+ if (emitDiffBlocks && diffInfo.isDiff) {
83865
+ const cursor = { oldLine: null, newLine: null };
83866
+ const diffLines = codeLines.map((line) => parseUnifiedDiffLine(line, cursor));
83867
+ nextMeta.diffBlocks = buildDiffBlocksFromLines(diffLines, codeLines, wantsTokens ? state.tokenLines : null, diffInfo.baseLang ?? null);
83868
+ } else if ("diffBlocks" in nextMeta) {
83869
+ delete nextMeta.diffBlocks;
83870
+ }
83871
+ updated.payload.meta = nextMeta;
83872
+ blocks[index2] = updated;
83873
+ const nextSnapshot = await blockToNodeSnapshot(updated);
83874
+ const patches = [];
83875
+ diffNodeSnapshot(updated.id, prevSnapshot, nextSnapshot, patches, metricsCollector);
83876
+ if (patches.length > 0) {
83877
+ dispatchPatchBatch(patches, metricsCollector);
83878
+ } else {
83879
+ emitMetricsSample(metricsCollector);
83880
+ if (getActiveMetricsCollector() === metricsCollector) {
83881
+ setActiveMetricsCollector(null);
83882
+ }
83883
+ }
83884
+ }
82841
83885
  async function enrichCodeBlock(block) {
82842
83886
  performanceTimer.mark("highlight-code");
82843
83887
  const metrics = getActiveMetricsCollector();
82844
83888
  const raw2 = block.payload.raw ?? "";
82845
83889
  const { code: code4, info, hadFence } = stripCodeFence(raw2);
82846
83890
  const { lang: lang236, meta: meta2 } = parseCodeFenceInfo(info);
82847
- const requestedLanguage = lang236 || "text";
83891
+ let diffInfo = detectDiffLanguage(lang236, meta2);
82848
83892
  const codeBody = hadFence ? code4 : dedentIndentedCode(raw2);
83893
+ const codeLines = extractCodeLines(raw2);
83894
+ if (!diffInfo.isDiff && emitDiffBlocks && looksLikeUnifiedDiff(codeLines)) {
83895
+ diffInfo = {
83896
+ isDiff: true,
83897
+ diffLang: "diff",
83898
+ baseLang: guessLanguageFromDiffLines(codeLines)
83899
+ };
83900
+ }
83901
+ const requestedLanguage = diffInfo.isDiff ? diffInfo.diffLang : lang236 || "text";
83902
+ const tokenLanguage = diffInfo.isDiff ? diffInfo.baseLang ?? "text" : requestedLanguage;
83903
+ const baseMeta = block.payload.meta ?? {};
82849
83904
  let resolvedLanguage = requestedLanguage;
82850
- let cachedHighlight = getHighlightCacheEntry(requestedLanguage, codeBody);
82851
- if (!block.isFinalized && !enableLiveCodeHighlighting) {
83905
+ let resolvedTokenLanguage = tokenLanguage;
83906
+ const hasHighlighter = Boolean(highlighter);
83907
+ const hasHighlightableContent = codeBody.trim().length > 0;
83908
+ const wantsHtml = highlightOutputMode === "html" || highlightOutputMode === "both";
83909
+ const wantsTokens = (highlightOutputMode === "tokens" || highlightOutputMode === "both") && emitHighlightTokens;
83910
+ const wantsTokensNow = wantsTokens && (block.isFinalized || liveTokenizationEnabled);
83911
+ if (!block.isFinalized) {
83912
+ if (codeHighlightingMode === "final" || !hasHighlighter || !hasHighlightableContent) {
83913
+ resetIncrementalHighlightState(block.id);
83914
+ block.payload.highlightedHtml = void 0;
83915
+ const nextMeta2 = { ...baseMeta, ...meta2, lang: resolvedLanguage };
83916
+ if ("highlightedLines" in nextMeta2) {
83917
+ delete nextMeta2.highlightedLines;
83918
+ }
83919
+ if ("tokenLines" in nextMeta2) {
83920
+ delete nextMeta2.tokenLines;
83921
+ }
83922
+ if ("diffKind" in nextMeta2) {
83923
+ delete nextMeta2.diffKind;
83924
+ }
83925
+ if ("oldNo" in nextMeta2) {
83926
+ delete nextMeta2.oldNo;
83927
+ }
83928
+ if ("newNo" in nextMeta2) {
83929
+ delete nextMeta2.newNo;
83930
+ }
83931
+ if ("diffBlocks" in nextMeta2) {
83932
+ delete nextMeta2.diffBlocks;
83933
+ }
83934
+ block.payload.meta = nextMeta2;
83935
+ return;
83936
+ }
83937
+ if (codeHighlightingMode === "incremental") {
83938
+ if (hasHighlighter) {
83939
+ if (wantsHtml) {
83940
+ resolvedLanguage = await resolveHighlightLanguage(requestedLanguage);
83941
+ }
83942
+ if (wantsTokens) {
83943
+ resolvedTokenLanguage = await resolveHighlightLanguage(tokenLanguage);
83944
+ }
83945
+ }
83946
+ let state = getIncrementalHighlightState(block.id, resolvedLanguage);
83947
+ if (wantsTokens && state.tokenLang && state.tokenLang !== resolvedTokenLanguage) {
83948
+ resetIncrementalHighlightState(block.id);
83949
+ state = getIncrementalHighlightState(block.id, resolvedLanguage);
83950
+ }
83951
+ if (codeBody.length < state.processedLength) {
83952
+ resetIncrementalHighlightState(block.id);
83953
+ state = getIncrementalHighlightState(block.id, resolvedLanguage);
83954
+ }
83955
+ state.tokenLang = wantsTokens ? resolvedTokenLanguage : void 0;
83956
+ const appended = codeBody.slice(state.processedLength);
83957
+ const combined = state.pendingLine + appended;
83958
+ const diffEnabled = diffInfo.isDiff && wantsTokensNow;
83959
+ if (combined.length > 0) {
83960
+ const parts = combined.split("\n");
83961
+ const completeLines = parts.slice(0, -1);
83962
+ const tail = parts.length > 0 ? parts[parts.length - 1] ?? "" : "";
83963
+ if (completeLines.length > 0) {
83964
+ if (wantsHtml || wantsTokensNow && !diffEnabled) {
83965
+ try {
83966
+ const sharedLanguage = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
83967
+ const tokens = highlighter?.codeToTokensWithThemes(completeLines.join("\n"), {
83968
+ lang: sharedLanguage,
83969
+ themes: CODE_HIGHLIGHT_THEMES,
83970
+ grammarState: state.grammarState
83971
+ });
83972
+ if (wantsHtml) {
83973
+ const htmlLines = renderShikiLines(tokens);
83974
+ state.highlightedLines.push(...htmlLines);
83975
+ }
83976
+ if (wantsTokensNow && !diffEnabled) {
83977
+ const tokenLines2 = renderTokenLines(tokens);
83978
+ state.tokenLines.push(...tokenLines2);
83979
+ }
83980
+ state.grammarState = highlighter?.getLastGrammarState(tokens);
83981
+ } catch (error) {
83982
+ console.warn("Incremental highlighting failed for", requestedLanguage, error);
83983
+ if (wantsHtml) {
83984
+ state.highlightedLines.push(...completeLines.map(() => null));
83985
+ }
83986
+ if (wantsTokensNow && !diffEnabled) {
83987
+ state.tokenLines.push(...completeLines.map(() => null));
83988
+ }
83989
+ }
83990
+ }
83991
+ if (wantsTokensNow && diffEnabled) {
83992
+ const cursor = state.diffCursor ?? { oldLine: null, newLine: null };
83993
+ const diffLines = completeLines.map((line) => parseUnifiedDiffLine(line, cursor));
83994
+ state.diffCursor = cursor;
83995
+ state.diffKind.push(...diffLines.map((line) => line.kind));
83996
+ state.oldNo.push(...diffLines.map((line) => line.oldNo ?? null));
83997
+ state.newNo.push(...diffLines.map((line) => line.newNo ?? null));
83998
+ try {
83999
+ const { tokenLines: tokenLines2, grammarState } = buildDiffTokenLines(diffLines, resolvedTokenLanguage, state.diffGrammar ?? {});
84000
+ state.tokenLines.push(...tokenLines2);
84001
+ state.diffGrammar = grammarState;
84002
+ } catch (error) {
84003
+ console.warn("Incremental diff tokenization failed for", tokenLanguage, error);
84004
+ state.tokenLines.push(
84005
+ ...diffLines.map((line) => line.text.length > 0 ? { spans: [{ t: line.text }] } : { spans: [] })
84006
+ );
84007
+ }
84008
+ }
84009
+ }
84010
+ state.pendingLine = tail ?? "";
84011
+ }
84012
+ state.processedLength = codeBody.length;
84013
+ state.lang = resolvedLanguage;
84014
+ block.payload.highlightedHtml = void 0;
84015
+ const effectiveLang2 = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
84016
+ const nextMeta2 = { ...baseMeta, ...meta2, lang: effectiveLang2 };
84017
+ if (wantsHtml) {
84018
+ nextMeta2.highlightedLines = state.highlightedLines;
84019
+ } else if ("highlightedLines" in nextMeta2) {
84020
+ delete nextMeta2.highlightedLines;
84021
+ }
84022
+ if (wantsTokensNow) {
84023
+ nextMeta2.tokenLines = state.tokenLines;
84024
+ if (diffEnabled) {
84025
+ nextMeta2.diffKind = state.diffKind;
84026
+ nextMeta2.oldNo = state.oldNo;
84027
+ nextMeta2.newNo = state.newNo;
84028
+ } else {
84029
+ if ("diffKind" in nextMeta2) delete nextMeta2.diffKind;
84030
+ if ("oldNo" in nextMeta2) delete nextMeta2.oldNo;
84031
+ if ("newNo" in nextMeta2) delete nextMeta2.newNo;
84032
+ }
84033
+ } else if ("tokenLines" in nextMeta2) {
84034
+ delete nextMeta2.tokenLines;
84035
+ if ("diffKind" in nextMeta2) delete nextMeta2.diffKind;
84036
+ if ("oldNo" in nextMeta2) delete nextMeta2.oldNo;
84037
+ if ("newNo" in nextMeta2) delete nextMeta2.newNo;
84038
+ }
84039
+ if (emitDiffBlocks && diffInfo.isDiff && liveTokenizationEnabled) {
84040
+ const cursor = { oldLine: null, newLine: null };
84041
+ const diffLines = codeLines.map((line) => parseUnifiedDiffLine(line, cursor));
84042
+ nextMeta2.diffBlocks = buildDiffBlocksFromLines(diffLines, codeLines, wantsTokensNow ? state.tokenLines : null, diffInfo.baseLang ?? null);
84043
+ } else if ("diffBlocks" in nextMeta2) {
84044
+ delete nextMeta2.diffBlocks;
84045
+ }
84046
+ block.payload.meta = nextMeta2;
84047
+ const highlightDuration2 = performanceTimer.measure("highlight-code");
84048
+ metrics?.recordShiki(highlightDuration2);
84049
+ metrics?.recordHighlightForLanguage(resolvedLanguage, highlightDuration2);
84050
+ return;
84051
+ }
84052
+ }
84053
+ resetIncrementalHighlightState(block.id);
84054
+ if (block.isFinalized && shouldLazyTokenizeBlock(codeLines.length, hasHighlighter, hasHighlightableContent) && (wantsHtml || wantsTokens)) {
84055
+ if (hasHighlighter) {
84056
+ if (wantsHtml) {
84057
+ resolvedLanguage = await resolveHighlightLanguage(requestedLanguage);
84058
+ }
84059
+ if (wantsTokens) {
84060
+ resolvedTokenLanguage = await resolveHighlightLanguage(tokenLanguage);
84061
+ }
84062
+ }
84063
+ const diffEnabled = diffInfo.isDiff && wantsTokens;
84064
+ const signature = makeLazySignature(codeBody, resolvedLanguage, resolvedTokenLanguage, diffEnabled);
84065
+ const state = getOrInitLazyState(block.id, signature, codeLines.length, resolvedLanguage, resolvedTokenLanguage, diffEnabled);
84066
+ const effectiveLang2 = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
84067
+ const nextMeta2 = { ...baseMeta, ...meta2, lang: effectiveLang2 };
84068
+ nextMeta2.lazyTokenization = true;
84069
+ nextMeta2.lazyTokenizedUntil = state.processedLines;
84070
+ if (wantsHtml) {
84071
+ nextMeta2.highlightedLines = state.highlightedLines;
84072
+ } else if ("highlightedLines" in nextMeta2) {
84073
+ delete nextMeta2.highlightedLines;
84074
+ }
84075
+ if (wantsTokens) {
84076
+ nextMeta2.tokenLines = state.tokenLines;
84077
+ if (diffEnabled) {
84078
+ nextMeta2.diffKind = state.diffKind;
84079
+ nextMeta2.oldNo = state.oldNo;
84080
+ nextMeta2.newNo = state.newNo;
84081
+ } else {
84082
+ if ("diffKind" in nextMeta2) delete nextMeta2.diffKind;
84083
+ if ("oldNo" in nextMeta2) delete nextMeta2.oldNo;
84084
+ if ("newNo" in nextMeta2) delete nextMeta2.newNo;
84085
+ }
84086
+ } else if ("tokenLines" in nextMeta2) {
84087
+ delete nextMeta2.tokenLines;
84088
+ if ("diffKind" in nextMeta2) delete nextMeta2.diffKind;
84089
+ if ("oldNo" in nextMeta2) delete nextMeta2.oldNo;
84090
+ if ("newNo" in nextMeta2) delete nextMeta2.newNo;
84091
+ }
84092
+ if (emitDiffBlocks && diffInfo.isDiff) {
84093
+ const cursor = { oldLine: null, newLine: null };
84094
+ const diffLines = codeLines.map((line) => parseUnifiedDiffLine(line, cursor));
84095
+ nextMeta2.diffBlocks = buildDiffBlocksFromLines(diffLines, codeLines, wantsTokens ? state.tokenLines : null, diffInfo.baseLang ?? null);
84096
+ } else if ("diffBlocks" in nextMeta2) {
84097
+ delete nextMeta2.diffBlocks;
84098
+ }
82852
84099
  block.payload.highlightedHtml = void 0;
82853
- block.payload.meta = {
82854
- ...meta2,
82855
- lang: resolvedLanguage
82856
- };
84100
+ block.payload.meta = nextMeta2;
82857
84101
  return;
82858
84102
  }
82859
- if (!cachedHighlight && highlighter && codeBody.trim()) {
82860
- try {
82861
- const loadedLangs = highlighter.getLoadedLanguages();
82862
- if (!loadedLangs.includes(requestedLanguage)) {
84103
+ let tokenLines;
84104
+ let diffKind;
84105
+ let diffOldNo;
84106
+ let diffNewNo;
84107
+ if (wantsHtml) {
84108
+ let cachedHighlight = block.isFinalized ? getHighlightCacheEntry(requestedLanguage, codeBody) : null;
84109
+ if (!cachedHighlight && highlighter && hasHighlightableContent) {
84110
+ try {
84111
+ resolvedLanguage = await resolveHighlightLanguage(requestedLanguage);
84112
+ const highlighted = highlighter.codeToHtml(codeBody, {
84113
+ lang: resolvedLanguage,
84114
+ themes: CODE_HIGHLIGHT_THEMES,
84115
+ defaultColor: false
84116
+ });
84117
+ const enhanced = enhanceHighlightedHtml(highlighted, resolvedLanguage);
84118
+ block.payload.highlightedHtml = enhanced;
84119
+ if (block.isFinalized) {
84120
+ setHighlightCacheEntry(resolvedLanguage, codeBody, enhanced);
84121
+ if (resolvedLanguage !== requestedLanguage) {
84122
+ setHighlightCacheEntry(requestedLanguage, codeBody, enhanced);
84123
+ }
84124
+ }
84125
+ cachedHighlight = getHighlightCacheEntry(resolvedLanguage, codeBody);
84126
+ } catch (error) {
84127
+ console.warn("Highlighting failed for", requestedLanguage, error);
84128
+ resolvedLanguage = "text";
84129
+ }
84130
+ }
84131
+ if (cachedHighlight) {
84132
+ resolvedLanguage = cachedHighlight.lang;
84133
+ block.payload.highlightedHtml = cachedHighlight.html;
84134
+ }
84135
+ } else {
84136
+ block.payload.highlightedHtml = void 0;
84137
+ }
84138
+ if (wantsTokens) {
84139
+ if (diffInfo.isDiff) {
84140
+ if (hasHighlighter) {
84141
+ resolvedTokenLanguage = await resolveHighlightLanguage(tokenLanguage);
84142
+ }
84143
+ const diffLines = codeBody.length > 0 ? codeBody.split("\n") : [];
84144
+ const cursor = { oldLine: null, newLine: null };
84145
+ const diffInfoLines = diffLines.map((line) => parseUnifiedDiffLine(line, cursor));
84146
+ diffKind = diffInfoLines.map((line) => line.kind);
84147
+ diffOldNo = diffInfoLines.map((line) => line.oldNo ?? null);
84148
+ diffNewNo = diffInfoLines.map((line) => line.newNo ?? null);
84149
+ if (!hasHighlighter || !hasHighlightableContent) {
84150
+ tokenLines = diffInfoLines.map((line) => line.text.length > 0 ? { spans: [{ t: line.text }] } : { spans: [] });
84151
+ } else {
82863
84152
  try {
82864
- await highlighter.loadLanguage(requestedLanguage);
82865
- } catch (loadError) {
82866
- console.warn(`Failed to load language ${requestedLanguage}, falling back to text:`, loadError);
84153
+ const result = buildDiffTokenLines(diffInfoLines, resolvedTokenLanguage, {});
84154
+ tokenLines = result.tokenLines;
84155
+ } catch (error) {
84156
+ console.warn("Diff tokenization failed for", tokenLanguage, error);
84157
+ tokenLines = diffInfoLines.map((line) => line.text.length > 0 ? { spans: [{ t: line.text }] } : { spans: [] });
82867
84158
  }
82868
84159
  }
82869
- resolvedLanguage = loadedLangs.includes(requestedLanguage) ? requestedLanguage : "text";
82870
- const highlighted = highlighter.codeToHtml(codeBody, {
82871
- lang: resolvedLanguage,
82872
- themes: {
82873
- dark: "github-dark",
82874
- light: "github-light"
82875
- },
82876
- defaultColor: false
82877
- });
82878
- const enhanced = enhanceHighlightedHtml(highlighted, resolvedLanguage);
82879
- block.payload.highlightedHtml = enhanced;
82880
- if (block.isFinalized) {
82881
- setHighlightCacheEntry(resolvedLanguage, codeBody, enhanced);
82882
- if (resolvedLanguage !== requestedLanguage) {
82883
- setHighlightCacheEntry(requestedLanguage, codeBody, enhanced);
84160
+ } else {
84161
+ const lineCount = codeBody.length > 0 ? codeBody.split("\n").length : 0;
84162
+ if (!hasHighlighter || !hasHighlightableContent) {
84163
+ tokenLines = new Array(lineCount).fill(null);
84164
+ } else {
84165
+ try {
84166
+ resolvedTokenLanguage = await resolveHighlightLanguage(tokenLanguage);
84167
+ const tokens = highlighter?.codeToTokensWithThemes(codeBody, {
84168
+ lang: resolvedTokenLanguage,
84169
+ themes: CODE_HIGHLIGHT_THEMES
84170
+ });
84171
+ tokenLines = renderTokenLines(tokens);
84172
+ } catch (error) {
84173
+ console.warn("Tokenization failed for", requestedLanguage, error);
84174
+ tokenLines = new Array(lineCount).fill(null);
82884
84175
  }
82885
84176
  }
82886
- cachedHighlight = getHighlightCacheEntry(resolvedLanguage, codeBody);
82887
- } catch (error) {
82888
- console.warn("Highlighting failed for", requestedLanguage, error);
82889
- resolvedLanguage = "text";
82890
84177
  }
82891
84178
  }
82892
- if (cachedHighlight) {
82893
- resolvedLanguage = cachedHighlight.lang;
82894
- block.payload.highlightedHtml = cachedHighlight.html;
84179
+ const effectiveLang = wantsHtml ? resolvedLanguage : resolvedTokenLanguage;
84180
+ const nextMeta = { ...baseMeta, ...meta2, lang: effectiveLang };
84181
+ if ("highlightedLines" in nextMeta) {
84182
+ delete nextMeta.highlightedLines;
82895
84183
  }
82896
- block.payload.meta = {
82897
- ...meta2,
82898
- lang: resolvedLanguage
82899
- };
84184
+ if (wantsTokens) {
84185
+ nextMeta.tokenLines = tokenLines ?? [];
84186
+ if (diffKind) {
84187
+ nextMeta.diffKind = diffKind;
84188
+ nextMeta.oldNo = diffOldNo ?? [];
84189
+ nextMeta.newNo = diffNewNo ?? [];
84190
+ } else {
84191
+ if ("diffKind" in nextMeta) delete nextMeta.diffKind;
84192
+ if ("oldNo" in nextMeta) delete nextMeta.oldNo;
84193
+ if ("newNo" in nextMeta) delete nextMeta.newNo;
84194
+ }
84195
+ } else if ("tokenLines" in nextMeta) {
84196
+ delete nextMeta.tokenLines;
84197
+ if ("diffKind" in nextMeta) delete nextMeta.diffKind;
84198
+ if ("oldNo" in nextMeta) delete nextMeta.oldNo;
84199
+ if ("newNo" in nextMeta) delete nextMeta.newNo;
84200
+ }
84201
+ if (emitDiffBlocks && diffInfo.isDiff) {
84202
+ const cursor = { oldLine: null, newLine: null };
84203
+ const diffLines = codeLines.map((line) => parseUnifiedDiffLine(line, cursor));
84204
+ nextMeta.diffBlocks = buildDiffBlocksFromLines(diffLines, codeLines, wantsTokens ? tokenLines ?? null : null, diffInfo.baseLang ?? null);
84205
+ } else if ("diffBlocks" in nextMeta) {
84206
+ delete nextMeta.diffBlocks;
84207
+ }
84208
+ block.payload.meta = nextMeta;
82900
84209
  const highlightDuration = performanceTimer.measure("highlight-code");
82901
84210
  metrics?.recordShiki(highlightDuration);
82902
84211
  metrics?.recordHighlightForLanguage(resolvedLanguage, highlightDuration);
@@ -83149,7 +84458,12 @@ function enrichListBlock(block) {
83149
84458
  }
83150
84459
  const items = itemsRaw.map((raw2) => inlineParser.parse(raw2));
83151
84460
  const isOrdered = /^\d+\./.test(lines[0]?.trimStart() || "");
83152
- block.payload.meta = { ordered: isOrdered, items };
84461
+ block.payload.meta = {
84462
+ ordered: isOrdered,
84463
+ items,
84464
+ formatAnticipation: block.isFinalized ? void 0 : formatAnticipationConfig,
84465
+ mathEnabled: enableMath
84466
+ };
83153
84467
  }
83154
84468
  function runDocumentPlugins(inputBlocks, content4) {
83155
84469
  const blocks2 = inputBlocks.slice();
@@ -83492,6 +84806,10 @@ function diffNodeSnapshot(blockId, prevNode, nextNode, patches, metrics) {
83492
84806
  if (onlyAppend && nextChildren.length > prevChildren.length) {
83493
84807
  const startIndex = prevChildren.length;
83494
84808
  const appended = nextChildren.slice(startIndex);
84809
+ const hasTokenLines = appended.some((child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "tokens"));
84810
+ const hasDiffKind = appended.some((child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "diffKind"));
84811
+ const hasOldNo = appended.some((child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "oldNo"));
84812
+ const hasNewNo = appended.some((child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "newNo"));
83495
84813
  patches.push({
83496
84814
  op: "appendLines",
83497
84815
  at: { blockId, nodeId: prevNode.id },
@@ -83500,7 +84818,27 @@ function diffNodeSnapshot(blockId, prevNode, nextNode, patches, metrics) {
83500
84818
  const text12 = typeof child.props?.text === "string" ? child.props?.text : "";
83501
84819
  return text12;
83502
84820
  }),
83503
- highlight: appended.map((child) => typeof child.props?.html === "string" ? child.props?.html : null)
84821
+ highlight: appended.map((child) => typeof child.props?.html === "string" ? child.props?.html : null),
84822
+ ...hasTokenLines ? {
84823
+ tokens: appended.map(
84824
+ (child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "tokens") ? child.props?.tokens : null
84825
+ )
84826
+ } : {},
84827
+ ...hasDiffKind ? {
84828
+ diffKind: appended.map(
84829
+ (child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "diffKind") ? child.props?.diffKind : null
84830
+ )
84831
+ } : {},
84832
+ ...hasOldNo ? {
84833
+ oldNo: appended.map(
84834
+ (child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "oldNo") ? child.props?.oldNo : null
84835
+ )
84836
+ } : {},
84837
+ ...hasNewNo ? {
84838
+ newNo: appended.map(
84839
+ (child) => Object.prototype.hasOwnProperty.call(child.props ?? {}, "newNo") ? child.props?.newNo : null
84840
+ )
84841
+ } : {}
83504
84842
  });
83505
84843
  metrics?.recordAppendLines(appended.length);
83506
84844
  return;
@@ -84019,6 +85357,17 @@ async function processWorkerMessage(msg) {
84019
85357
  });
84020
85358
  return;
84021
85359
  }
85360
+ case "TOKENIZE_RANGE": {
85361
+ const priority = msg.priority === "prefetch" ? "prefetch" : "visible";
85362
+ enqueueLazyTokenization({
85363
+ blockId: msg.blockId,
85364
+ startLine: msg.startLine,
85365
+ endLine: msg.endLine,
85366
+ priority,
85367
+ requestedAt: now()
85368
+ });
85369
+ return;
85370
+ }
84022
85371
  case "MDX_COMPILED":
84023
85372
  handleMdxStatus(msg.blockId, {
84024
85373
  compiledRef: { id: msg.compiledId },