diff --git a/packages/app/src/components/markdown/renderer.test.ts b/packages/app/src/components/markdown/renderer.test.ts index 85b31eed46..c1c19f627d 100644 --- a/packages/app/src/components/markdown/renderer.test.ts +++ b/packages/app/src/components/markdown/renderer.test.ts @@ -146,6 +146,18 @@ it.each([ "Notes\n\nItem | Detail\n:--- | ---:\nA | one", ["Document", "Paragraph", "Table"], ], + [ + "an entity at the start of a header without outer pipes", + "Notes\nAT&T | Detail\n--- | ---\nA | one", + "Notes\n\nAT\\&T | Detail\n--- | ---\nA | one", + ["Document", "Paragraph", "Table"], + ], + [ + "a local image at the start of a header without outer pipes", + "Notes\n![Local](assets/a.png) | Detail\n--- | ---\nA | one", + "Notes\n\nLocal | Detail\n--- | ---\nA | one", + ["Document", "Paragraph", "Table"], + ], [ "CRLF lines", "Notes\r\n| Item |\r\n| --- |\r\n| A |", @@ -205,6 +217,42 @@ it.each([ expect(blocks(await parseMarkdown(rendered, flags))).toEqual(expected); }); +it.each([ + [ + "a literal backslash", + "Notes\\\n| Item |\n| --- |\n| A |", + "Notes\\\n\n| Item |\n| --- |\n| A |", + "Notes\\", + ], + [ + "an entity and literal backslash with LF lines", + "AT&T\\\n| Item |\n| --- |\n| A |", + "AT\\&T\\\n\n| Item |\n| --- |\n| A |", + "AT&T\\", + ], + [ + "an entity and literal backslash with CRLF lines", + "AT&T\\\r\n| Item |\r\n| --- |\r\n| A |", + "AT\\&T\\\r\n\r\n| Item |\r\n| --- |\r\n| A |", + "AT&T\\", + ], + [ + "an entity and literal backslash with CR lines", + "AT&T\\\r| Item |\r| --- |\r| A |", + "AT\\&T\\\r\r| Item |\r| --- |\r| A |", + "AT&T\\", + ], +])( + "preserves paragraph text before an interrupting table in %s", + async (_name, source, separated, text) => { + const rendered = prepareMarkdownSource(source).render(); + expect(rendered).toEqual(separated); + const tree = await parseMarkdown(rendered, { hardSoftBreaks: true, latexMath: false }); + expect(tree.children?.map((node) => node.type)).toEqual(["Paragraph", "Table"]); + expect(tree.children?.[0]?.children?.map((node) => node.content).join("")).toEqual(text); + }, +); + it.each([ "```yaml\n---\nkey: value\n---\n```\n", "~~~md\n| Item |\n| --- |\n| A |\n~~~\n", diff --git a/packages/app/src/components/markdown/source.ts b/packages/app/src/components/markdown/source.ts index 177d571000..c1b13633c6 100644 --- a/packages/app/src/components/markdown/source.ts +++ b/packages/app/src/components/markdown/source.ts @@ -216,7 +216,8 @@ export function prepareMarkdownSource( Math.max(source.lastIndexOf("\n", start - 1), source.lastIndexOf("\r", start - 1)) + 1; const newline = source.slice(lineStart - 2, lineStart).replace(/[^\r\n]/g, ""); const blank = source.slice(lineStart, start).replace(/[^>]/g, " ").trimEnd(); - edits.push({ start: lineStart, end: lineStart, text: `${blank}${newline}` }); + const boundary = lineStart - newline.length; + edits.push({ start: boundary, end: lineStart, text: `${newline}${blank}${newline}` }); } if (node.type === "link") { const title = workspaceHoverTitle(node, source.slice(start, end), workspaceRoot);