@ai-react-markdown/engine 2.4.1 → 2.4.2

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/index.cjs CHANGED
@@ -295,6 +295,10 @@ var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|--
295
295
  var TRUNCATED_TAG_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)([^<>]*)$/;
296
296
  var REF_RE = /!?\[((?:[^[\]\\]|\\.)*)\]/g;
297
297
  var BACKTICK_RUN_RE = /`+/g;
298
+ var MD_BLANK_RE = /^[ \t\r]*$/;
299
+ var isMdBlank = (text) => MD_BLANK_RE.test(text);
300
+ var mdTrim = (text) => text.replace(/^[ \t\r]+|[ \t\r]+$/g, "");
301
+ var mdTrimStart = (text) => text.replace(/^[ \t\r]+/, "");
298
302
  function computeIndent(text) {
299
303
  let indent = 0;
300
304
  for (const ch of text) {
@@ -304,8 +308,25 @@ function computeIndent(text) {
304
308
  }
305
309
  return indent;
306
310
  }
311
+ function firstUnescaped(text, ch) {
312
+ for (let i = 0; i < text.length; i++) {
313
+ if (text[i] === "\\") i += 1;
314
+ else if (text[i] === ch) return i;
315
+ }
316
+ return -1;
317
+ }
318
+ function lastUnclosedBracket(text) {
319
+ let open = -1;
320
+ for (let i = 0; i < text.length; i++) {
321
+ const c = text[i];
322
+ if (c === "\\") i += 1;
323
+ else if (c === "[") open = i;
324
+ else if (c === "]") open = -1;
325
+ }
326
+ return open;
327
+ }
307
328
  function normalizeLabel(label) {
308
- const collapsed = label.trim().replace(/[ \t\r\n]+/g, " ");
329
+ const collapsed = label.replace(/[ \t\r\n]+/g, " ").replace(/^ | $/g, "");
309
330
  return collapsed ? (0, import_micromark_util_normalize_identifier.normalizeIdentifier)(collapsed) : "";
310
331
  }
311
332
  function canBecomeDdLine(text, confirmed) {
@@ -382,6 +403,7 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
382
403
  prevLineWasText: false,
383
404
  prevLineWasValidDef: false,
384
405
  paragraphHasUnpairedRun: false,
406
+ openBracket: null,
385
407
  htmlFlowSinceBlank: false,
386
408
  htmlSeamPending: false,
387
409
  phasePoisonedAt: Infinity,
@@ -389,11 +411,11 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
389
411
  };
390
412
  }
391
413
  function isPlausibleLinkDefRest(rest) {
392
- const t = rest.trim();
414
+ const t = mdTrim(rest);
393
415
  if (t === "") return false;
394
416
  const destEnd = linkDestinationEnd(t);
395
417
  if (destEnd === -1) return false;
396
- const after = t.slice(destEnd).trim();
418
+ const after = mdTrim(t.slice(destEnd));
397
419
  if (after === "") return true;
398
420
  const opener = after[0];
399
421
  if (opener !== '"' && opener !== "'" && opener !== "(") return false;
@@ -403,7 +425,7 @@ function isPlausibleLinkDefRest(rest) {
403
425
  i += 1;
404
426
  continue;
405
427
  }
406
- if (after[i] === closer) return after.slice(i + 1).trim() === "";
428
+ if (after[i] === closer) return isMdBlank(after.slice(i + 1));
407
429
  }
408
430
  return false;
409
431
  }
@@ -440,6 +462,36 @@ function linkDestinationEnd(t) {
440
462
  if (balance !== 0 || i === 0) return -1;
441
463
  return i;
442
464
  }
465
+ function inlineResourceEnd(text, openIdx) {
466
+ let i = openIdx + 1;
467
+ const skipWs = () => {
468
+ while (i < text.length && (text[i] === " " || text[i] === " ")) i += 1;
469
+ };
470
+ skipWs();
471
+ if (text[i] === ")") return i + 1;
472
+ const destEnd = linkDestinationEnd(text.slice(i));
473
+ if (destEnd === -1) return -1;
474
+ i += destEnd;
475
+ const beforeWs = i;
476
+ skipWs();
477
+ if (text[i] === ")") return i + 1;
478
+ if (i === beforeWs) return -1;
479
+ const opener = text[i];
480
+ if (opener !== '"' && opener !== "'" && opener !== "(") return -1;
481
+ const closer = opener === "(" ? ")" : opener;
482
+ for (i += 1; i < text.length; i++) {
483
+ if (text[i] === "\\") {
484
+ i += 1;
485
+ continue;
486
+ }
487
+ if (text[i] === closer) {
488
+ i += 1;
489
+ skipWs();
490
+ return text[i] === ")" ? i + 1 : -1;
491
+ }
492
+ }
493
+ return -1;
494
+ }
443
495
  function classifyBlockStart(text, indent, defListEnabled) {
444
496
  if (indent >= 4) return true;
445
497
  if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
@@ -457,12 +509,13 @@ function computeFreezeBoundary(text, options, resume) {
457
509
  let end = text.indexOf("\n", start);
458
510
  if (end === -1) end = text.length;
459
511
  const confirmed = end < text.length;
460
- const lineText = text.slice(start, end);
512
+ const rawLine = text.slice(start, end);
513
+ const lineText = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
461
514
  const ln = {
462
515
  start,
463
516
  end,
464
517
  text: lineText,
465
- blank: confirmed && lineText.trim() === "",
518
+ blank: confirmed && isMdBlank(lineText),
466
519
  indent: computeIndent(lineText)
467
520
  };
468
521
  if (!confirmed) {
@@ -551,7 +604,7 @@ function processConfirmedLine(cp, ln, text) {
551
604
  const isBlockStart = cp.prevLineBlank;
552
605
  if (cp.htmlSeamPending && !ln.blank && !cp.htmlFlowSinceBlank && !(cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen)) {
553
606
  const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
554
- const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").trim() === "";
607
+ const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
555
608
  if (!defShapedLine && !commentOnly) {
556
609
  cp.htmlSeamPending = false;
557
610
  }
@@ -572,13 +625,14 @@ function processConfirmedLine(cp, ln, text) {
572
625
  const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen;
573
626
  if (cp.inFence) {
574
627
  const close = FENCE_RE.exec(ln.text);
575
- if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && ln.text.trim() === close[1]) {
628
+ if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && isMdBlank(ln.text.slice(close[0].length))) {
576
629
  cp.inFence = false;
577
630
  cp.fenceChar = "";
578
631
  cp.fenceLen = 0;
579
632
  }
580
633
  cp.blankRun = 0;
581
634
  cp.paragraphHasUnpairedRun = false;
635
+ cp.openBracket = null;
582
636
  cp.prevLineBlank = false;
583
637
  cp.prevLineWasText = false;
584
638
  cp.prevLineWasValidDef = false;
@@ -600,6 +654,7 @@ function processConfirmedLine(cp, ln, text) {
600
654
  cp.openIndent = ln.indent;
601
655
  cp.blankRun = 0;
602
656
  cp.paragraphHasUnpairedRun = false;
657
+ cp.openBracket = null;
603
658
  cp.prevLineBlank = false;
604
659
  cp.prevLineWasText = false;
605
660
  cp.prevLineWasValidDef = false;
@@ -608,12 +663,13 @@ function processConfirmedLine(cp, ln, text) {
608
663
  }
609
664
  if (cp.inMath) {
610
665
  const close = MATH_RUN_RE.exec(ln.text);
611
- if (close && close[1].length >= cp.mathFenceLen && ln.text.trim() === close[1]) {
666
+ if (close && close[1].length >= cp.mathFenceLen && isMdBlank(ln.text.slice(close[0].length))) {
612
667
  cp.inMath = false;
613
668
  cp.mathFenceLen = 0;
614
669
  }
615
670
  cp.blankRun = 0;
616
671
  cp.paragraphHasUnpairedRun = false;
672
+ cp.openBracket = null;
617
673
  cp.prevLineBlank = false;
618
674
  cp.prevLineWasText = false;
619
675
  cp.prevLineWasValidDef = false;
@@ -635,6 +691,7 @@ function processConfirmedLine(cp, ln, text) {
635
691
  cp.openIndent = ln.indent;
636
692
  cp.blankRun = 0;
637
693
  cp.paragraphHasUnpairedRun = false;
694
+ cp.openBracket = null;
638
695
  cp.prevLineBlank = false;
639
696
  cp.prevLineWasText = false;
640
697
  cp.prevLineWasValidDef = false;
@@ -658,6 +715,7 @@ function processConfirmedLine(cp, ln, text) {
658
715
  defListSettled: null
659
716
  });
660
717
  cp.paragraphHasUnpairedRun = false;
718
+ cp.openBracket = null;
661
719
  cp.htmlFlowSinceBlank = false;
662
720
  cp.prevLineBlank = true;
663
721
  cp.prevLineWasText = false;
@@ -670,13 +728,13 @@ function processConfirmedLine(cp, ln, text) {
670
728
  } else if (LIST_MARKER_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text) || cp.defListEnabled && DEF_LIST_DD_RE.test(ln.text) || ln.indent >= 4) {
671
729
  cp.hazardVerdict = true;
672
730
  }
673
- const tagStart = ln.indent <= 3 ? /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(ln.text.trimStart()) : null;
731
+ const tagStart = ln.indent <= 3 ? /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(mdTrimStart(ln.text)) : null;
674
732
  if (tagStart) {
675
733
  cp.htmlFlowSinceBlank = true;
676
734
  if (!TYPE6_NAMES.has(tagStart[1].toLowerCase())) cp.hazardVerdict = true;
677
735
  }
678
736
  const inRawText = cp.htmlFlowSinceBlank || rawOpenAtLineStart;
679
- const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(ln.text.trimStart());
737
+ const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(mdTrimStart(ln.text));
680
738
  const { masked, unpaired } = inRawText ? { masked: null, unpaired: false } : maskIntraLineCodeSpans(ln.text, cp.paragraphHasUnpairedRun);
681
739
  if (unpaired) cp.paragraphHasUnpairedRun = true;
682
740
  const scanText = masked ?? ln.text;
@@ -694,28 +752,50 @@ function processConfirmedLine(cp, ln, text) {
694
752
  if (key && !cp.defs.has(key)) cp.defs.set(key, ln.end);
695
753
  }
696
754
  }
697
- if (cp.referenceTaint && scanText.includes("[")) {
698
- const defBracket = validDef ? def.index + def[0].indexOf("[") : -1;
699
- REF_RE.lastIndex = 0;
700
- let m;
701
- while ((m = REF_RE.exec(scanText)) !== null) {
702
- const follow = scanText[m.index + m[0].length];
703
- if (follow === "(") continue;
704
- if (follow === ":" && m.index === defBracket) continue;
705
- const inner = m[1];
755
+ if (cp.referenceTaint) {
756
+ const pushRef = (offset, inner, followAt) => {
757
+ const follow = scanText[followAt];
758
+ if (follow === "(" && inlineResourceEnd(scanText, followAt) !== -1) return;
706
759
  let label;
707
760
  let footnote = false;
708
761
  if (inner.startsWith("^")) {
709
762
  footnote = true;
710
763
  label = normalizeLabel(inner.slice(1));
711
764
  } else if (follow === "[") {
712
- const explicit = /^\[((?:[^[\]\\]|\\.)*)\]/.exec(scanText.slice(m.index + m[0].length));
765
+ const explicit = /^\[((?:[^[\]\\]|\\.)*)\]/.exec(scanText.slice(followAt));
713
766
  label = normalizeLabel(explicit && explicit[1] ? explicit[1] : inner);
714
767
  } else {
715
768
  label = normalizeLabel(inner);
716
769
  }
717
- if (!label) continue;
718
- cp.unresolvedRefs.push({ offset: ln.start + m.index, label, footnote });
770
+ if (label) cp.unresolvedRefs.push({ offset, label, footnote });
771
+ };
772
+ const pending = cp.openBracket;
773
+ cp.openBracket = null;
774
+ if (pending) {
775
+ const close = firstUnescaped(scanText, "]");
776
+ const open = firstUnescaped(scanText, "[");
777
+ const cont = (t) => t.replace(/^ {0,3}>[ \t]?/, "");
778
+ if (close !== -1 && (open === -1 || close < open)) {
779
+ pushRef(pending.offset, `${pending.text}
780
+ ${cont(scanText.slice(0, close))}`, close + 1);
781
+ } else if (close === -1 && open === -1) {
782
+ cp.openBracket = { offset: pending.offset, text: `${pending.text}
783
+ ${cont(scanText)}` };
784
+ }
785
+ }
786
+ if (scanText.includes("[")) {
787
+ const defBracket = validDef ? def.index + def[0].indexOf("[") : -1;
788
+ REF_RE.lastIndex = 0;
789
+ let m;
790
+ while ((m = REF_RE.exec(scanText)) !== null) {
791
+ const followAt = m.index + m[0].length;
792
+ if (scanText[followAt] === ":" && m.index === defBracket) continue;
793
+ pushRef(ln.start + m.index, m[1], followAt);
794
+ }
795
+ const trailingOpen = lastUnclosedBracket(scanText);
796
+ if (trailingOpen !== -1) {
797
+ cp.openBracket = { offset: ln.start + trailingOpen, text: scanText.slice(trailingOpen + 1) };
798
+ }
719
799
  }
720
800
  }
721
801
  const rawSpans = [];
@@ -776,7 +856,7 @@ function processConfirmedLine(cp, ln, text) {
776
856
  if (scanText[pi + 2] === ">") {
777
857
  rawSpans.push([pi, pi + 3]);
778
858
  pos = pi + 3;
779
- if (scanText.slice(0, pi).trim() !== "" || ln.indent > 3) poisonRawDivergence();
859
+ if (!isMdBlank(scanText.slice(0, pi)) || ln.indent > 3) poisonRawDivergence();
780
860
  continue;
781
861
  }
782
862
  rawSpans.push([pi, pi + 2]);
@@ -827,7 +907,7 @@ function processConfirmedLine(cp, ln, text) {
827
907
  applyTag(tag, closing);
828
908
  }
829
909
  if (cp.commentOpen && lastCommentOpenerIdx !== -1 && !inRawText) {
830
- if (tagText.slice(0, lastCommentOpenerIdx).trim() !== "") {
910
+ if (!isMdBlank(tagText.slice(0, lastCommentOpenerIdx))) {
831
911
  cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + lastCommentOpenerIdx);
832
912
  }
833
913
  }
@@ -1053,13 +1133,14 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
1053
1133
  const position = node.position;
1054
1134
  if (position) {
1055
1135
  for (const point of [position.start, position.end]) {
1136
+ if (!point) continue;
1056
1137
  const seg = point.offset !== void 0 && point.offset <= maxEnd ? segments.find((s) => point.offset >= s.injStart && point.offset <= s.injEnd) : void 0;
1057
1138
  if (seg) {
1058
1139
  point.offset += seg.offsetDelta;
1059
- point.line += seg.lineDelta;
1140
+ if (typeof point.line === "number") point.line += seg.lineDelta;
1060
1141
  } else {
1061
1142
  if (point.offset !== void 0) point.offset += offsetDelta;
1062
- point.line += lineDelta;
1143
+ if (typeof point.line === "number") point.line += lineDelta;
1063
1144
  }
1064
1145
  }
1065
1146
  }
@@ -1226,6 +1307,9 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1226
1307
  nextIdx = pairIdx + 1 + stripped;
1227
1308
  const candidate = visibles[nextIdx];
1228
1309
  if (!candidate) return null;
1310
+ if (start === void 0 && sepBuffer.some((sep) => sep.type !== "text" || sep.value !== "\n")) {
1311
+ return null;
1312
+ }
1229
1313
  if (start !== void 0) {
1230
1314
  const cStart = candidate.position?.start?.offset;
1231
1315
  const cEnd = candidate.position?.end?.offset;
@@ -1242,6 +1326,9 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1242
1326
  const trailingGaps = sawContent ? trailingStripped : Math.max(0, visibles.length - 1);
1243
1327
  const seam = visibles.length > 0 && tailWrapVisible ? 1 : 0;
1244
1328
  const last = out[out.length - 1];
1329
+ if (last !== void 0 && last.type === "text" && last.position !== void 0 && last.value.trim() === "") {
1330
+ return null;
1331
+ }
1245
1332
  const lastIsLiteral = last !== void 0 && last.type === "text" && last.value.trim() !== "";
1246
1333
  const litOwnerEnd = pairIdx >= 0 ? visibles[pairIdx].position?.end?.offset : void 0;
1247
1334
  const litEnd = lastIsLiteral ? last.position?.end?.offset : void 0;
@@ -1279,8 +1366,16 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1279
1366
  const v = lastPaired.value;
1280
1367
  const lastLt = v.lastIndexOf("<");
1281
1368
  if (lastLt !== -1 && /^<[!?]/.test(v.slice(lastLt))) return null;
1369
+ const lastOut = out[out.length - 1];
1370
+ const outEnd = lastOut?.type === "element" ? lastOut.position?.end?.offset : void 0;
1371
+ const blockEnd = lastPaired.position?.end?.offset;
1372
+ if (outEnd !== void 0 && blockEnd !== void 0 && outEnd < blockEnd) return null;
1282
1373
  }
1283
1374
  if (sepBuffer.length !== trailingGaps && sepBuffer.length !== trailingGaps + 1) return null;
1375
+ for (let j = pairIdx + 1; j < visibles.length; j++) {
1376
+ const v = visibles[j];
1377
+ if (v.type === "html" && !/^\s*<[!?]/.test(v.value)) return null;
1378
+ }
1284
1379
  for (let i = 0; i < trailingGaps + seam; i++) {
1285
1380
  out.push({ type: "text", value: "\n" });
1286
1381
  }
@@ -1875,6 +1970,7 @@ function createRegistry(onEmpty) {
1875
1970
  }
1876
1971
  },
1877
1972
  contributeLabels(symbol, footnotes, links) {
1973
+ if (!this.chunkOrder.includes(symbol)) return;
1878
1974
  const data = this.chunkData.get(symbol);
1879
1975
  if (data) {
1880
1976
  data.ownFootnoteLabels = footnotes;
@@ -1899,6 +1995,7 @@ function createRegistry(onEmpty) {
1899
1995
  this._notify();
1900
1996
  },
1901
1997
  contributeChunkData(symbol, data) {
1998
+ if (!this.chunkOrder.includes(symbol)) return;
1902
1999
  this.chunkData.set(symbol, data);
1903
2000
  this.labelSet.footnoteLabels = /* @__PURE__ */ new Set();
1904
2001
  this.labelSet.linkLabels = /* @__PURE__ */ new Set();
@@ -2004,14 +2101,16 @@ var import_rehype_unwrap_images = __toESM(require("rehype-unwrap-images"), 1);
2004
2101
  var import_unist_util_visit4 = require("unist-util-visit");
2005
2102
  var IMAGE_TAGS = /* @__PURE__ */ new Set(["img", "cross-chunk-image"]);
2006
2103
  var LINK_TAGS = /* @__PURE__ */ new Set(["a", "cross-chunk-link"]);
2007
- function applicable(node, inLink) {
2104
+ function applicable(node, inLink, seen) {
2008
2105
  let image = 0 /* Unknown */;
2009
2106
  for (const child of node.children) {
2010
2107
  if (child.type === "text" && /^\s*$/.test(child.value)) continue;
2011
2108
  if (child.type === "element" && IMAGE_TAGS.has(child.tagName)) {
2109
+ if (child.tagName !== "img") seen.placeholder = true;
2012
2110
  image = 1 /* ContainsImage */;
2013
2111
  } else if (!inLink && child.type === "element" && LINK_TAGS.has(child.tagName)) {
2014
- const inner = applicable(child, true);
2112
+ if (child.tagName !== "a") seen.placeholder = true;
2113
+ const inner = applicable(child, true, seen);
2015
2114
  if (inner === 2 /* ContainsOther */) return 2 /* ContainsOther */;
2016
2115
  if (inner === 1 /* ContainsImage */) image = 1 /* ContainsImage */;
2017
2116
  } else {
@@ -2023,9 +2122,9 @@ function applicable(node, inLink) {
2023
2122
  function rehypeUnwrapCrossChunkImages() {
2024
2123
  return function transform(tree) {
2025
2124
  (0, import_unist_util_visit4.visit)(tree, "element", (node, index, parent) => {
2026
- if (node.tagName === "p" && parent && typeof index === "number" && applicable(node, false) === 1 /* ContainsImage */ && // Only paragraphs that actually hold a placeholder — plain <img>
2027
- // paragraphs were already unwrapped by rehype-unwrap-images.
2028
- JSON.stringify(node.children).includes('"cross-chunk-image"')) {
2125
+ if (node.tagName !== "p" || !parent || typeof index !== "number") return;
2126
+ const seen = { placeholder: false };
2127
+ if (applicable(node, false, seen) === 1 /* ContainsImage */ && seen.placeholder) {
2029
2128
  parent.children.splice(index, 1, ...node.children);
2030
2129
  return [import_unist_util_visit4.SKIP, index];
2031
2130
  }
@@ -3513,14 +3612,12 @@ function isProtocolAllowed(url, allowed) {
3513
3612
  }
3514
3613
  function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
3515
3614
  rawUrl = (0, import_micromark_util_sanitize_uri2.normalizeUri)(rawUrl);
3516
- const transformed = urlTransform(rawUrl, key, fakeElement(tagName, key, rawUrl));
3517
- if (transformed == null) return "";
3518
- const stringUrl = String(transformed);
3519
- if (stringUrl === "") return "";
3520
3615
  const callerProtocols = schema.protocols;
3521
3616
  const allowed = callerProtocols === void 0 || callerProtocols === null ? sanitizeSchema.protocols?.[key] : callerProtocols[key];
3522
- if (!allowed || allowed.length === 0) return stringUrl;
3523
- return isProtocolAllowed(stringUrl, allowed) ? stringUrl : "";
3617
+ if (allowed && allowed.length > 0 && !isProtocolAllowed(rawUrl, allowed)) return null;
3618
+ const transformed = urlTransform(rawUrl, key, fakeElement(tagName, key, rawUrl));
3619
+ if (transformed == null) return null;
3620
+ return String(transformed);
3524
3621
  }
3525
3622
 
3526
3623
  // src/plugins/defs.ts
@@ -3900,6 +3997,20 @@ var LITERAL_CONTENT_CLOSE_REGEX = {
3900
3997
  math: /<\/math\s*>/gi,
3901
3998
  svg: /<\/svg\s*>/gi
3902
3999
  };
4000
+ function restOfLineIsBlank(content, pos) {
4001
+ for (let i = pos; i < content.length; i++) {
4002
+ const c = content[i];
4003
+ if (c === "\n") return true;
4004
+ if (c !== " " && c !== " " && c !== "\r") return false;
4005
+ }
4006
+ return true;
4007
+ }
4008
+ function lineHasBacktick(content, pos) {
4009
+ for (let i = pos; i < content.length && content[i] !== "\n"; i++) {
4010
+ if (content[i] === "`") return true;
4011
+ }
4012
+ return false;
4013
+ }
3903
4014
  function isAtLineStart(content, pos) {
3904
4015
  let i = pos - 1;
3905
4016
  let spaces = 0;
@@ -3942,7 +4053,7 @@ function splitByProtectedRegions(content) {
3942
4053
  if (multilineStart !== -1) {
3943
4054
  if (char === multilineFenceMarker) {
3944
4055
  const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
3945
- if (runLen >= multilineFenceLength && isAtLineStart(content, i)) {
4056
+ if (runLen >= multilineFenceLength && isAtLineStart(content, i) && restOfLineIsBlank(content, i + runLen)) {
3946
4057
  pushProtected(multilineStart, i + runLen);
3947
4058
  multilineStart = -1;
3948
4059
  multilineFenceMarker = null;
@@ -3958,7 +4069,7 @@ function splitByProtectedRegions(content) {
3958
4069
  }
3959
4070
  if (char === "`" || char === "~") {
3960
4071
  const runLen = getRepeatedMarkerLength(content, i, char);
3961
- if (runLen >= 3 && isAtLineStart(content, i)) {
4072
+ if (runLen >= 3 && isAtLineStart(content, i) && !(char === "`" && lineHasBacktick(content, i + runLen))) {
3962
4073
  multilineStart = i;
3963
4074
  multilineFenceMarker = char;
3964
4075
  multilineFenceLength = runLen;