@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.js CHANGED
@@ -202,6 +202,10 @@ var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|--
202
202
  var TRUNCATED_TAG_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)([^<>]*)$/;
203
203
  var REF_RE = /!?\[((?:[^[\]\\]|\\.)*)\]/g;
204
204
  var BACKTICK_RUN_RE = /`+/g;
205
+ var MD_BLANK_RE = /^[ \t\r]*$/;
206
+ var isMdBlank = (text) => MD_BLANK_RE.test(text);
207
+ var mdTrim = (text) => text.replace(/^[ \t\r]+|[ \t\r]+$/g, "");
208
+ var mdTrimStart = (text) => text.replace(/^[ \t\r]+/, "");
205
209
  function computeIndent(text) {
206
210
  let indent = 0;
207
211
  for (const ch of text) {
@@ -211,8 +215,25 @@ function computeIndent(text) {
211
215
  }
212
216
  return indent;
213
217
  }
218
+ function firstUnescaped(text, ch) {
219
+ for (let i = 0; i < text.length; i++) {
220
+ if (text[i] === "\\") i += 1;
221
+ else if (text[i] === ch) return i;
222
+ }
223
+ return -1;
224
+ }
225
+ function lastUnclosedBracket(text) {
226
+ let open = -1;
227
+ for (let i = 0; i < text.length; i++) {
228
+ const c = text[i];
229
+ if (c === "\\") i += 1;
230
+ else if (c === "[") open = i;
231
+ else if (c === "]") open = -1;
232
+ }
233
+ return open;
234
+ }
214
235
  function normalizeLabel(label) {
215
- const collapsed = label.trim().replace(/[ \t\r\n]+/g, " ");
236
+ const collapsed = label.replace(/[ \t\r\n]+/g, " ").replace(/^ | $/g, "");
216
237
  return collapsed ? normalizeIdentifier(collapsed) : "";
217
238
  }
218
239
  function canBecomeDdLine(text, confirmed) {
@@ -289,6 +310,7 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
289
310
  prevLineWasText: false,
290
311
  prevLineWasValidDef: false,
291
312
  paragraphHasUnpairedRun: false,
313
+ openBracket: null,
292
314
  htmlFlowSinceBlank: false,
293
315
  htmlSeamPending: false,
294
316
  phasePoisonedAt: Infinity,
@@ -296,11 +318,11 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
296
318
  };
297
319
  }
298
320
  function isPlausibleLinkDefRest(rest) {
299
- const t = rest.trim();
321
+ const t = mdTrim(rest);
300
322
  if (t === "") return false;
301
323
  const destEnd = linkDestinationEnd(t);
302
324
  if (destEnd === -1) return false;
303
- const after = t.slice(destEnd).trim();
325
+ const after = mdTrim(t.slice(destEnd));
304
326
  if (after === "") return true;
305
327
  const opener = after[0];
306
328
  if (opener !== '"' && opener !== "'" && opener !== "(") return false;
@@ -310,7 +332,7 @@ function isPlausibleLinkDefRest(rest) {
310
332
  i += 1;
311
333
  continue;
312
334
  }
313
- if (after[i] === closer) return after.slice(i + 1).trim() === "";
335
+ if (after[i] === closer) return isMdBlank(after.slice(i + 1));
314
336
  }
315
337
  return false;
316
338
  }
@@ -347,6 +369,36 @@ function linkDestinationEnd(t) {
347
369
  if (balance !== 0 || i === 0) return -1;
348
370
  return i;
349
371
  }
372
+ function inlineResourceEnd(text, openIdx) {
373
+ let i = openIdx + 1;
374
+ const skipWs = () => {
375
+ while (i < text.length && (text[i] === " " || text[i] === " ")) i += 1;
376
+ };
377
+ skipWs();
378
+ if (text[i] === ")") return i + 1;
379
+ const destEnd = linkDestinationEnd(text.slice(i));
380
+ if (destEnd === -1) return -1;
381
+ i += destEnd;
382
+ const beforeWs = i;
383
+ skipWs();
384
+ if (text[i] === ")") return i + 1;
385
+ if (i === beforeWs) return -1;
386
+ const opener = text[i];
387
+ if (opener !== '"' && opener !== "'" && opener !== "(") return -1;
388
+ const closer = opener === "(" ? ")" : opener;
389
+ for (i += 1; i < text.length; i++) {
390
+ if (text[i] === "\\") {
391
+ i += 1;
392
+ continue;
393
+ }
394
+ if (text[i] === closer) {
395
+ i += 1;
396
+ skipWs();
397
+ return text[i] === ")" ? i + 1 : -1;
398
+ }
399
+ }
400
+ return -1;
401
+ }
350
402
  function classifyBlockStart(text, indent, defListEnabled) {
351
403
  if (indent >= 4) return true;
352
404
  if (LIST_MARKER_RE.test(text) || FOOTNOTE_DEF_RE.test(text)) return true;
@@ -364,12 +416,13 @@ function computeFreezeBoundary(text, options, resume) {
364
416
  let end = text.indexOf("\n", start);
365
417
  if (end === -1) end = text.length;
366
418
  const confirmed = end < text.length;
367
- const lineText = text.slice(start, end);
419
+ const rawLine = text.slice(start, end);
420
+ const lineText = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
368
421
  const ln = {
369
422
  start,
370
423
  end,
371
424
  text: lineText,
372
- blank: confirmed && lineText.trim() === "",
425
+ blank: confirmed && isMdBlank(lineText),
373
426
  indent: computeIndent(lineText)
374
427
  };
375
428
  if (!confirmed) {
@@ -458,7 +511,7 @@ function processConfirmedLine(cp, ln, text) {
458
511
  const isBlockStart = cp.prevLineBlank;
459
512
  if (cp.htmlSeamPending && !ln.blank && !cp.htmlFlowSinceBlank && !(cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen)) {
460
513
  const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
461
- const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").trim() === "";
514
+ const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
462
515
  if (!defShapedLine && !commentOnly) {
463
516
  cp.htmlSeamPending = false;
464
517
  }
@@ -479,13 +532,14 @@ function processConfirmedLine(cp, ln, text) {
479
532
  const rawOpenAtLineStart = cp.commentOpen || cp.piOpen || cp.declOpen || cp.cdataOpen;
480
533
  if (cp.inFence) {
481
534
  const close = FENCE_RE.exec(ln.text);
482
- if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && ln.text.trim() === close[1]) {
535
+ if (close && close[1][0] === cp.fenceChar && close[1].length >= cp.fenceLen && isMdBlank(ln.text.slice(close[0].length))) {
483
536
  cp.inFence = false;
484
537
  cp.fenceChar = "";
485
538
  cp.fenceLen = 0;
486
539
  }
487
540
  cp.blankRun = 0;
488
541
  cp.paragraphHasUnpairedRun = false;
542
+ cp.openBracket = null;
489
543
  cp.prevLineBlank = false;
490
544
  cp.prevLineWasText = false;
491
545
  cp.prevLineWasValidDef = false;
@@ -507,6 +561,7 @@ function processConfirmedLine(cp, ln, text) {
507
561
  cp.openIndent = ln.indent;
508
562
  cp.blankRun = 0;
509
563
  cp.paragraphHasUnpairedRun = false;
564
+ cp.openBracket = null;
510
565
  cp.prevLineBlank = false;
511
566
  cp.prevLineWasText = false;
512
567
  cp.prevLineWasValidDef = false;
@@ -515,12 +570,13 @@ function processConfirmedLine(cp, ln, text) {
515
570
  }
516
571
  if (cp.inMath) {
517
572
  const close = MATH_RUN_RE.exec(ln.text);
518
- if (close && close[1].length >= cp.mathFenceLen && ln.text.trim() === close[1]) {
573
+ if (close && close[1].length >= cp.mathFenceLen && isMdBlank(ln.text.slice(close[0].length))) {
519
574
  cp.inMath = false;
520
575
  cp.mathFenceLen = 0;
521
576
  }
522
577
  cp.blankRun = 0;
523
578
  cp.paragraphHasUnpairedRun = false;
579
+ cp.openBracket = null;
524
580
  cp.prevLineBlank = false;
525
581
  cp.prevLineWasText = false;
526
582
  cp.prevLineWasValidDef = false;
@@ -542,6 +598,7 @@ function processConfirmedLine(cp, ln, text) {
542
598
  cp.openIndent = ln.indent;
543
599
  cp.blankRun = 0;
544
600
  cp.paragraphHasUnpairedRun = false;
601
+ cp.openBracket = null;
545
602
  cp.prevLineBlank = false;
546
603
  cp.prevLineWasText = false;
547
604
  cp.prevLineWasValidDef = false;
@@ -565,6 +622,7 @@ function processConfirmedLine(cp, ln, text) {
565
622
  defListSettled: null
566
623
  });
567
624
  cp.paragraphHasUnpairedRun = false;
625
+ cp.openBracket = null;
568
626
  cp.htmlFlowSinceBlank = false;
569
627
  cp.prevLineBlank = true;
570
628
  cp.prevLineWasText = false;
@@ -577,13 +635,13 @@ function processConfirmedLine(cp, ln, text) {
577
635
  } 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) {
578
636
  cp.hazardVerdict = true;
579
637
  }
580
- const tagStart = ln.indent <= 3 ? /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(ln.text.trimStart()) : null;
638
+ const tagStart = ln.indent <= 3 ? /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(mdTrimStart(ln.text)) : null;
581
639
  if (tagStart) {
582
640
  cp.htmlFlowSinceBlank = true;
583
641
  if (!TYPE6_NAMES.has(tagStart[1].toLowerCase())) cp.hazardVerdict = true;
584
642
  }
585
643
  const inRawText = cp.htmlFlowSinceBlank || rawOpenAtLineStart;
586
- const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(ln.text.trimStart());
644
+ const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(mdTrimStart(ln.text));
587
645
  const { masked, unpaired } = inRawText ? { masked: null, unpaired: false } : maskIntraLineCodeSpans(ln.text, cp.paragraphHasUnpairedRun);
588
646
  if (unpaired) cp.paragraphHasUnpairedRun = true;
589
647
  const scanText = masked ?? ln.text;
@@ -601,28 +659,50 @@ function processConfirmedLine(cp, ln, text) {
601
659
  if (key && !cp.defs.has(key)) cp.defs.set(key, ln.end);
602
660
  }
603
661
  }
604
- if (cp.referenceTaint && scanText.includes("[")) {
605
- const defBracket = validDef ? def.index + def[0].indexOf("[") : -1;
606
- REF_RE.lastIndex = 0;
607
- let m;
608
- while ((m = REF_RE.exec(scanText)) !== null) {
609
- const follow = scanText[m.index + m[0].length];
610
- if (follow === "(") continue;
611
- if (follow === ":" && m.index === defBracket) continue;
612
- const inner = m[1];
662
+ if (cp.referenceTaint) {
663
+ const pushRef = (offset, inner, followAt) => {
664
+ const follow = scanText[followAt];
665
+ if (follow === "(" && inlineResourceEnd(scanText, followAt) !== -1) return;
613
666
  let label;
614
667
  let footnote = false;
615
668
  if (inner.startsWith("^")) {
616
669
  footnote = true;
617
670
  label = normalizeLabel(inner.slice(1));
618
671
  } else if (follow === "[") {
619
- const explicit = /^\[((?:[^[\]\\]|\\.)*)\]/.exec(scanText.slice(m.index + m[0].length));
672
+ const explicit = /^\[((?:[^[\]\\]|\\.)*)\]/.exec(scanText.slice(followAt));
620
673
  label = normalizeLabel(explicit && explicit[1] ? explicit[1] : inner);
621
674
  } else {
622
675
  label = normalizeLabel(inner);
623
676
  }
624
- if (!label) continue;
625
- cp.unresolvedRefs.push({ offset: ln.start + m.index, label, footnote });
677
+ if (label) cp.unresolvedRefs.push({ offset, label, footnote });
678
+ };
679
+ const pending = cp.openBracket;
680
+ cp.openBracket = null;
681
+ if (pending) {
682
+ const close = firstUnescaped(scanText, "]");
683
+ const open = firstUnescaped(scanText, "[");
684
+ const cont = (t) => t.replace(/^ {0,3}>[ \t]?/, "");
685
+ if (close !== -1 && (open === -1 || close < open)) {
686
+ pushRef(pending.offset, `${pending.text}
687
+ ${cont(scanText.slice(0, close))}`, close + 1);
688
+ } else if (close === -1 && open === -1) {
689
+ cp.openBracket = { offset: pending.offset, text: `${pending.text}
690
+ ${cont(scanText)}` };
691
+ }
692
+ }
693
+ if (scanText.includes("[")) {
694
+ const defBracket = validDef ? def.index + def[0].indexOf("[") : -1;
695
+ REF_RE.lastIndex = 0;
696
+ let m;
697
+ while ((m = REF_RE.exec(scanText)) !== null) {
698
+ const followAt = m.index + m[0].length;
699
+ if (scanText[followAt] === ":" && m.index === defBracket) continue;
700
+ pushRef(ln.start + m.index, m[1], followAt);
701
+ }
702
+ const trailingOpen = lastUnclosedBracket(scanText);
703
+ if (trailingOpen !== -1) {
704
+ cp.openBracket = { offset: ln.start + trailingOpen, text: scanText.slice(trailingOpen + 1) };
705
+ }
626
706
  }
627
707
  }
628
708
  const rawSpans = [];
@@ -683,7 +763,7 @@ function processConfirmedLine(cp, ln, text) {
683
763
  if (scanText[pi + 2] === ">") {
684
764
  rawSpans.push([pi, pi + 3]);
685
765
  pos = pi + 3;
686
- if (scanText.slice(0, pi).trim() !== "" || ln.indent > 3) poisonRawDivergence();
766
+ if (!isMdBlank(scanText.slice(0, pi)) || ln.indent > 3) poisonRawDivergence();
687
767
  continue;
688
768
  }
689
769
  rawSpans.push([pi, pi + 2]);
@@ -734,7 +814,7 @@ function processConfirmedLine(cp, ln, text) {
734
814
  applyTag(tag, closing);
735
815
  }
736
816
  if (cp.commentOpen && lastCommentOpenerIdx !== -1 && !inRawText) {
737
- if (tagText.slice(0, lastCommentOpenerIdx).trim() !== "") {
817
+ if (!isMdBlank(tagText.slice(0, lastCommentOpenerIdx))) {
738
818
  cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start + lastCommentOpenerIdx);
739
819
  }
740
820
  }
@@ -960,13 +1040,14 @@ function rebaseDualWalk(node, segments, maxEnd, offsetDelta, lineDelta) {
960
1040
  const position = node.position;
961
1041
  if (position) {
962
1042
  for (const point of [position.start, position.end]) {
1043
+ if (!point) continue;
963
1044
  const seg = point.offset !== void 0 && point.offset <= maxEnd ? segments.find((s) => point.offset >= s.injStart && point.offset <= s.injEnd) : void 0;
964
1045
  if (seg) {
965
1046
  point.offset += seg.offsetDelta;
966
- point.line += seg.lineDelta;
1047
+ if (typeof point.line === "number") point.line += seg.lineDelta;
967
1048
  } else {
968
1049
  if (point.offset !== void 0) point.offset += offsetDelta;
969
- point.line += lineDelta;
1050
+ if (typeof point.line === "number") point.line += lineDelta;
970
1051
  }
971
1052
  }
972
1053
  }
@@ -1133,6 +1214,9 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1133
1214
  nextIdx = pairIdx + 1 + stripped;
1134
1215
  const candidate = visibles[nextIdx];
1135
1216
  if (!candidate) return null;
1217
+ if (start === void 0 && sepBuffer.some((sep) => sep.type !== "text" || sep.value !== "\n")) {
1218
+ return null;
1219
+ }
1136
1220
  if (start !== void 0) {
1137
1221
  const cStart = candidate.position?.start?.offset;
1138
1222
  const cEnd = candidate.position?.end?.offset;
@@ -1149,6 +1233,9 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1149
1233
  const trailingGaps = sawContent ? trailingStripped : Math.max(0, visibles.length - 1);
1150
1234
  const seam = visibles.length > 0 && tailWrapVisible ? 1 : 0;
1151
1235
  const last = out[out.length - 1];
1236
+ if (last !== void 0 && last.type === "text" && last.position !== void 0 && last.value.trim() === "") {
1237
+ return null;
1238
+ }
1152
1239
  const lastIsLiteral = last !== void 0 && last.type === "text" && last.value.trim() !== "";
1153
1240
  const litOwnerEnd = pairIdx >= 0 ? visibles[pairIdx].position?.end?.offset : void 0;
1154
1241
  const litEnd = lastIsLiteral ? last.position?.end?.offset : void 0;
@@ -1186,8 +1273,16 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1186
1273
  const v = lastPaired.value;
1187
1274
  const lastLt = v.lastIndexOf("<");
1188
1275
  if (lastLt !== -1 && /^<[!?]/.test(v.slice(lastLt))) return null;
1276
+ const lastOut = out[out.length - 1];
1277
+ const outEnd = lastOut?.type === "element" ? lastOut.position?.end?.offset : void 0;
1278
+ const blockEnd = lastPaired.position?.end?.offset;
1279
+ if (outEnd !== void 0 && blockEnd !== void 0 && outEnd < blockEnd) return null;
1189
1280
  }
1190
1281
  if (sepBuffer.length !== trailingGaps && sepBuffer.length !== trailingGaps + 1) return null;
1282
+ for (let j = pairIdx + 1; j < visibles.length; j++) {
1283
+ const v = visibles[j];
1284
+ if (v.type === "html" && !/^\s*<[!?]/.test(v.value)) return null;
1285
+ }
1191
1286
  for (let i = 0; i < trailingGaps + seam; i++) {
1192
1287
  out.push({ type: "text", value: "\n" });
1193
1288
  }
@@ -1782,6 +1877,7 @@ function createRegistry(onEmpty) {
1782
1877
  }
1783
1878
  },
1784
1879
  contributeLabels(symbol, footnotes, links) {
1880
+ if (!this.chunkOrder.includes(symbol)) return;
1785
1881
  const data = this.chunkData.get(symbol);
1786
1882
  if (data) {
1787
1883
  data.ownFootnoteLabels = footnotes;
@@ -1806,6 +1902,7 @@ function createRegistry(onEmpty) {
1806
1902
  this._notify();
1807
1903
  },
1808
1904
  contributeChunkData(symbol, data) {
1905
+ if (!this.chunkOrder.includes(symbol)) return;
1809
1906
  this.chunkData.set(symbol, data);
1810
1907
  this.labelSet.footnoteLabels = /* @__PURE__ */ new Set();
1811
1908
  this.labelSet.linkLabels = /* @__PURE__ */ new Set();
@@ -1911,14 +2008,16 @@ import rehypeUnwrapImages from "rehype-unwrap-images";
1911
2008
  import { SKIP as SKIP3, visit as visit4 } from "unist-util-visit";
1912
2009
  var IMAGE_TAGS = /* @__PURE__ */ new Set(["img", "cross-chunk-image"]);
1913
2010
  var LINK_TAGS = /* @__PURE__ */ new Set(["a", "cross-chunk-link"]);
1914
- function applicable(node, inLink) {
2011
+ function applicable(node, inLink, seen) {
1915
2012
  let image = 0 /* Unknown */;
1916
2013
  for (const child of node.children) {
1917
2014
  if (child.type === "text" && /^\s*$/.test(child.value)) continue;
1918
2015
  if (child.type === "element" && IMAGE_TAGS.has(child.tagName)) {
2016
+ if (child.tagName !== "img") seen.placeholder = true;
1919
2017
  image = 1 /* ContainsImage */;
1920
2018
  } else if (!inLink && child.type === "element" && LINK_TAGS.has(child.tagName)) {
1921
- const inner = applicable(child, true);
2019
+ if (child.tagName !== "a") seen.placeholder = true;
2020
+ const inner = applicable(child, true, seen);
1922
2021
  if (inner === 2 /* ContainsOther */) return 2 /* ContainsOther */;
1923
2022
  if (inner === 1 /* ContainsImage */) image = 1 /* ContainsImage */;
1924
2023
  } else {
@@ -1930,9 +2029,9 @@ function applicable(node, inLink) {
1930
2029
  function rehypeUnwrapCrossChunkImages() {
1931
2030
  return function transform(tree) {
1932
2031
  visit4(tree, "element", (node, index, parent) => {
1933
- if (node.tagName === "p" && parent && typeof index === "number" && applicable(node, false) === 1 /* ContainsImage */ && // Only paragraphs that actually hold a placeholder — plain <img>
1934
- // paragraphs were already unwrapped by rehype-unwrap-images.
1935
- JSON.stringify(node.children).includes('"cross-chunk-image"')) {
2032
+ if (node.tagName !== "p" || !parent || typeof index !== "number") return;
2033
+ const seen = { placeholder: false };
2034
+ if (applicable(node, false, seen) === 1 /* ContainsImage */ && seen.placeholder) {
1936
2035
  parent.children.splice(index, 1, ...node.children);
1937
2036
  return [SKIP3, index];
1938
2037
  }
@@ -3420,14 +3519,12 @@ function isProtocolAllowed(url, allowed) {
3420
3519
  }
3421
3520
  function sanitizeCrossChunkUrl(rawUrl, key, tagName, urlTransform, schema) {
3422
3521
  rawUrl = normalizeUri2(rawUrl);
3423
- const transformed = urlTransform(rawUrl, key, fakeElement(tagName, key, rawUrl));
3424
- if (transformed == null) return "";
3425
- const stringUrl = String(transformed);
3426
- if (stringUrl === "") return "";
3427
3522
  const callerProtocols = schema.protocols;
3428
3523
  const allowed = callerProtocols === void 0 || callerProtocols === null ? sanitizeSchema.protocols?.[key] : callerProtocols[key];
3429
- if (!allowed || allowed.length === 0) return stringUrl;
3430
- return isProtocolAllowed(stringUrl, allowed) ? stringUrl : "";
3524
+ if (allowed && allowed.length > 0 && !isProtocolAllowed(rawUrl, allowed)) return null;
3525
+ const transformed = urlTransform(rawUrl, key, fakeElement(tagName, key, rawUrl));
3526
+ if (transformed == null) return null;
3527
+ return String(transformed);
3431
3528
  }
3432
3529
 
3433
3530
  // src/plugins/defs.ts
@@ -3807,6 +3904,20 @@ var LITERAL_CONTENT_CLOSE_REGEX = {
3807
3904
  math: /<\/math\s*>/gi,
3808
3905
  svg: /<\/svg\s*>/gi
3809
3906
  };
3907
+ function restOfLineIsBlank(content, pos) {
3908
+ for (let i = pos; i < content.length; i++) {
3909
+ const c = content[i];
3910
+ if (c === "\n") return true;
3911
+ if (c !== " " && c !== " " && c !== "\r") return false;
3912
+ }
3913
+ return true;
3914
+ }
3915
+ function lineHasBacktick(content, pos) {
3916
+ for (let i = pos; i < content.length && content[i] !== "\n"; i++) {
3917
+ if (content[i] === "`") return true;
3918
+ }
3919
+ return false;
3920
+ }
3810
3921
  function isAtLineStart(content, pos) {
3811
3922
  let i = pos - 1;
3812
3923
  let spaces = 0;
@@ -3849,7 +3960,7 @@ function splitByProtectedRegions(content) {
3849
3960
  if (multilineStart !== -1) {
3850
3961
  if (char === multilineFenceMarker) {
3851
3962
  const runLen = getRepeatedMarkerLength(content, i, multilineFenceMarker);
3852
- if (runLen >= multilineFenceLength && isAtLineStart(content, i)) {
3963
+ if (runLen >= multilineFenceLength && isAtLineStart(content, i) && restOfLineIsBlank(content, i + runLen)) {
3853
3964
  pushProtected(multilineStart, i + runLen);
3854
3965
  multilineStart = -1;
3855
3966
  multilineFenceMarker = null;
@@ -3865,7 +3976,7 @@ function splitByProtectedRegions(content) {
3865
3976
  }
3866
3977
  if (char === "`" || char === "~") {
3867
3978
  const runLen = getRepeatedMarkerLength(content, i, char);
3868
- if (runLen >= 3 && isAtLineStart(content, i)) {
3979
+ if (runLen >= 3 && isAtLineStart(content, i) && !(char === "`" && lineHasBacktick(content, i + runLen))) {
3869
3980
  multilineStart = i;
3870
3981
  multilineFenceMarker = char;
3871
3982
  multilineFenceLength = runLen;