fix(print): make an editor-mode PDF export contain the document - #407
Merged
PathGao merged 1 commit intoAug 3, 2026
Merged
Conversation
Exporting to PDF from plain edit mode produced a blank page, from two
independent causes - and fixing either one alone is worse than fixing
neither.
The print sheet hides the editor pane and restores the preview with
`.pane.viewer-pane { width: 100% !important }`, two classes. Svelte scopes
the edit-mode collapse to
`.layout-container:not(.split).editing.svelte-xxx .viewer-pane:where(.svelte-xxx)`,
five. Both carry `!important`, so specificity decides and `width: 0` wins;
`opacity: 0` had no print reset at all, so even a width-only fix prints a
correctly sized blank rectangle. `#app` is the only handle a global sheet
has that outranks a component's scoped selector.
The preview-render effect runs on `tab.isSplit || (isEditing && showToc)`,
so in plain edit mode with the outline closed `tab.content` never updates.
Showing the pane without this yields the document as it was before the
edits - present, stale, and looking like it worked, which is worse than a
blank page.
`syncPreviewForPrint` renders and awaits `renderRichContent` before
printing, skipped in reading mode (that DOM already came from the same
buffer, and re-rendering would discard scroll, fold and find state) and
skipped when the rendered content already matches. A failure toasts rather
than silently exporting a stale document.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PathGao
force-pushed
the
fix/editor-mode-pdf-export
branch
from
August 2, 2026 23:11
e045222 to
f8f8409
Compare
PathGao
added a commit
that referenced
this pull request
Aug 3, 2026
Leaving the editor re-read the file from disk, so a dirty tab had to resolve a save decision - silently write, or answer a modal - before the rendered view could appear. dayeggpi reported this in #168: "no way to see rendered view until file is saved." The prompt was never about losing data. Nothing is lost by switching view mode; the buffer stays in memory either way. It existed because the exit path called `loadMarkdown(tab.path)`, and reading the disk on a dirty tab would show the wrong text. The untitled branch two lines below already rendered the buffer instead - and #407 extracted `renderTabPreviewFromRaw` for the print path, which is exactly the same operation with a real path. Both exits now use it. That also removes three problems the disk read carried: the exit took the 50KB preview branch, so leaving the editor on a large file re-truncated a complete buffer and refused saves until the background read finished; `loadMarkdown` writes into the *active* tab, so `toggleSplitView(tabId)` on a background tab would have yanked the active one; and `if (!success) return` kept the tab in edit mode when the write failed - which for a read-only file or a lossily decoded buffer meant reading mode was permanently unreachable. One segment of that block is kept, narrowed to `autoSave && !confirmBeforeSave`: the auto-save effect treats a tab as writable only while `isEditing || isSplit`, and clears its pending timer otherwise, so leaving edit mode drops the scheduled write. That flush is the last chance before the window closes, not a condition of the switch. Closing a tab and closing a window still ask. Those buffers are about to cease to exist; this one is not. VS Code, Obsidian and Typora all render the buffer, and none of them asks. Co-authored-by: PathGao <gaoyanbo@gaoyanbodeMacBook-Air.local> Co-authored-by: Claude Opus 5 <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.
Exporting to PDF from plain edit mode produced a blank page. Two independent causes — and fixing either one alone is worse than fixing neither.
Cause 1: a specificity fight the print sheet cannot win
The print sheet hides the editor pane and restores the preview with
.pane.viewer-pane { width: 100% !important }— two classes. Svelte scopes the edit-mode collapse to:— five. Both carry
!important, so specificity decides andwidth: 0wins. Andopacity: 0had no print reset at all, so even a width-only fix prints a correctly sized blank rectangle.#app(the root inapp.html) is the only handle a global sheet has that outranks a component's scoped selector.Side effect worth noting: the old
.pane.viewer-pane { flex: none !important }was also losing in reading mode, beaten by the same five-classflex: 1 !important. Harmless there, now correct everywhere.Cause 2: the preview content is stale in edit mode
The preview-render effect runs on
tab.isSplit || (isEditing && settings.showToc), so in plain edit mode with the outline closed,tab.contentnever updates.Showing the pane without fixing this yields the document as it was before the edits — present, stale, and looking like it worked. That is worse than a blank page, which at least announces the failure.
syncPreviewForPrint()renders and awaitsrenderRichContentbefore printing. Skipped in reading mode — that DOM already came fromloadMarkdownon the same buffer, and re-rendering would discard scroll, fold and find state — and skipped when the rendered content already matches. A failure toasts rather than silently exporting a stale document.#382's print work is intact;
exportFoldParity.test.tsstill green.Tests
scripts/editorPdfExport.test.tsresolves the cascade over the real compiled component CSS (svelte/compiler) plusstyles.css, modelling#app,:where()/:not()specificity, and the pane's inlineflex.The three that pass by design are premise anchors: edit mode still hides the pane on screen, the editor still stays off the page, and the effect condition is what the fix assumes.
Not covered
.markdown-containercarrieszoom: 1in edit mode butzoomLevel/100in reading mode, so a PDF from the editor is always 100% while one from reading mode inherits the user's zoom. Left alone.🤖 Generated with Claude Code