Preserve formatting in the exported PDF

The printed book is rendered from the same markdown the editor writes, but
markdown-it escaped HTML and did not understand Folio's extensions, so
underlines, text/highlight colors, alignments, ==highlights==, callouts and
wikilinks all showed up as raw source text in the PDF. Render the print book
with a purpose-built print-format renderer that keeps every feature:
  - html: true so the toolbar's <u>, <span style=...> and <div align=...>
    pass through and render instead of appearing literally,
  - ==highlight== rendered as <mark> (new inline rule),
  - Obsidian callouts (> [!note] Title) rendered as styled divs with a bold
    title (new core rule),
  - wikilinks resolved to links via the shared wikilink plugin.
Add matching print styles for mark, underline and callout types, and e2e
assertions that none of these features leak as raw source into #printBook.
This commit is contained in:
avi 2026-08-18 10:59:28 -05:00
commit d510a48742
4 changed files with 232 additions and 14 deletions

View file

@ -484,6 +484,48 @@ const BOOK2_DIR = __BOOKDIR2_VALUE__;
pdfLongRes.bytes > pdfRes.bytes * 2 &&
pdfLongRes.pdfOk === true;
// Formatting must survive into the printed book: markdown-it is configured
// to pass through the toolbar's HTML (<u>, <span style=...>, <div>),
// ==highlight== becomes <mark>, callouts become styled divs, and
// wikilinks resolve to links — none of them may show up as raw source.
const fmtId = (await window.folio.createChapter("Formatting")).id;
await window.folio.saveChapter(
fmtId,
[
"**bold** *italic* ~~strike~~ ==highlight== <u>under</u>",
'<span style="color:#e11d48">red</span> <span style="background-color:#fde047">marked</span>',
"",
"> [!note] Callout title",
"> callout body",
"",
"[[Beta Renamed]]",
].join("\n")
);
await new Promise((r) => setTimeout(r, 500));
document.getElementById("fullBookBtn").click();
await new Promise((r) => setTimeout(r, 400));
const pbInner = document.getElementById("printBook").innerHTML;
const pbText = document.getElementById("printBook").textContent;
out.printFmtBold = /<strong>bold<\/strong>/.test(pbInner);
out.printFmtMark = /<mark>highlight<\/mark>/.test(pbInner);
out.printFmtUnderline = /<u>under<\/u>/.test(pbInner);
out.printFmtColor = /<span style="color:#e11d48">red<\/span>/.test(pbInner);
out.printFmtNoRawEq = !pbText.includes("==highlight==");
out.printFmtCallout = /class="callout callout-note"/.test(pbInner);
out.printFmtNoRawCallout = !pbText.includes("[!note]");
out.printFmtWikilink = /class="wikilink internal"/.test(pbInner);
out.printFmtNoRawWikilink = !pbText.includes("[[Beta Renamed]]");
out.printFmtOk =
out.printFmtBold &&
out.printFmtMark &&
out.printFmtUnderline &&
out.printFmtColor &&
out.printFmtNoRawEq &&
out.printFmtCallout &&
out.printFmtNoRawCallout &&
out.printFmtWikilink &&
out.printFmtNoRawWikilink;
const okFlags = [
"dndMoved",
"kbMoved",
@ -537,6 +579,7 @@ const BOOK2_DIR = __BOOKDIR2_VALUE__;
"printBookHasAllChapters",
"printBookLongFull",
"pdfLongExportOk",
"printFmtOk",
];
out.all = okFlags.every((f) => out[f] === true);
} catch (e) {