Three defensive fixes for WKWebView.createPDF() rendering text far
larger than the source HTML's actual font sizes specify:
- Added a viewport meta tag and explicit -webkit-text-size-adjust:
100% — WebKit's shared engine has a text-autosizing heuristic
(normally associated with mobile Safari, but can trigger in WKWebView
contexts too, especially for content loaded via loadHTMLString with
no base URL) that boosts font sizes for perceived readability; this
disables it explicitly rather than relying on it not firing.
- Explicit body font-size (was previously unset, relying on WebKit's
default) and webView.pageZoom = 1.0.
- Resize the webview to the actual rendered content height
(via document.body.scrollHeight) before calling createPDF, instead
of relying on its undocumented auto-sizing against the arbitrary
initial frame — a bounds mismatch here is a known cause of
blown-up/rescaled PDF output.
Dark: added a prefers-color-scheme: dark CSS block, so HTML export
adapts to the browser/OS theme it's later viewed in. PDF is baked at
export time so it can't respond live — instead the offscreen WKWebView
used for PDF rendering has its appearance explicitly set to
NSApp.effectiveAppearance, matching whatever mode the app is in right
now at export time.
Tables: the renderer had no table support at all (previously
documented as an intentional scope cut), so GFM pipe tables were
falling through to the plain-paragraph path and showing up as literal
"| --- | --- |" text. Added detection (a row line immediately followed
by a valid dashes/colons separator row) plus alignment parsing from
the separator's colons.
Top item on the roadmap ranking from 2026-07-27 — multi-modal export
alongside the existing Markdown/JSON. New ConversationExportService
consolidates the two previously-duplicated Markdown builders
(ChatViewModel and ConversationListView had separate copies of the
same **User**/**Assistant** + --- format) and adds:
- A hand-rolled Markdown->HTML renderer scoped to what actually shows
up in chat messages (headers, bold/italic, inline code, fenced code
blocks, lists, blockquotes, links, horizontal rules) rather than
full CommonMark/GFM — no existing markdown-to-HTML utility existed
in the codebase, and swift-markdown-ui is SwiftUI-view-only with no
HTML-string export API. Content is HTML-escaped before any markdown
substitution so example code containing "<div>" etc renders as
visible text, not live markup.
- PDF via an offscreen WKWebView loading that same HTML and calling
the official createPDF(configuration:) API (macOS 11+) — no new
project/framework linkage needed, WebKit is a system framework.
Wired into every place Markdown export already existed: File menu
(Export as HTML.../PDF...), /export slash command (now md|html|pdf|json),
and a new Export submenu (Markdown/HTML/PDF) on each conversation row's
context menu in the advanced conversation list, replacing the old
single-format swipe-only export. Help docs and InputBar autocomplete
updated to match.