feat(export): Export to PDF — clean-copy print-to-PDF#64
Merged
Conversation
…to PDF…) A one-shot export of the current document to PDF for sharing with people who don't have Quill (PRD §7 backlog item). Two decisions, made with Sam: clean copy only, and the webview print-to-PDF rendering path (reuses the editor's own typography, no second styling pipeline to drift). How it works: - New `File → Export to PDF…` native menu item (Cmd+P), emitting `menu-export-pdf`, wired through App's menu-handler ref like the other File items. The non-native-menu path (dev/e2e) handles Cmd+P too. - `handleExportPdf` sets document.title to the doc's name (so the OS dialog defaults the filename) and calls window.print(); macOS offers "Save as PDF". Title is restored after the (synchronous) dialog. - An `@media print` block in App.css defines the artifact: hide all chrome (toolbar, footer, comment layer, find bar, banners, modals); collapse the height:100vh / overflow:hidden scroll+zoom containers so content reflows and paginates on paper; reset the screen zoom and page-break guide lines. Clean copy of the suggesting-mode markup — insertions render as plain text, pending deletions (<del>) are display:none, and comment/find/focus highlights are stripped. US Letter, 0.75in margins; the OS owns pagination. Docs: PRD §3.5 documents the feature and §7 records review-copy export as a deliberate (revisitable) non-goal; USER_GUIDE gets a one-liner. The printed artifact can't be asserted in CI; verified by build + the full check bar, and needs a manual print-preview pass in the Tauri app. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes the CI gap for Export to PDF: the OS print dialog and the binary PDF can't be driven in CI, but the artifact is defined entirely by the `@media print` rules, so Playwright emulates print media and reads computed styles to assert the clean-copy contract directly. Three specs: app chrome (toolbar/footer/comment layer) goes display:none; a tracked deletion is removed (<del> display:none) while a tracked insertion renders as plain text (no decoration, no background); a comment highlight loses its background and underline. Builds the markup through the real editor (type → suggesting mode → delete/insert; select → comment) rather than fixtures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the Export to PDF for sharing backlog item (PRD §7): a one-shot export of the current document to PDF so it can be shared with people who don't have Quill.
Two design decisions, made with Sam up front:
What's in it
File → Export to PDF…(Cmd+P) — new native menu item emittingmenu-export-pdf, wired throughApp.tsx's menu-handler ref alongside the other File items. The non-native-menu path (dev/e2e) handles Cmd+P too, so it works innpm run dev.handleExportPdfsetsdocument.titleto the document's name (so the OS dialog defaults the filename), callswindow.print(), and restores the title after the synchronous dialog. On macOS the dialog's Save as PDF writes the file.@media printblock inApp.cssdefines the artifact:height:100vh/overflow:hiddenscroll + zoom containers so content reflows and paginates naturally on paper; resets the screen zoom and the dashed page-break guide lines.ins.track-insert→ plain text,del.track-delete→display:none, comment/find/annotation-focus highlights stripped.Docs
Verification
typecheck, eslint, prettier, vitest (255),
cargo fmt/clippy/test(35), andvite buildall green locally.🤖 Generated with Claude Code