@simon_he/vue-tui 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/markdown.cjs CHANGED
@@ -1279,7 +1279,7 @@ function loadBuiltinMathRasterizer() {
1279
1279
  })()), builtinRasterizerLoad;
1280
1280
  }
1281
1281
 
1282
- // node_modules/.pnpm/stream-markdown-parser@1.1.9/node_modules/stream-markdown-parser/dist/index.js
1282
+ // node_modules/.pnpm/stream-markdown-parser@1.2.3/node_modules/stream-markdown-parser/dist/index.js
1283
1283
  var __create2 = Object.create, __defProp$1 = Object.defineProperty, __getOwnPropDesc2 = Object.getOwnPropertyDescriptor, __getOwnPropNames2 = Object.getOwnPropertyNames, __getProtoOf2 = Object.getPrototypeOf, __hasOwnProp2 = Object.prototype.hasOwnProperty, __commonJS = (cb, mod) => function() {
1284
1284
  return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
1285
1285
  }, __export$1 = (all) => {
@@ -11183,7 +11183,23 @@ function shouldDemoteFilenameLikeLinkify(linkText, context = {}) {
11183
11183
  let extension = String(extensionMatch[1] ?? "").toLowerCase();
11184
11184
  return isMarketTickerLikeText(linkText, extension, context.marketTicker === !0) ? !0 : FILENAMEISH_LINK_EXTENSIONS.has(extension) ? !AMBIGUOUS_BARE_DOMAIN_EXTENSIONS.has(extension) || context.filename ? !0 : hasStrongFilenameSignals(linkText) : !!(context.explicitFilename && EXPLICIT_FILENAME_CONTEXT_ONLY_EXTENSIONS.has(extension) || context.filename && FILENAME_CONTEXT_ONLY_EXTENSIONS.has(extension));
11185
11185
  }
11186
+ var syntheticLinkOrigins = /* @__PURE__ */ new WeakMap(), cacheStableLinkValidators = /* @__PURE__ */ new WeakSet();
11187
+ function setSyntheticLinkOrigin(token, origin) {
11188
+ return syntheticLinkOrigins.set(token, origin), token;
11189
+ }
11190
+ function readSyntheticLinkOrigin(token) {
11191
+ return syntheticLinkOrigins.get(token);
11192
+ }
11193
+ function registerCacheStableLinkValidator(validateLink$1) {
11194
+ cacheStableLinkValidators.add(validateLink$1);
11195
+ }
11196
+ function isCacheStableLinkValidator(validateLink$1) {
11197
+ return validateLink$1 === void 0 || cacheStableLinkValidators.has(validateLink$1);
11198
+ }
11186
11199
  var LINKIFY_HARD_STOP_CHARS = ["\uFF01"];
11200
+ function getSyntheticLinkOrigin(markup) {
11201
+ return markup === "linkify" || markup === "autolink" ? markup : "recovery";
11202
+ }
11187
11203
  function textToken(content) {
11188
11204
  return {
11189
11205
  type: "text",
@@ -11229,13 +11245,13 @@ function pushEmClose(arr, type) {
11229
11245
  nesting: -1
11230
11246
  }));
11231
11247
  }
11232
- function createLinkToken(text$1, href, loading) {
11248
+ function createLinkToken(text$1, href, loading, origin = "recovery") {
11233
11249
  let title = "";
11234
11250
  if (href.includes('"')) {
11235
11251
  let temps = href.split('"');
11236
11252
  href = temps[0].trim(), title = temps[1].trim();
11237
11253
  }
11238
- return {
11254
+ return setSyntheticLinkOrigin({
11239
11255
  type: "link",
11240
11256
  loading,
11241
11257
  href,
@@ -11247,7 +11263,7 @@ function createLinkToken(text$1, href, loading) {
11247
11263
  raw: text$1
11248
11264
  }],
11249
11265
  raw: `[${text$1}](${href})`
11250
- };
11266
+ }, origin);
11251
11267
  }
11252
11268
  function appendToLinkToken(link$1, suffix) {
11253
11269
  if (!(!link$1 || !suffix) && (link$1.href = String(link$1.href ?? "") + suffix, link$1.text = String(link$1.text ?? "") + suffix, link$1.raw = `[${link$1.text}](${link$1.href})`, Array.isArray(link$1.children) && link$1.children.length)) {
@@ -11411,13 +11427,13 @@ function fixLinkToken(tokens, raw) {
11411
11427
  } else if (curToken?.type === "text" && curToken.content?.endsWith("(") && tokens[i + 1]?.type === "link_open") {
11412
11428
  let match = curToken.content.match(/\[([^\]]+)\]/);
11413
11429
  if (match) {
11414
- let beforeText = curToken.content.slice(0, match.index), emphasisMatch = beforeText.match(/(\*+)$/), replacerTokens = [];
11430
+ let beforeText = curToken.content.slice(0, match.index), emphasisMatch = beforeText.match(/(\*+)$/), origin = getSyntheticLinkOrigin(tokens[i + 1]?.markup), replacerTokens = [];
11415
11431
  if (emphasisMatch) {
11416
11432
  beforeText = beforeText.slice(0, emphasisMatch.index), beforeText && replacerTokens.push(textToken(beforeText));
11417
11433
  let text$1 = match[1], type = emphasisMatch[1].length;
11418
11434
  pushEmOpen(replacerTokens, type);
11419
11435
  let href = tokens[i + 2]?.content || "";
11420
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"))), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
11436
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"), origin)), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
11421
11437
  let afterText = tokens[i + 4].content?.replace(/^\)\**/, "");
11422
11438
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
11423
11439
  } else
@@ -11429,7 +11445,7 @@ function fixLinkToken(tokens, raw) {
11429
11445
  let type = emphasisMatch$1[0].length;
11430
11446
  text$1 = text$1.replace(/^\*+/, "").replace(/\*+$/, "");
11431
11447
  let href$1 = tokens[i + 2]?.content || "";
11432
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href$1 += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), pushEmOpen(replacerTokens, type), replacerTokens.push(createLinkToken(text$1, href$1, !tokens[i + 4]?.content?.startsWith(")"))), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
11448
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href$1 += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), pushEmOpen(replacerTokens, type), replacerTokens.push(createLinkToken(text$1, href$1, !tokens[i + 4]?.content?.startsWith(")"), origin)), pushEmClose(replacerTokens, type), tokens[i + 4]?.type === "text") {
11433
11449
  let afterText = tokens[i + 4].content?.replace(/^\)/, "");
11434
11450
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
11435
11451
  } else
@@ -11438,7 +11454,7 @@ function fixLinkToken(tokens, raw) {
11438
11454
  continue;
11439
11455
  }
11440
11456
  let href = tokens[i + 2]?.content || "";
11441
- if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"))), tokens[i + 4]?.type === "text") {
11457
+ if (tokens[i + 4]?.type === "text" && !tokens[i + 4].content?.startsWith(")") && (href += tokens[i + 4]?.content || "", tokens[i + 4].content = ""), replacerTokens.push(createLinkToken(text$1, href, !tokens[i + 4]?.content?.startsWith(")"), origin)), tokens[i + 4]?.type === "text") {
11442
11458
  let afterText = tokens[i + 4].content?.replace(/^\)/, "");
11443
11459
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i, 5, ...replacerTokens);
11444
11460
  } else
@@ -11452,11 +11468,11 @@ function fixLinkToken(tokens, raw) {
11452
11468
  let replacerTokens = [], text$1 = tokens[i - 3].content || "", href = curToken.attrs?.find((attr) => attr[0] === "href")?.[1] || "";
11453
11469
  if (tokens[i + 3]?.type === "text") {
11454
11470
  let m = (tokens[i + 3]?.content ?? "").indexOf(")"), loading = m === -1;
11455
- m === -1 && (href += tokens[i + 3]?.content?.slice(0, m) || "", tokens[i + 3].content = ""), replacerTokens.push(createLinkToken(text$1, href, loading));
11471
+ m === -1 && (href += tokens[i + 3]?.content?.slice(0, m) || "", tokens[i + 3].content = ""), replacerTokens.push(createLinkToken(text$1, href, loading, "linkify"));
11456
11472
  let afterText = tokens[i + 3].content?.replace(/^\)\**/, "");
11457
11473
  afterText && replacerTokens.push(textToken(afterText)), tokens.splice(i - 4, 8, ...replacerTokens);
11458
11474
  } else
11459
- replacerTokens.push({
11475
+ replacerTokens.push(setSyntheticLinkOrigin({
11460
11476
  type: "link",
11461
11477
  loading: !0,
11462
11478
  href,
@@ -11468,7 +11484,7 @@ function fixLinkToken(tokens, raw) {
11468
11484
  raw: href
11469
11485
  }],
11470
11486
  raw: `[${text$1}](${href})`
11471
- }), tokens.splice(i - 4, 7, ...replacerTokens);
11487
+ }, "linkify")), tokens.splice(i - 4, 7, ...replacerTokens);
11472
11488
  continue;
11473
11489
  } else if (tokens[i - 1].content === "](" && tokens[i - 3]?.type === "text" && tokens[i - 3].content?.endsWith(")"))
11474
11490
  if (tokens[i - 2]?.type === "strong_open") {
@@ -11502,7 +11518,7 @@ function fixLinkToken(tokens, raw) {
11502
11518
  count += 1;
11503
11519
  }
11504
11520
  }
11505
- let linkToken = {
11521
+ let linkToken = setSyntheticLinkOrigin({
11506
11522
  type: "link",
11507
11523
  loading: !1,
11508
11524
  href,
@@ -11514,7 +11530,7 @@ function fixLinkToken(tokens, raw) {
11514
11530
  raw: text$1
11515
11531
  }],
11516
11532
  raw: `[${text$1}](${href})`
11517
- };
11533
+ }, curToken.markup ? getSyntheticLinkOrigin(curToken.markup) : "explicit");
11518
11534
  if (replacerTokens.push(linkToken), emphasisMatch) {
11519
11535
  let type = emphasisMatch[1].length;
11520
11536
  pushEmClose(replacerTokens, type);
@@ -13044,10 +13060,14 @@ function factory(opts = {}) {
13044
13060
  ...experimental
13045
13061
  }
13046
13062
  });
13047
- return hasCustomValidateLink || md.set({ validateLink: (url) => !isUnsafeHtmlUrl(url, {
13048
- tagName: "a",
13049
- attrName: "href"
13050
- }) }), applyInlineUrlValidation(md), applyLinkifyCandidateFilter(md), (opts.enableMath ?? !0) && applyMath(md, {
13063
+ if (!hasCustomValidateLink) {
13064
+ let validateLink$1 = (url) => !isUnsafeHtmlUrl(url, {
13065
+ tagName: "a",
13066
+ attrName: "href"
13067
+ });
13068
+ registerCacheStableLinkValidator(validateLink$1), md.set({ validateLink: validateLink$1 });
13069
+ }
13070
+ return applyInlineUrlValidation(md), applyLinkifyCandidateFilter(md), (opts.enableMath ?? !0) && applyMath(md, {
13051
13071
  ...getDefaultMathOptions() ?? {},
13052
13072
  ...opts.mathOptions ?? {}
13053
13073
  }), (opts.enableContainers ?? !0) && applyContainers(md), opts.enableFixIndentedCodeBlock !== !1 && applyFixIndentedCodeBlock(md), applyFixLinkTokens(md), applyFixStrongTokens(md), applyFixListItem(md), applyFixTableTokens(md), applyRenderRules(md), applyFixHtmlInlineTokens(md, { customHtmlTags: opts.customHtmlTags }), md;
@@ -13096,7 +13116,11 @@ function parseEmphasisToken(tokens, startIndex, options) {
13096
13116
  nextIndex: i < tokens.length ? i + 1 : tokens.length
13097
13117
  };
13098
13118
  }
13099
- var TRAILING_FENCE_LINE_RE = /\r?\n[ \t]*`+\s*$/, DIFF_HEADER_PREFIXES = [
13119
+ function TRAILING_OWN_FENCE_LINE_RE(marker, minLen) {
13120
+ return /* @__PURE__ */ new RegExp(`\r?
13121
+ [ \\t]*${marker}{${minLen},}[ \\t]*$`);
13122
+ }
13123
+ var DIFF_HEADER_PREFIXES = [
13100
13124
  "diff ",
13101
13125
  "index ",
13102
13126
  "--- ",
@@ -13149,7 +13173,11 @@ function parseFenceToken(token) {
13149
13173
  let s = info, sp = s.indexOf(" ");
13150
13174
  return sp === -1 ? "" : String(s.slice(sp + 1) ?? "");
13151
13175
  })() : info, content = String(token.content ?? "");
13152
- if (TRAILING_FENCE_LINE_RE.test(content) && (content = content.replace(TRAILING_FENCE_LINE_RE, "")), diff) {
13176
+ if (!closed && token.markup) {
13177
+ let marker = token.markup[0], minLen = token.markup.length, trailingFenceLineRe = TRAILING_OWN_FENCE_LINE_RE(marker, minLen);
13178
+ trailingFenceLineRe.test(content) && (content = content.replace(trailingFenceLineRe, ""));
13179
+ }
13180
+ if (diff) {
13153
13181
  let { original, updated } = splitUnifiedDiff(content, closed === !0);
13154
13182
  return {
13155
13183
  type: "code_block",
@@ -14442,11 +14470,11 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
14442
14470
  content
14443
14471
  });
14444
14472
  if (currentTextNode) {
14445
- currentTextNode.content += stripTrailingMidStateMarker(textNode.content, token, markerFlags), currentTextNode.raw += textNode.raw;
14473
+ currentTextNode.content += options?.final ? textNode.content : stripTrailingMidStateMarker(textNode.content, token, markerFlags), currentTextNode.raw += textNode.raw;
14446
14474
  return;
14447
14475
  }
14448
14476
  let maybeMath = preToken?.tag === "br" && tokens[i - 2]?.content === "[";
14449
- nextToken || (textNode.content = stripTrailingMidStateMarker(textNode.content, token, markerFlags)), currentTextNode = textNode, currentTextNode.center = maybeMath, result.push(currentTextNode);
14477
+ nextToken || (textNode.content = options?.final ? textNode.content : stripTrailingMidStateMarker(textNode.content, token, markerFlags)), currentTextNode = textNode, currentTextNode.center = maybeMath, result.push(currentTextNode);
14450
14478
  }
14451
14479
  function handleTextToken(token) {
14452
14480
  let rawContent = String(token.content ?? ""), rawMarkerFlags = getInlineTextMarkerFlags(rawContent), rawHasBackslash = (rawMarkerFlags & INLINE_TEXT_MARKER_BACKSLASH) !== 0, rawSource = tokens.length === 1 && rawHasBackslash && typeof raw == "string" ? String(raw) : "", content = rawSource ? decodeVisibleTextFromRaw(rawSource) : rawHasBackslash ? rawContent.replace(ESCAPED_PUNCTUATION_RE, "$1") : rawContent, markerFlags = content === rawContent ? rawMarkerFlags : getInlineTextMarkerFlags(content);
@@ -14469,7 +14497,7 @@ function parseInlineTokens(tokens, raw, pPreToken, options) {
14469
14497
  i++;
14470
14498
  return;
14471
14499
  }
14472
- if (!nextToken && markerFlags & INLINE_TEXT_MARKER_OPEN_PAREN && /[^\]]\s*\(\s*$/.test(content) && (content = content.replace(/\(\s*$/, "")), !content) {
14500
+ if (!nextToken && options?.final !== !0 && markerFlags & INLINE_TEXT_MARKER_OPEN_PAREN && /[^\]]\s*\(\s*$/.test(content) && (content = content.replace(/\(\s*$/, "")), !content) {
14473
14501
  i++;
14474
14502
  return;
14475
14503
  }
@@ -15807,16 +15835,23 @@ function recordInternalNodeSourceRange(node, token, options) {
15807
15835
  end: offsets[Math.max(0, Math.trunc(endLine))] ?? source.length
15808
15836
  });
15809
15837
  }
15810
- var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExplicitMathTailCache = /* @__PURE__ */ new WeakMap(), TOLERANT_BOUNDARY_SPLIT_OPENERS = ["$$", "\\["], STREAMING_ADMONITION_OPEN_RE = /(^|\r?\n)[\t ]*:::[\t ]*(?:warning|info|note|tip|danger|caution|error)(?=[\t ]|\r?\n|$)[^\r\n]*(?:\r?\n[\t ]*)*$/, structuredStreamCache = /* @__PURE__ */ new WeakMap(), topLevelStreamParseMode = /* @__PURE__ */ new WeakMap(), REUSABLE_INLINE_TOKEN_TYPES = /* @__PURE__ */ new Set([
15838
+ var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExplicitMathTailCache = /* @__PURE__ */ new WeakMap(), TOLERANT_BOUNDARY_SPLIT_OPENERS = ["$", "\\["], STREAMING_ADMONITION_OPEN_RE = /(^|\r?\n)[\t ]*:::[\t ]*(?:warning|info|note|tip|danger|caution|error)(?=[\t ]|\r?\n|$)[^\r\n]*(?:\r?\n[\t ]*)*$/, SAFE_MARKDOWN_WINDOW_MARGIN = 1024, SAFE_MARKDOWN_WINDOW_OVERLAP = 16, safeMarkdownCache = /* @__PURE__ */ new WeakMap(), structuredStreamCache = /* @__PURE__ */ new WeakMap(), topLevelStreamParseMode = /* @__PURE__ */ new WeakMap(), REUSABLE_INLINE_TOKEN_TYPES = /* @__PURE__ */ new Set([
15811
15839
  "code_inline",
15812
15840
  "em_close",
15813
15841
  "em_open",
15814
15842
  "emoji",
15815
15843
  "hardbreak",
15844
+ "html_block",
15845
+ "html_inline",
15846
+ "image",
15816
15847
  "ins_close",
15817
15848
  "ins_open",
15849
+ "link",
15850
+ "link_close",
15851
+ "link_open",
15818
15852
  "mark_close",
15819
15853
  "mark_open",
15854
+ "math_inline",
15820
15855
  "s_close",
15821
15856
  "s_open",
15822
15857
  "softbreak",
@@ -15836,6 +15871,7 @@ var tolerantMathBoundaryStreamCache = /* @__PURE__ */ new WeakMap(), pendingExpl
15836
15871
  "code_block",
15837
15872
  "fence",
15838
15873
  "hr",
15874
+ "inline",
15839
15875
  "math_block"
15840
15876
  ]);
15841
15877
  function getParserNow() {
@@ -15867,21 +15903,38 @@ function processTokensWithTiming(tokens, options, timing) {
15867
15903
  let startedAt = getParserNow(), result = processTokens(tokens, options);
15868
15904
  return addTiming(timing, "processTokensMs", getParserNow() - startedAt), result;
15869
15905
  }
15870
- function hasOnlyReusableInlineTokens(tokens) {
15906
+ function hasOnlyReusableInlineTokens(tokens, validateLink$1) {
15871
15907
  return tokens.every((token) => {
15872
- if (!REUSABLE_INLINE_TOKEN_TYPES.has(token.type))
15908
+ if (!REUSABLE_INLINE_TOKEN_TYPES.has(token.type) || (token.type === "link" || token.type === "link_open" || token.type === "link_close") && !isCacheStableLinkValidator(validateLink$1))
15873
15909
  return !1;
15910
+ if (token.type === "link") {
15911
+ let origin = readSyntheticLinkOrigin(token);
15912
+ if (origin !== "explicit" && origin !== "linkify" && origin !== "autolink")
15913
+ return !1;
15914
+ }
15915
+ if (token.type === "link_open" || token.type === "link_close") {
15916
+ let markup = token.markup ?? "";
15917
+ if (markup !== "" && markup !== "linkify" && markup !== "autolink")
15918
+ return !1;
15919
+ }
15874
15920
  let children = token.children;
15875
- return !Array.isArray(children) || hasOnlyReusableInlineTokens(children);
15921
+ return !Array.isArray(children) || hasOnlyReusableInlineTokens(children, validateLink$1);
15876
15922
  });
15877
15923
  }
15878
- function getReusableTopLevelTokenGroups(tokens) {
15924
+ function getReusableTopLevelPairedCloseType(tokenType) {
15925
+ let known = REUSABLE_TOP_LEVEL_PAIRED_TOKEN_TYPES.get(tokenType);
15926
+ if (known)
15927
+ return known;
15928
+ let containerMatch = /^container_(.+)_open$/.exec(tokenType);
15929
+ return containerMatch ? `container_${containerMatch[1]}_close` : void 0;
15930
+ }
15931
+ function getReusableTopLevelTokenGroups(tokens, validateLink$1) {
15879
15932
  let groupStarts = [], mixed = !1, index = 0;
15880
15933
  for (; index < tokens.length; ) {
15881
15934
  let token = tokens[index];
15882
15935
  if (!token || token.level !== 0)
15883
15936
  return null;
15884
- let closeType = REUSABLE_TOP_LEVEL_PAIRED_TOKEN_TYPES.get(token.type), groupEnd = index + 1;
15937
+ let closeType = getReusableTopLevelPairedCloseType(token.type), groupEnd = index + 1;
15885
15938
  if (closeType) {
15886
15939
  if (token.nesting !== 1)
15887
15940
  return null;
@@ -15913,7 +15966,7 @@ function getReusableTopLevelTokenGroups(tokens) {
15913
15966
  if (current.type !== "inline")
15914
15967
  continue;
15915
15968
  let children = current.children;
15916
- if (!Array.isArray(children) || !hasOnlyReusableInlineTokens(children))
15969
+ if (!Array.isArray(children) || !hasOnlyReusableInlineTokens(children, validateLink$1))
15917
15970
  return null;
15918
15971
  }
15919
15972
  groupStarts.push(index), index = groupEnd;
@@ -15948,24 +16001,36 @@ function updateStructuredStreamCache(md, source, tokens, groups, nodes, options)
15948
16001
  source,
15949
16002
  nodes,
15950
16003
  stableGroupCount: groups.mixed ? Math.max(0, groupStarts.length - 1) : sourceEndsWithBlankLine(source) ? groupStarts.length : Math.max(0, groupStarts.length - 1),
15951
- requireClosingStrong: options.requireClosingStrong
16004
+ requireClosingStrong: options.requireClosingStrong,
16005
+ validateLink: options.validateLink
15952
16006
  });
15953
16007
  }
15954
16008
  function hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount) {
16009
+ let lastGroupIndex = groupStarts.length - 1;
15955
16010
  for (let index = 0; index < stableGroupCount; index++) {
15956
16011
  let start = groupStarts[index], end = groupStarts[index + 1] ?? tokens.length, boundary = previous.groupBoundaries[index];
15957
- if (!boundary || boundary.firstToken !== tokens[start] || boundary.lastToken !== tokens[end - 1] || boundary.tokenCount !== end - start)
16012
+ if (!boundary || boundary.tokenCount !== end - start)
16013
+ return !1;
16014
+ if (!(boundary.firstToken === tokens[start] && boundary.lastToken === tokens[end - 1]) && (index >= lastGroupIndex || !isSameTokenShapeForReuse(boundary.firstToken, tokens[start]) || !isSameTokenShapeForReuse(boundary.lastToken, tokens[end - 1])))
15958
16015
  return !1;
15959
16016
  }
15960
16017
  return !0;
15961
16018
  }
15962
16019
  function processTopLevelTokensWithReuse(md, source, tokens, options, timing) {
15963
- let owner = md, groups = getReusableTopLevelTokenGroups(tokens);
15964
- if (!(shouldUseTopLevelStreamParse(md, options) && canReuseStructuredStreamNodes(options) && groups !== null))
16020
+ let owner = md, structuredReuseDisabled = options.__disableStructuredReuse === !0;
16021
+ if (!(shouldUseTopLevelStreamParse(md, options) && canReuseStructuredStreamNodes(options)))
16022
+ return structuredReuseDisabled || structuredStreamCache.delete(owner), processTokensWithTiming(tokens, options, timing);
16023
+ if (structuredReuseDisabled)
16024
+ return processTokensWithTiming(tokens, options, timing);
16025
+ let groups = getReusableTopLevelTokenGroups(tokens, options.validateLink);
16026
+ if (!groups)
15965
16027
  return structuredStreamCache.delete(owner), processTokensWithTiming(tokens, options, timing);
15966
16028
  let groupStarts = groups.starts, previous = structuredStreamCache.get(owner), mode = topLevelStreamParseMode.get(owner), stableGroupCount = previous && groups.mixed ? Math.min(previous.stableGroupCount, Math.max(0, previous.groupBoundaries.length - 1)) : previous?.stableGroupCount ?? 0;
15967
- if (previous && stableGroupCount > 0 && previous.requireClosingStrong === options.requireClosingStrong && source.startsWith(previous.source) && groupStarts.length >= stableGroupCount && (mode === "append" || mode === "tail") && hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount)) {
15968
- let tailStart = groupStarts[stableGroupCount] ?? tokens.length, tailNodes = processTokensWithTiming(tokens.slice(tailStart), options, timing), expectedTailNodes = groupStarts.length - stableGroupCount;
16029
+ if (previous && stableGroupCount > 0 && previous.requireClosingStrong === options.requireClosingStrong && previous.validateLink === options.validateLink && source.startsWith(previous.source) && groupStarts.length >= stableGroupCount && (mode === "append" || mode === "tail") && hasStableStructuredStreamGroupBoundaries(previous, tokens, groupStarts, stableGroupCount)) {
16030
+ let tailStart = groupStarts[stableGroupCount] ?? tokens.length, tailNodes = processTokensWithTiming(tokens.slice(tailStart), {
16031
+ ...options,
16032
+ __linkifyDemotionSeed: previous.nodes.slice(0, stableGroupCount).map((node) => String(node.raw ?? ""))
16033
+ }, timing), expectedTailNodes = groupStarts.length - stableGroupCount;
15969
16034
  if (tailNodes.length === expectedTailNodes) {
15970
16035
  let result$1 = previous.nodes.slice(0, stableGroupCount).concat(tailNodes);
15971
16036
  return addTiming(timing, "processTokensReusedTopLevelNodes", stableGroupCount), updateStructuredStreamCache(md, source, tokens, groups, result$1, options), result$1;
@@ -16573,6 +16638,22 @@ function sameTokenMap(left, right) {
16573
16638
  let leftMap = left?.map, rightMap = right?.map;
16574
16639
  return leftMap === rightMap ? !0 : !Array.isArray(leftMap) || !Array.isArray(rightMap) ? !1 : leftMap.length === rightMap.length && leftMap.every((value, index) => value === rightMap[index]);
16575
16640
  }
16641
+ function sameTokenAttrs(left, right) {
16642
+ let leftAttrs = left?.attrs, rightAttrs = right?.attrs;
16643
+ if (leftAttrs === rightAttrs)
16644
+ return !0;
16645
+ if (!Array.isArray(leftAttrs) || !Array.isArray(rightAttrs) || leftAttrs.length !== rightAttrs.length)
16646
+ return !1;
16647
+ for (let index = 0; index < leftAttrs.length; index++) {
16648
+ let leftAttr = leftAttrs[index], rightAttr = rightAttrs[index];
16649
+ if (leftAttr[0] !== rightAttr[0] || leftAttr[1] !== rightAttr[1])
16650
+ return !1;
16651
+ }
16652
+ return !0;
16653
+ }
16654
+ function isSameTokenShapeForReuse(left, right) {
16655
+ return !!left && !!right && left.type === right.type && left.tag === right.tag && left.nesting === right.nesting && left.level === right.level && left.markup === right.markup && left.content === right.content && left.info === right.info && sameTokenMap(left, right) && sameTokenAttrs(left, right);
16656
+ }
16576
16657
  function isSameTokenShape(left, right) {
16577
16658
  return !!left && !!right && left.type === right.type && left.tag === right.tag && left.nesting === right.nesting && left.markup === right.markup && left.content === right.content && sameTokenMap(left, right);
16578
16659
  }
@@ -17000,7 +17081,8 @@ function hasTopLevelHtmlBlock(nodes) {
17000
17081
  function parseDetailsFragmentChildren(fragment, md, options) {
17001
17082
  return fragment.trim() ? parseMarkdownToStructure(fragment, md, {
17002
17083
  ...options,
17003
- __disableStreamParse: !0
17084
+ __disableStreamParse: !0,
17085
+ __disableStructuredReuse: !0
17004
17086
  }) : [];
17005
17087
  }
17006
17088
  function parseSummaryChildren(fragment, md, options) {
@@ -17196,54 +17278,7 @@ function stripDanglingHtmlLikeTail(markdown) {
17196
17278
  }
17197
17279
  }
17198
17280
  return !0;
17199
- }, isInsideFencedCodeBlock = (src, pos) => {
17200
- let inFence = !1, fenceChar = "", fenceLen = 0, isIndentWs = (ch) => ch === " " || ch === " ", parseFenceMarker = (line) => {
17201
- let i = 0;
17202
- for (; i < line.length && isIndentWs(line[i]); )
17203
- i++;
17204
- let ch = line[i];
17205
- if (ch !== "`" && ch !== "~")
17206
- return null;
17207
- let j = i;
17208
- for (; j < line.length && line[j] === ch; )
17209
- j++;
17210
- let len = j - i;
17211
- return len < 3 ? null : {
17212
- markerChar: ch,
17213
- markerLen: len,
17214
- rest: line.slice(j)
17215
- };
17216
- }, stripBlockquotePrefix = (line) => {
17217
- let i = 0;
17218
- for (; i < line.length && isIndentWs(line[i]); )
17219
- i++;
17220
- let saw = !1;
17221
- for (; i < line.length && line[i] === ">"; )
17222
- for (saw = !0, i++; i < line.length && isIndentWs(line[i]); )
17223
- i++;
17224
- return saw ? line.slice(i) : null;
17225
- }, matchFence = (rawLine) => {
17226
- let direct = parseFenceMarker(rawLine);
17227
- if (direct)
17228
- return direct;
17229
- let afterQuote = stripBlockquotePrefix(rawLine);
17230
- return afterQuote == null ? null : parseFenceMarker(afterQuote);
17231
- }, offset = 0, lines = src.split(/\r?\n/);
17232
- for (let line of lines) {
17233
- let lineStart = offset, lineEnd$2 = offset + line.length;
17234
- if (pos < lineStart)
17235
- break;
17236
- let fenceMatch = matchFence(line);
17237
- if (fenceMatch) {
17238
- let markerChar = fenceMatch.markerChar, markerLen = fenceMatch.markerLen;
17239
- inFence ? markerChar === fenceChar && markerLen >= fenceLen && /^\s*$/.test(fenceMatch.rest) && (inFence = !1, fenceChar = "", fenceLen = 0) : (inFence = !0, fenceChar = markerChar, fenceLen = markerLen);
17240
- }
17241
- if (pos <= lineEnd$2)
17242
- break;
17243
- offset = lineEnd$2 + 1;
17244
- }
17245
- return inFence;
17246
- }, s = String(markdown ?? ""), lastLt = s.lastIndexOf("<");
17281
+ }, isInsideFencedCodeBlock = (src, pos) => isInsideOpenMarkdownFenceBeforeOffset(src, pos), s = String(markdown ?? ""), lastLt = s.lastIndexOf("<");
17247
17282
  if (lastLt === -1 || isInsideFencedCodeBlock(s, lastLt))
17248
17283
  return s;
17249
17284
  if (lastLt > 0) {
@@ -17889,9 +17924,76 @@ function ensureBlankLineBeforeCustomHtmlBlocks(markdown, tags) {
17889
17924
  }
17890
17925
  return out;
17891
17926
  }
17892
- function parseMarkdownToStructure(markdown, md, options = {}) {
17893
- let timing = getParseTiming(options), parseStartedAt = timing ? getParserNow() : 0, isFinal = !!options.final, sourceMarkdown = (markdown ?? "").toString(), safeMarkdown = sourceMarkdown.replace(/([^\\])\r(ight|ho)/g, "$1\\r$2").replace(/([^\\])\r?\n(abla|eq|ot|exists)/g, "$1\\n$2");
17894
- if (shouldResetTopLevelStreamCacheForFinalAutoParse(md, options) && (md.stream.reset(), clearTolerantMathBoundaryStreamCache(md)), isFinal || (safeMarkdown.endsWith("- *") && (safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*")), /(?:^|\n)\s*-\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => m.startsWith(`
17927
+ function createLatexSplitMathScanner(source) {
17928
+ let inFence = !1, fenceMarker = "", fenceLen = 0, inDollarBlock = !1, inBracketMath = !1, singleDollarOpen = !1, scanned = 0, processLine = (line, _lineStartOffset) => {
17929
+ let fenceMatch = matchMarkdownFenceMarker(line);
17930
+ if (fenceMatch) {
17931
+ inFence ? fenceMatch.markerChar === fenceMarker && fenceMatch.markerLen >= fenceLen && /^\s*$/.test(fenceMatch.rest) && (inFence = !1, fenceMarker = "", fenceLen = 0) : (inFence = !0, fenceMarker = fenceMatch.markerChar, fenceLen = fenceMatch.markerLen);
17932
+ return;
17933
+ }
17934
+ if (inFence)
17935
+ return;
17936
+ let i = 0;
17937
+ for (; i < line.length; ) {
17938
+ if (inDollarBlock) {
17939
+ line.startsWith("$$", i) && !isEscapedDelimiterAt(line, i) ? (inDollarBlock = !1, i += 2) : i++;
17940
+ continue;
17941
+ }
17942
+ if (inBracketMath) {
17943
+ line.startsWith("\\]", i) && !isEscapedDelimiterAt(line, i) ? (inBracketMath = !1, i += 2) : i++;
17944
+ continue;
17945
+ }
17946
+ let ch = line[i];
17947
+ if (ch === "`") {
17948
+ let runLen = countRepeatedChar(line, i, "`"), closeIndex = findCodeSpanCloseIndex(line, i + runLen, runLen);
17949
+ if (closeIndex === -1)
17950
+ break;
17951
+ i = closeIndex + runLen;
17952
+ continue;
17953
+ }
17954
+ if (ch === "\\") {
17955
+ let next = line[i + 1];
17956
+ next === "[" && !isEscapedDelimiterAt(line, i) ? (inBracketMath = !0, i += 2) : (next === "]" && isEscapedDelimiterAt(line, i), i += 2);
17957
+ continue;
17958
+ }
17959
+ if (ch === "$") {
17960
+ if (line[i + 1] === "$" && !isEscapedDelimiterAt(line, i)) {
17961
+ inDollarBlock = !0, singleDollarOpen = !1, i += 2;
17962
+ continue;
17963
+ }
17964
+ if (singleDollarOpen) {
17965
+ singleDollarOpen = !1, i++;
17966
+ continue;
17967
+ }
17968
+ let after = line[i + 1];
17969
+ (after === void 0 || after !== " " && after !== " " && !/\d/.test(after)) && (singleDollarOpen = !0), i++;
17970
+ continue;
17971
+ }
17972
+ i++;
17973
+ }
17974
+ };
17975
+ return {
17976
+ scanTo: (target) => {
17977
+ for (; scanned < target; ) {
17978
+ let newlineIndex = source.indexOf(`
17979
+ `, scanned), lineEndRaw = newlineIndex === -1 || newlineIndex >= target ? target : newlineIndex, lineEnd$2 = lineEndRaw > scanned && source[lineEndRaw - 1] === "\r" ? lineEndRaw - 1 : lineEndRaw;
17980
+ if (processLine(source.slice(scanned, lineEnd$2), scanned), newlineIndex === -1 || newlineIndex >= target) {
17981
+ scanned = target;
17982
+ break;
17983
+ }
17984
+ singleDollarOpen = !1, scanned = newlineIndex + 1;
17985
+ }
17986
+ },
17987
+ inMath: () => inDollarBlock || inBracketMath || singleDollarOpen
17988
+ };
17989
+ }
17990
+ function transformStreamingSafeMarkdown(source, isFinal, md, options) {
17991
+ let safeMarkdown = source.replace(/([^\\])\r(ight|ho)/g, "$1\\r$2"), latexSplitMathScanner = createLatexSplitMathScanner(safeMarkdown);
17992
+ if (safeMarkdown = safeMarkdown.replace(/([^\\])\r?\n(abla|eq|ot|exists)/g, (full, before, cmd, offset) => {
17993
+ latexSplitMathScanner.scanTo(offset + 1);
17994
+ let shouldReconstruct = latexSplitMathScanner.inMath();
17995
+ return latexSplitMathScanner.scanTo(offset + full.length), shouldReconstruct ? `${before}\\n${cmd}` : full;
17996
+ }), isFinal || (safeMarkdown.endsWith("- *") && (safeMarkdown = safeMarkdown.replace(/- \*$/, "- \\*")), /(?:^|\n)\s*-\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*-\s*$/, (m) => m.startsWith(`
17895
17997
  `) ? `
17896
17998
  ` : "") : /(?:^|\n)\s*--\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*--\s*$/, (m) => m.startsWith(`
17897
17999
  `) ? `
@@ -17903,7 +18005,7 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
17903
18005
  ` : "")) : /(?:^|\n)\s*\d+[.)]\s+\*{1,3}\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/((?:^|\n)\s*\d+[.)]\s+)(\*{1,3})\s*$/, (_, prefix, stars) => `${prefix}${stars.split("").map(() => "\\*").join("")}`) : /(?:^|\n)\s*\d+[.)]\s*$/.test(safeMarkdown) ? safeMarkdown = safeMarkdown.replace(/(?:^|\n)\s*\d+[.)]\s*$/, (m) => m.startsWith(`
17904
18006
  `) ? `
17905
18007
  ` : "") : /\n[[(]\n*$/.test(safeMarkdown) && (safeMarkdown = safeMarkdown.replace(/(\n\[|\n\()+\n*$/g, `
17906
- `)), safeMarkdown = stripPendingExplicitMathTail(safeMarkdown, md), safeMarkdown = getStreamingAdmonitionOpenTailReplacement(safeMarkdown, options.customHtmlTags) ?? safeMarkdown), options.customHtmlTags?.length && safeMarkdown.includes("<")) {
18008
+ `)), safeMarkdown = getStreamingAdmonitionOpenTailReplacement(safeMarkdown, options.customHtmlTags) ?? safeMarkdown), options.customHtmlTags?.length && safeMarkdown.includes("<")) {
17907
18009
  let tags = normalizeCustomHtmlTags(options.customHtmlTags);
17908
18010
  if (tags.length && (safeMarkdown = ensureBlankLineBeforeInlineMultilineCustomHtmlBlocks(safeMarkdown, tags), safeMarkdown = normalizeCustomHtmlOpeningTagSameLine(safeMarkdown, tags), safeMarkdown = ensureBlankLineBeforeCustomHtmlBlocks(safeMarkdown, tags), safeMarkdown = ensureBlankLineAfterCustomHtmlCloseBeforeBlockMarkerSameLine(safeMarkdown, tags), safeMarkdown.includes("</")))
17909
18011
  for (let tag of tags) {
@@ -17911,7 +18013,26 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
17911
18013
  safeMarkdown = safeMarkdown.replace(re, "$1$2$2");
17912
18014
  }
17913
18015
  }
17914
- isFinal || (safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown));
18016
+ return isFinal || (safeMarkdown = stripDanglingHtmlLikeTail(safeMarkdown)), safeMarkdown;
18017
+ }
18018
+ function getSafeMarkdown(md, sourceMarkdown, isFinal, options) {
18019
+ let owner = md, mode = `${isFinal ? "final" : "stream"}:${(options.customHtmlTags ?? []).join(",")}`, previous = safeMarkdownCache.get(owner), safeMarkdown;
18020
+ if (!isFinal && !options.customHtmlTags?.length && previous && previous.mode === mode && sourceMarkdown.length >= previous.source.length && sourceMarkdown.startsWith(previous.source)) {
18021
+ let windowStart = Math.max(0, previous.source.length - SAFE_MARKDOWN_WINDOW_MARGIN - SAFE_MARKDOWN_WINDOW_OVERLAP), transformed = transformStreamingSafeMarkdown(sourceMarkdown.slice(windowStart), isFinal, md, options), overlapLength = previous.source.length - windowStart;
18022
+ safeMarkdown = transformed.length >= overlapLength && transformed.slice(0, overlapLength) === previous.safeMarkdown.slice(-overlapLength) ? previous.safeMarkdown.slice(0, previous.safeMarkdown.length - overlapLength) + transformed : transformStreamingSafeMarkdown(sourceMarkdown, isFinal, md, options);
18023
+ } else
18024
+ safeMarkdown = transformStreamingSafeMarkdown(sourceMarkdown, isFinal, md, options);
18025
+ return isFinal || (safeMarkdown = stripPendingExplicitMathTail(safeMarkdown, md)), safeMarkdownCache.set(owner, {
18026
+ source: sourceMarkdown,
18027
+ safeMarkdown,
18028
+ mode
18029
+ }), safeMarkdown;
18030
+ }
18031
+ function parseMarkdownToStructure(markdown, md, options = {}) {
18032
+ let timing = getParseTiming(options), parseStartedAt = timing ? getParserNow() : 0, isFinal = !!options.final, sourceMarkdown = (markdown ?? "").toString();
18033
+ shouldResetTopLevelStreamCacheForFinalAutoParse(md, options) && (md.stream.reset(), clearTolerantMathBoundaryStreamCache(md), safeMarkdownCache.delete(md));
18034
+ let safeMarkdown = getSafeMarkdown(md, sourceMarkdown, isFinal, options);
18035
+ timing && addTiming(timing, "safeMarkdownMs", getParserNow() - parseStartedAt);
17915
18036
  let standaloneHtmlDocument = parseStandaloneHtmlDocument(safeMarkdown);
17916
18037
  if (standaloneHtmlDocument) {
17917
18038
  if (options.includeSourceMap) {
@@ -17928,8 +18049,8 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
17928
18049
  }
17929
18050
  return finishParsedNodes(standaloneHtmlDocument, options, timing, parseStartedAt);
17930
18051
  }
17931
- let tokens = parseTopLevelTokens(md, safeMarkdown, { __markstreamFinal: isFinal }, options);
17932
- if (!tokens || !Array.isArray(tokens))
18052
+ let tokenizeStartedAt = timing ? getParserNow() : 0, tokens = parseTopLevelTokens(md, safeMarkdown, { __markstreamFinal: isFinal }, options);
18053
+ if (timing && addTiming(timing, "tokenizeMs", getParserNow() - tokenizeStartedAt), !tokens || !Array.isArray(tokens))
17933
18054
  return finishParsedNodes([], options, timing, parseStartedAt);
17934
18055
  let pre = options.preTransformTokens, post = options.postTransformTokens, transformedTokens = tokens;
17935
18056
  pre && typeof pre == "function" && (transformedTokens = pre(transformedTokens) || transformedTokens);
@@ -17951,7 +18072,11 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
17951
18072
  }, timing) : result = postResult;
17952
18073
  }
17953
18074
  }
17954
- if (hasTopLevelHtmlBlock(result) && (result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown, internalOptions), result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md, internalOptions, isFinal)[0], result = structureGenericHtmlBlockChildren(result, md, internalOptions, isFinal)), isFinal) {
18075
+ if (hasTopLevelHtmlBlock(result)) {
18076
+ let htmlPassesStartedAt = timing ? getParserNow() : 0;
18077
+ result = mergeSplitTopLevelHtmlBlocks(result, isFinal, safeMarkdown, internalOptions), result = combineStructuredDetailsHtmlBlocks(result, safeMarkdown, md, internalOptions, isFinal)[0], result = structureGenericHtmlBlockChildren(result, md, internalOptions, isFinal), timing && addTiming(timing, "htmlBlockPassesMs", getParserNow() - htmlPassesStartedAt);
18078
+ }
18079
+ if (isFinal) {
17955
18080
  let seen = /* @__PURE__ */ new WeakSet(), finalizeHtmlBlockLoading = (value) => {
17956
18081
  if (!value || typeof value != "object" || seen.has(value))
17957
18082
  return;
@@ -17972,7 +18097,11 @@ function parseMarkdownToStructure(markdown, md, options = {}) {
17972
18097
  function processTokens(tokens, options) {
17973
18098
  if (!tokens || !Array.isArray(tokens))
17974
18099
  return [];
17975
- let result = [], linkifyContext = createLinkifyDemotionContextTracker(options), includeSourceMap = options?.includeSourceMap === !0, i = 0;
18100
+ let result = [], linkifyContext = createLinkifyDemotionContextTracker(options), seedRaws = options?.__linkifyDemotionSeed;
18101
+ if (Array.isArray(seedRaws) && seedRaws.length)
18102
+ for (let raw of seedRaws)
18103
+ linkifyContext.remember(String(raw ?? ""));
18104
+ let includeSourceMap = options?.includeSourceMap === !0, i = 0;
17976
18105
  for (; i < tokens.length; ) {
17977
18106
  let handled = parseCommonBlockToken(tokens, i, linkifyContext.options(), containerTokenHandlers);
17978
18107
  if (handled) {
@@ -19730,11 +19859,60 @@ function mergeStyle2(base, overlay) {
19730
19859
  let merged = Object.freeze({ ...base, ...overlay });
19731
19860
  return bucket.set(overlay, merged), merged;
19732
19861
  }
19733
- var activeMarkdownImageGraphics = /* @__PURE__ */ new WeakMap();
19862
+ var activeMarkdownImageGraphics = /* @__PURE__ */ new WeakMap(), markdownImageGraphicIdCache = /* @__PURE__ */ new WeakMap(), preparedMarkdownImageGraphicCache = /* @__PURE__ */ new WeakMap();
19734
19863
  function markdownImageGraphicId(segment, identity) {
19735
- return `md-image:${stableTerminalGraphicNumericId(
19864
+ let cachedIds = markdownImageGraphicIdCache.get(segment);
19865
+ cachedIds || (cachedIds = /* @__PURE__ */ new Map(), markdownImageGraphicIdCache.set(segment, cachedIds));
19866
+ let cached = cachedIds.get(identity);
19867
+ if (cached)
19868
+ return cached;
19869
+ let id = `md-image:${stableTerminalGraphicNumericId(
19736
19870
  `${identity}:${segment.src ?? segment.tex ?? ""}:${segment.displayWidth ?? 0}:${segment.displayHeight ?? 0}:${segment.base64 ?? ""}`
19737
19871
  )}`;
19872
+ return cachedIds.set(identity, id), id;
19873
+ }
19874
+ function prepareMarkdownImageGraphic(segment, identity, protocol, placement) {
19875
+ if (!segment.base64)
19876
+ return null;
19877
+ let preparedByVariant = preparedMarkdownImageGraphicCache.get(segment);
19878
+ preparedByVariant || (preparedByVariant = /* @__PURE__ */ new Map(), preparedMarkdownImageGraphicCache.set(segment, preparedByVariant));
19879
+ let cacheKey = `${identity}\0${protocol}\0${placement.width}\0${placement.height}\0${placement.sourceX ?? ""}\0${placement.sourceY ?? ""}\0${placement.sourceWidth ?? ""}\0${placement.sourceHeight ?? ""}`, cached = preparedByVariant.get(cacheKey);
19880
+ if (cached)
19881
+ return cached;
19882
+ let id = markdownImageGraphicId(segment, identity), imageId = stableTerminalGraphicNumericId(`image:${id}`), placementId = stableTerminalGraphicNumericId(`placement:${id}`), sequence = protocol === "kitty" ? createKittyGraphicsSequence(segment.base64, {
19883
+ imageId,
19884
+ placementId,
19885
+ columns: placement.width,
19886
+ rows: placement.height,
19887
+ sourceX: placement.sourceX,
19888
+ sourceY: placement.sourceY,
19889
+ sourceWidth: placement.sourceWidth,
19890
+ sourceHeight: placement.sourceHeight,
19891
+ zIndex: -1
19892
+ }) : protocol === "iterm2" ? createIterm2InlineImageSequence(segment.base64, {
19893
+ width: placement.width,
19894
+ height: placement.height,
19895
+ preserveAspectRatio: !0,
19896
+ doNotMoveCursor: !0
19897
+ }) : "";
19898
+ if (!sequence)
19899
+ return null;
19900
+ let prepared = Object.freeze({
19901
+ id,
19902
+ sequence,
19903
+ clearSequence: protocol === "kitty" ? createKittyDeleteGraphicsSequence({ imageId, placementId }) : void 0,
19904
+ resizeSequence: protocol === "kitty" ? createKittyPlacementSequence({
19905
+ imageId,
19906
+ placementId,
19907
+ columns: placement.width,
19908
+ rows: placement.height,
19909
+ sourceX: placement.sourceX,
19910
+ sourceY: placement.sourceY,
19911
+ sourceWidth: placement.sourceWidth,
19912
+ sourceHeight: placement.sourceHeight
19913
+ }) : void 0
19914
+ });
19915
+ return preparedByVariant.set(cacheKey, prepared), prepared;
19738
19916
  }
19739
19917
  function rememberMarkdownImageGraphic(terminal, id, rect) {
19740
19918
  let active = activeMarkdownImageGraphics.get(terminal);
@@ -19765,57 +19943,47 @@ function clearMarkdownImageGraphics(terminal, rect) {
19765
19943
  for (let [id, item] of active)
19766
19944
  rect && (item.x >= rect.x + rect.w || item.x + item.w <= rect.x || item.y >= rect.y + rect.h || item.y + item.h <= rect.y) || clearTrackedMarkdownImageGraphic(terminal, id);
19767
19945
  }
19768
- function queueMarkdownImageGraphic(terminal, segment, identity, rect) {
19946
+ function queueMarkdownImageGraphic(terminal, segment, identity, rect, placementOverride) {
19769
19947
  if (!segment.base64)
19770
19948
  return "unavailable";
19771
19949
  let output = getTerminalGraphicsOutput(terminal), protocol = output?.capabilities.preferredProtocol;
19772
19950
  if (!output?.capabilities.supported || !isTerminalGraphicsProtocol(protocol))
19773
19951
  return "unavailable";
19774
- let width = Math.max(1, Math.floor(segment.displayWidth ?? rect.w)), height = Math.max(1, Math.floor(segment.displayHeight ?? 1)), id = markdownImageGraphicId(segment, identity), imageId = stableTerminalGraphicNumericId(`image:${id}`), placementId = stableTerminalGraphicNumericId(`placement:${id}`), sequence = protocol === "kitty" ? createKittyGraphicsSequence(segment.base64, {
19775
- imageId,
19776
- placementId,
19777
- columns: width,
19778
- rows: height,
19779
- zIndex: -1
19780
- }) : protocol === "iterm2" ? createIterm2InlineImageSequence(segment.base64, {
19781
- width,
19782
- height,
19783
- preserveAspectRatio: !0,
19784
- doNotMoveCursor: !0
19785
- }) : "";
19786
- if (!sequence)
19952
+ let placement = placementOverride ?? {
19953
+ width: Math.max(1, Math.floor(segment.displayWidth ?? rect.w)),
19954
+ height: Math.max(1, Math.floor(segment.displayHeight ?? 1))
19955
+ }, prepared = prepareMarkdownImageGraphic(segment, identity, protocol, placement);
19956
+ if (!prepared)
19787
19957
  return "unavailable";
19788
- let clearSequence = protocol === "kitty" ? createKittyDeleteGraphicsSequence({
19789
- imageId,
19790
- placementId
19791
- }) : void 0, resizeSequence = protocol === "kitty" ? createKittyPlacementSequence({
19792
- imageId,
19793
- placementId,
19794
- columns: width,
19795
- rows: height
19796
- }) : void 0, accepted = output.queue({
19797
- id,
19958
+ let accepted = output.queue({
19959
+ id: prepared.id,
19798
19960
  x: rect.x,
19799
19961
  y: rect.y,
19800
- w: width,
19801
- h: height,
19962
+ w: placement.width,
19963
+ h: placement.height,
19802
19964
  protocol,
19803
- sequence,
19804
- resizeSequence,
19805
- clearSequence,
19965
+ sequence: prepared.sequence,
19966
+ resizeSequence: prepared.resizeSequence,
19967
+ clearSequence: prepared.clearSequence,
19968
+ placementMoveWithoutClear: protocol === "kitty",
19806
19969
  fallbackText: segment.alt ?? (segment.kind === "math" ? segment.raw ?? segment.tex ?? "math" : "image")
19807
19970
  });
19808
19971
  return markdownImageDebug(
19809
- `queue id=${id}`,
19972
+ `queue id=${prepared.id}`,
19810
19973
  `accepted=${accepted ? "true" : "false"}`,
19811
19974
  `x=${rect.x}`,
19812
19975
  `y=${rect.y}`,
19813
- `w=${width}`,
19814
- `h=${height}`,
19976
+ `w=${placement.width}`,
19977
+ `h=${placement.height}`,
19815
19978
  `visibleW=${rect.w}`,
19816
19979
  `displayW=${segment.displayWidth ?? ""}`,
19817
19980
  `displayH=${segment.displayHeight ?? ""}`
19818
- ), accepted && rememberMarkdownImageGraphic(terminal, id, { x: rect.x, y: rect.y, w: width, h: height }), accepted ? "queued" : "rejected";
19981
+ ), accepted && rememberMarkdownImageGraphic(terminal, prepared.id, {
19982
+ x: rect.x,
19983
+ y: rect.y,
19984
+ w: placement.width,
19985
+ h: placement.height
19986
+ }), accepted ? "queued" : "rejected";
19819
19987
  }
19820
19988
  function collectVisibleMarkdownImageGraphicIds(rows, options) {
19821
19989
  let keepIds = /* @__PURE__ */ new Set();
@@ -19831,7 +19999,7 @@ function collectVisibleMarkdownImageGraphicIds(rows, options) {
19831
19999
  let logicalX = 0;
19832
20000
  for (let [segmentIndex, segment] of row.segments.entries()) {
19833
20001
  let segmentStart = logicalX, segmentEnd = logicalX + segment.cells;
19834
- if (logicalX = segmentEnd, !segment.graphic || segmentEnd <= clipStart || segmentStart >= clipEnd || Math.max(segmentStart, clipStart) !== segmentStart)
20002
+ if (logicalX = segmentEnd, !segment.graphic || segmentEnd <= clipStart || segmentStart >= clipEnd)
19835
20003
  continue;
19836
20004
  let height = Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1));
19837
20005
  if (rowIndex + height <= firstRow || rowIndex >= lastRow)
@@ -19847,10 +20015,74 @@ function collectVisibleMarkdownImageGraphicIds(rows, options) {
19847
20015
  }
19848
20016
  return keepIds;
19849
20017
  }
20018
+ function queueClippedVisibleMarkdownImageGraphics(terminal, rows, options) {
20019
+ let queuedIds = /* @__PURE__ */ new Set(), output = getTerminalGraphicsOutput(terminal);
20020
+ if (options.w <= 0 || options.h <= 0 || !output?.capabilities.supported || output.capabilities.preferredProtocol !== "kitty")
20021
+ return queuedIds;
20022
+ let clipStart = Math.max(0, Math.floor(options.clipStart)), firstRow = Math.min(rows.length, Math.max(0, Math.floor(options.rowOffset))), lastRow = Math.min(rows.length, firstRow + Math.max(0, Math.floor(options.h))), scanStart = firstRow;
20023
+ for (; scanStart > 0 && (rows[scanStart]?.segments.length ?? 0) === 0; )
20024
+ scanStart--;
20025
+ for (let rowIndex = scanStart; rowIndex < lastRow; rowIndex++) {
20026
+ let row = rows[rowIndex];
20027
+ if (!row)
20028
+ continue;
20029
+ let logicalX = 0;
20030
+ for (let [segmentIndex, segment] of row.segments.entries()) {
20031
+ let segmentStart = logicalX;
20032
+ if (logicalX += segment.cells, !segment.graphic?.base64)
20033
+ continue;
20034
+ let fullWidth = Math.max(1, Math.floor(segment.graphic.displayWidth ?? segment.cells)), fullHeight = Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1)), fullRect = {
20035
+ x: options.x + segmentStart - clipStart,
20036
+ y: options.y + rowIndex - firstRow,
20037
+ w: fullWidth,
20038
+ h: fullHeight
20039
+ }, visibleRect = {
20040
+ x: Math.max(options.x, fullRect.x),
20041
+ y: Math.max(options.y, fullRect.y),
20042
+ w: Math.min(options.x + options.w, fullRect.x + fullRect.w) - Math.max(options.x, fullRect.x),
20043
+ h: Math.min(options.y + options.h, fullRect.y + fullRect.h) - Math.max(options.y, fullRect.y)
20044
+ };
20045
+ if (visibleRect.w <= 0 || visibleRect.h <= 0 || visibleRect.x === fullRect.x && visibleRect.y === fullRect.y && visibleRect.w === fullRect.w && visibleRect.h === fullRect.h || options.isGraphicCovered?.(visibleRect))
20046
+ continue;
20047
+ let naturalWidth = Math.floor(segment.graphic.naturalWidth ?? 0), naturalHeight = Math.floor(segment.graphic.naturalHeight ?? 0);
20048
+ if (naturalWidth <= 0 || naturalHeight <= 0)
20049
+ continue;
20050
+ let offsetX = visibleRect.x - fullRect.x, offsetY = visibleRect.y - fullRect.y, sourceX = Math.floor(offsetX * naturalWidth / fullWidth), sourceY = Math.floor(offsetY * naturalHeight / fullHeight), sourceRight = Math.max(
20051
+ sourceX + 1,
20052
+ Math.min(naturalWidth, Math.ceil((offsetX + visibleRect.w) * naturalWidth / fullWidth))
20053
+ ), sourceBottom = Math.max(
20054
+ sourceY + 1,
20055
+ Math.min(
20056
+ naturalHeight,
20057
+ Math.ceil((offsetY + visibleRect.h) * naturalHeight / fullHeight)
20058
+ )
20059
+ ), identity = `${row.key}:${segmentIndex}`;
20060
+ queueMarkdownImageGraphic(
20061
+ terminal,
20062
+ segment.graphic,
20063
+ identity,
20064
+ { x: visibleRect.x, y: visibleRect.y, w: visibleRect.w },
20065
+ {
20066
+ width: visibleRect.w,
20067
+ height: visibleRect.h,
20068
+ sourceX,
20069
+ sourceY,
20070
+ sourceWidth: sourceRight - sourceX,
20071
+ sourceHeight: sourceBottom - sourceY
20072
+ }
20073
+ ) === "queued" && queuedIds.add(markdownImageGraphicId(segment.graphic, identity));
20074
+ }
20075
+ }
20076
+ return queuedIds;
20077
+ }
19850
20078
  function paintMarkdownVisualRow(terminal, row, options) {
19851
20079
  let clipStart = Math.max(0, Math.floor(options.clipStart ?? 0)), clipEnd = clipStart + options.w;
19852
20080
  if (!row) {
19853
- options.clear !== !1 && (terminal.write(spaces(options.w), { x: options.x, y: options.y, style: options.baseStyle }), clearStaleMarkdownImageGraphicsForRow(terminal, options.y, /* @__PURE__ */ new Set(), options.keepGraphicIds));
20081
+ options.clear !== !1 && (terminal.write(spaces(options.w), {
20082
+ x: options.x,
20083
+ y: options.y,
20084
+ style: options.baseStyle
20085
+ }), clearStaleMarkdownImageGraphicsForRow(terminal, options.y, /* @__PURE__ */ new Set(), options.keepGraphicIds));
19854
20086
  return;
19855
20087
  }
19856
20088
  let logicalX = 0, used = 0, queuedGraphics = /* @__PURE__ */ new Set();
@@ -19881,12 +20113,12 @@ function paintMarkdownVisualRow(terminal, row, options) {
19881
20113
  y: options.y,
19882
20114
  w: Math.max(1, Math.floor(segment.graphic.displayWidth ?? visibleCells)),
19883
20115
  h: Math.max(1, Math.floor(segment.graphic.displayHeight ?? 1))
19884
- }, queueResult = !(options.isGraphicCovered?.(graphicRect) === !0) && visibleStart === segmentStart && visibleCells > 0 && queueMarkdownImageGraphic(terminal, segment.graphic, `${row.key}:${segmentIndex}`, {
20116
+ }, graphicCovered = options.isGraphicCovered?.(graphicRect) === !0, graphicId = markdownImageGraphicId(segment.graphic, `${row.key}:${segmentIndex}`), queueResult = options.prequeuedGraphicIds?.has(graphicId) === !0 ? "queued" : !graphicCovered && visibleStart === segmentStart && visibleCells > 0 && queueMarkdownImageGraphic(terminal, segment.graphic, `${row.key}:${segmentIndex}`, {
19885
20117
  x: cellX,
19886
20118
  y: options.y,
19887
20119
  w: visibleCells
19888
20120
  }), graphicAvailable = queueResult || canAttemptMarkdownImageGraphic(terminal, segment.graphic), queuedGraphic = queueResult === "queued", suppressFallback = queuedGraphic || queueResult === "rejected" || graphicAvailable === !0;
19889
- queuedGraphic && queuedGraphics.add(markdownImageGraphicId(segment.graphic, `${row.key}:${segmentIndex}`)), terminal.write(
20121
+ queuedGraphic && queuedGraphics.add(graphicId), terminal.write(
19890
20122
  suppressFallback ? spaces(visibleCells) : sliceByCellsRange(
19891
20123
  segment.fallbackText ?? segment.graphic.alt ?? (segment.graphic.kind === "math" ? segment.graphic.raw ?? segment.graphic.tex ?? "math" : "image"),
19892
20124
  0,
@@ -20614,23 +20846,36 @@ function markdownStyleSignature(style) {
20614
20846
  style.href ?? ""
20615
20847
  ].join("") : "";
20616
20848
  }
20849
+ var markdownRowSignatureCache = /* @__PURE__ */ new WeakMap(), markdownRowGraphicSignatureCache = /* @__PURE__ */ new WeakMap();
20617
20850
  function markdownRowSignature(row) {
20618
- return row ? [
20851
+ if (!row)
20852
+ return "";
20853
+ let cached = markdownRowSignatureCache.get(row);
20854
+ if (cached != null)
20855
+ return cached;
20856
+ let signature = [
20619
20857
  row.key,
20620
20858
  row.plainText,
20621
20859
  row.segments.map(
20622
20860
  (segment) => `${segment.text}${segment.cells}${markdownStyleSignature(segment.style)}${segment.graphic?.src ?? ""}${segment.graphic?.base64 ?? ""}${segment.fallbackText ?? ""}`
20623
20861
  ).join("")
20624
- ].join("") : "";
20862
+ ].join("");
20863
+ return markdownRowSignatureCache.set(row, signature), signature;
20625
20864
  }
20626
20865
  function getWheelScrollInput(e) {
20627
20866
  let deltaY = Number(e.deltaY ?? 0), deltaMode = typeof e.deltaMode == "number" ? e.deltaMode : void 0;
20628
20867
  return Number.isInteger(deltaY) && deltaY !== 0 && Math.abs(deltaY) >= 100 && Math.abs(deltaY) % 100 === 0 && deltaMode == null ? { deltaY: deltaY / 100, mode: "line" } : deltaMode === 1 ? { deltaY, mode: "line" } : deltaMode === 0 ? { deltaY, mode: "pixel" } : { deltaY, mode: "auto" };
20629
20868
  }
20630
20869
  function rowGraphicSignature(row) {
20631
- return row ? row.segments.map(
20632
- (segment) => segment.graphic ? `${segment.graphic.kind}${segment.graphic.src}${segment.graphic.base64 ?? ""}` : ""
20633
- ).join("") : "";
20870
+ if (!row)
20871
+ return "";
20872
+ let cached = markdownRowGraphicSignatureCache.get(row);
20873
+ if (cached != null)
20874
+ return cached;
20875
+ let signature = row.segments.filter((segment) => segment.graphic).map(
20876
+ (segment) => `${segment.graphic.kind}${segment.graphic.src}${segment.graphic.base64 ?? ""}`
20877
+ ).join("");
20878
+ return markdownRowGraphicSignatureCache.set(row, signature), signature;
20634
20879
  }
20635
20880
  var TVirtualMarkdown = (0, import_vue10.defineComponent)({
20636
20881
  name: "TVirtualMarkdown",
@@ -20681,6 +20926,10 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
20681
20926
  imageOcclusionRects: {
20682
20927
  type: Array,
20683
20928
  default: void 0
20929
+ },
20930
+ rowScrollMode: {
20931
+ type: String,
20932
+ default: "off"
20684
20933
  }
20685
20934
  },
20686
20935
  emits: {
@@ -20694,7 +20943,16 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
20694
20943
  linkAction: (_payload) => !0
20695
20944
  },
20696
20945
  setup(props, { emit }) {
20697
- let instance = (0, import_vue10.getCurrentInstance)(), { terminal, defaultStyle, events, scheduler, selection, widthProvider } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue10.inject)(EventZIndexContextKey, (0, import_vue10.computed)(() => 0)), eventZ = (0, import_vue10.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), internalScrollTop = (0, import_vue10.ref)(0), documentVersion = (0, import_vue10.ref)(0), rows = (0, import_vue10.shallowRef)((0, import_vue10.markRaw)([])), pendingSelectionScrollFocusRemap = !1, wheelState = createWheelScrollState(), builtOnce = !1, rebuildVersion = 0, layoutCache, alive = !0, parser = (0, import_vue10.shallowRef)(
20946
+ let instance = (0, import_vue10.getCurrentInstance)(), {
20947
+ terminal,
20948
+ defaultStyle,
20949
+ events,
20950
+ scheduler,
20951
+ selection,
20952
+ widthProvider,
20953
+ render,
20954
+ rendererCapabilities
20955
+ } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue10.inject)(EventZIndexContextKey, (0, import_vue10.computed)(() => 0)), plane = (0, import_vue10.inject)(RenderPlaneContextKey, (0, import_vue10.ref)("default")), eventZ = (0, import_vue10.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), internalScrollTop = (0, import_vue10.ref)(0), documentVersion = (0, import_vue10.ref)(0), rows = (0, import_vue10.shallowRef)((0, import_vue10.markRaw)([])), pendingSelectionScrollFocusRemap = !1, wheelState = createWheelScrollState(), builtOnce = !1, rebuildVersion = 0, layoutCache, alive = !0, dirtyRowsHint, renderNodeId = null, parser = (0, import_vue10.shallowRef)(
20698
20956
  (0, import_vue10.markRaw)(
20699
20957
  createTuiMarkdownParser({
20700
20958
  streaming: props.streaming,
@@ -20769,7 +21027,16 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
20769
21027
  let nextRows = nextLayout.rows;
20770
21028
  rows.value = (0, import_vue10.markRaw)(nextRows), enqueuePendingMathImages(), reconcileScrollTop();
20771
21029
  let nextScrollTop = internalScrollTop.value, nextVisibleRows = visibleRowSignatures(nextRows, nextScrollTop), nextVisibleGraphics = visibleRowGraphics(nextRows, nextScrollTop), visibleChanged = prevVisibleRows.length !== nextVisibleRows.length || prevVisibleRows.some((row, index) => row !== nextVisibleRows[index]) || prevVisibleGraphics.some((row, index) => row !== nextVisibleGraphics[index]);
20772
- (!builtOnce || prevScrollTop !== nextScrollTop || visibleChanged) && (documentVersion.value++, selection.refresh());
21030
+ if (!builtOnce || prevScrollTop !== nextScrollTop || visibleChanged) {
21031
+ if (visibleChanged && prevScrollTop === nextScrollTop && prevVisibleGraphics.every((signature) => !signature) && nextVisibleGraphics.every((signature) => !signature)) {
21032
+ let rect = normalizedRect(), changedRows = [], count = Math.max(prevVisibleRows.length, nextVisibleRows.length);
21033
+ for (let index = 0; index < count; index++)
21034
+ prevVisibleRows[index] !== nextVisibleRows[index] && changedRows.push(rect.y + index);
21035
+ markRowsDirty(changedRows);
21036
+ } else
21037
+ markRowsDirty(viewportRows());
21038
+ documentVersion.value++, selection.refresh();
21039
+ }
20773
21040
  }
20774
21041
  function scheduleRebuild() {
20775
21042
  let currentVersion = ++rebuildVersion;
@@ -20826,16 +21093,60 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
20826
21093
  out.push(rowGraphicSignature(sourceRows[index]));
20827
21094
  return out;
20828
21095
  }
21096
+ function viewportRows() {
21097
+ let rect = normalizedRect(), result = [];
21098
+ for (let y = rect.y; y < rect.y + rect.h; y++)
21099
+ result.push(y);
21100
+ return result;
21101
+ }
21102
+ function exposedRowsForDelta(y, height, delta) {
21103
+ let result = [];
21104
+ if (delta > 0)
21105
+ for (let offset = height - delta; offset < height; offset++)
21106
+ result.push(y + offset);
21107
+ else
21108
+ for (let offset = 0; offset < -delta; offset++)
21109
+ result.push(y + offset);
21110
+ return result;
21111
+ }
21112
+ function markRowsDirty(nextRows) {
21113
+ let rows2 = new Set(dirtyRowsHint);
21114
+ for (let y of nextRows)
21115
+ rows2.add(y);
21116
+ dirtyRowsHint = Array.from(rows2).sort((a, b) => a - b), renderNodeId && render.markDirtyRows(renderNodeId, dirtyRowsHint);
21117
+ }
21118
+ function visibleGraphicsAt(scrollTop) {
21119
+ let rect = normalizedRect(), { x: clipX, y: clipY } = clipOffsets();
21120
+ return collectVisibleMarkdownImageGraphicIds(rows.value, {
21121
+ x: rect.x,
21122
+ y: rect.y,
21123
+ w: rect.w,
21124
+ h: rect.h,
21125
+ rowOffset: scrollTop + clipY,
21126
+ clipStart: clipX
21127
+ }).size > 0;
21128
+ }
21129
+ function isClipped() {
21130
+ let rect = normalizedRect(), full = normalizedFullRect();
21131
+ return rect.x !== full.x || rect.y !== full.y || rect.w !== full.w || rect.h !== full.h;
21132
+ }
21133
+ function markScrollDamage(prevTop, nextTop) {
21134
+ let rect = normalizedRect(), delta = nextTop - prevTop;
21135
+ if (rect.h <= 0 || !delta)
21136
+ return;
21137
+ let size = terminal.size();
21138
+ props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && rect.x === 0 && rect.w >= size.cols && rect.y >= 0 && rect.y + rect.h <= size.rows && !isClipped() && Math.abs(delta) < rect.h && !dirtyRowsHint?.length && !visibleGraphicsAt(prevTop) ? (render.unsafeScrollPlaneRows(plane.value, rect.y, rect.y + rect.h, delta), markRowsDirty(exposedRowsForDelta(rect.y, rect.h, delta))) : markRowsDirty(viewportRows());
21139
+ }
20829
21140
  function hasControlledScrollTop() {
20830
21141
  return Object.prototype.hasOwnProperty.call(instance?.vnode.props ?? {}, "scrollTop");
20831
21142
  }
20832
21143
  function applyControlledScrollTop(next, remapSelectionFocus = !1) {
20833
21144
  let desired = Math.floor(Number(next) || 0), clamped = clamp3(desired, 0, maxScrollTop()), changed = internalScrollTop.value !== clamped;
20834
- changed && (internalScrollTop.value = clamped), desired !== clamped && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || remapSelectionFocus) && selection.refresh(remapSelectionFocus ? { remapFocus: !0 } : void 0);
21145
+ changed && (markScrollDamage(internalScrollTop.value, clamped), internalScrollTop.value = clamped), desired !== clamped && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || remapSelectionFocus) && selection.refresh(remapSelectionFocus ? { remapFocus: !0 } : void 0);
20835
21146
  }
20836
21147
  function setScrollTop(next, emitChange = !0, refreshOptions) {
20837
21148
  let desired = Math.floor(Number(next) || 0), clamped = clamp3(desired, 0, maxScrollTop()), changed = internalScrollTop.value !== clamped;
20838
- changed && (internalScrollTop.value = clamped), emitChange && (changed || refreshOptions?.emitClampEvenIfUnchanged && desired !== clamped) && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || refreshOptions?.remapSelectionFocus) && selection.refresh(refreshOptions?.remapSelectionFocus ? { remapFocus: !0 } : void 0);
21149
+ changed && (markScrollDamage(internalScrollTop.value, clamped), internalScrollTop.value = clamped), emitChange && (changed || refreshOptions?.emitClampEvenIfUnchanged && desired !== clamped) && (emit("update:scrollTop", clamped), emit("scroll", clamped)), (changed || refreshOptions?.remapSelectionFocus) && selection.refresh(refreshOptions?.remapSelectionFocus ? { remapFocus: !0 } : void 0);
20839
21150
  }
20840
21151
  function reconcileScrollTop() {
20841
21152
  let desired = hasControlledScrollTop() ? Math.floor(Number(props.scrollTop) || 0) : internalScrollTop.value, clamped = clamp3(desired, 0, maxScrollTop());
@@ -21046,16 +21357,18 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
21046
21357
  keydown: onKeydown
21047
21358
  }
21048
21359
  }));
21049
- return (0, import_vue10.watchEffect)(() => {
21360
+ (0, import_vue10.watchEffect)(() => {
21050
21361
  if (!props.autoFocus || !visible.value)
21051
21362
  return;
21052
21363
  let manager = events.value, nodeId = eventNode.id.value;
21053
21364
  nodeId && manager && manager.getFocused() !== nodeId && manager.focus(nodeId);
21054
21365
  }), (0, import_vue10.onBeforeUnmount)(() => {
21055
21366
  alive = !1, rebuildVersion++, unsubscribeGraphicsOutput(), unsubscribeMathRenderer(), unsubscribeMathImage(), clearMarkdownImageGraphics(terminal, fullRect.value);
21056
- }), useRenderNode(() => ({
21367
+ });
21368
+ let renderNode = useRenderNode(() => ({
21057
21369
  zIndex: props.zIndex,
21058
21370
  rect: visible.value ? normalizedRect() : { x: 0, y: 0, w: 0, h: 0 },
21371
+ dirtyRowsHint,
21059
21372
  deps: [
21060
21373
  visible.value,
21061
21374
  absRect.value,
@@ -21068,13 +21381,25 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
21068
21381
  props.imageOcclusionRects
21069
21382
  ],
21070
21383
  paint: (dirtyRows) => {
21071
- withTextWidthProvider(widthProvider, () => {
21384
+ dirtyRowsHint = void 0, withTextWidthProvider(widthProvider, () => {
21072
21385
  if (!visible.value)
21073
21386
  return;
21074
21387
  let r = normalizedRect();
21075
21388
  if (r.w <= 0 || r.h <= 0)
21076
21389
  return;
21077
- let baseStyle = props.style ?? defaultStyle.value, { x: clipX, y: clipY } = clipOffsets(), isGraphicCovered = (rect) => props.imageOcclusionRects?.some((item) => intersectRect(rect, item)) === !0, keepGraphicIds = collectVisibleMarkdownImageGraphicIds(rows.value, {
21390
+ let baseStyle = props.style ?? defaultStyle.value, { x: clipX, y: clipY } = clipOffsets(), isGraphicCovered = (rect) => props.imageOcclusionRects?.some((item) => intersectRect(rect, item)) === !0, prequeuedGraphicIds = queueClippedVisibleMarkdownImageGraphics(
21391
+ terminal,
21392
+ rows.value,
21393
+ {
21394
+ x: r.x,
21395
+ y: r.y,
21396
+ w: r.w,
21397
+ h: r.h,
21398
+ rowOffset: internalScrollTop.value + clipY,
21399
+ clipStart: clipX,
21400
+ isGraphicCovered
21401
+ }
21402
+ ), keepGraphicIds = collectVisibleMarkdownImageGraphicIds(rows.value, {
21078
21403
  x: r.x,
21079
21404
  y: r.y,
21080
21405
  w: r.w,
@@ -21094,6 +21419,7 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
21094
21419
  baseStyle,
21095
21420
  clear: !0,
21096
21421
  keepGraphicIds,
21422
+ prequeuedGraphicIds,
21097
21423
  isGraphicCovered
21098
21424
  });
21099
21425
  };
@@ -21106,7 +21432,10 @@ var TVirtualMarkdown = (0, import_vue10.defineComponent)({
21106
21432
  paintRow(y);
21107
21433
  });
21108
21434
  }
21109
- })), () => (0, import_vue10.h)("span", rootProps);
21435
+ }));
21436
+ return (0, import_vue10.watchEffect)(() => {
21437
+ renderNodeId = renderNode.id.value;
21438
+ }), () => (0, import_vue10.h)("span", rootProps);
21110
21439
  }
21111
21440
  });
21112
21441