From 0ead1213277c7a06021398824a6a4cae473c8797 Mon Sep 17 00:00:00 2001 From: Twest2 Date: Sat, 13 Jun 2026 21:35:55 -0500 Subject: [PATCH] Render rich text, links, and special characters correctly in PDF exports PDF exports now preserve bold/italic/links/lists/blockquotes from the description editor (via a new HTML block/run parser) instead of flattening to plain text. Literal "[text](url)" links inserted by the editor's Link button are converted to real tags before rendering. Tabs and common "smart typography" characters (smart quotes, dashes, ellipsis, bullet) are mapped to their WinAnsiEncoding glyphs instead of rendering as "?". Co-Authored-By: Claude Sonnet 4.6 --- core/htmlblocks.js | 125 ++++++++++++++++++++++++++++++++++++++++ core/pdf.js | 32 +++++++++-- core/renderast.js | 22 ++++--- core/util.js | 15 +++++ exporters/pdf.js | 139 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 313 insertions(+), 20 deletions(-) create mode 100644 core/htmlblocks.js diff --git a/core/htmlblocks.js b/core/htmlblocks.js new file mode 100644 index 0000000..5da76f6 --- /dev/null +++ b/core/htmlblocks.js @@ -0,0 +1,125 @@ +'use strict'; + +const { decodeEntities } = require('./util'); + +/** + * Parse sanitized description HTML (see core/sanitize.js) into a flat list + * of blocks with inline formatting runs, for renderers (PDF) that need to + * preserve bold/italic/links/lists rather than flattening to plain text. + * + * Each block: { type, runs, indent, n? } + * type: 'p' | 'h1'..'h4' | 'blockquote' | 'li' | 'oli' | 'hr' + * runs: [{ text, bold, italic, code, href }] (absent for 'hr') + * indent: list/quote nesting depth (0 = top level) + * n: list item number, only for 'oli' + */ + +const TAG_RE = /<\s*(\/?)\s*([a-zA-Z][a-zA-Z0-9]*)((?:"[^"]*"|'[^']*'|[^>"'])*)>/g; +const HREF_RE = /href\s*=\s*"([^"]*)"|href\s*=\s*'([^']*)'/i; + +function htmlToBlocks(html) { + const blocks = []; + let current = null; + const styleStack = [{}]; + const context = []; // nesting of