Skip to content

Persist a validated preview width preference - #346

Merged
PathGao merged 1 commit into
stack-test/320-checkboxfrom
stack-test/321-width-preference
Aug 2, 2026
Merged

Persist a validated preview width preference#346
PathGao merged 1 commit into
stack-test/320-checkboxfrom
stack-test/321-width-preference

Conversation

@PathGao

@PathGao PathGao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Stack created with GitHub Stacks CLIGive Feedback 💬

@PathGao PathGao changed the title stack test/321 width preference Persist a validated preview width preference Aug 2, 2026
@PathGao
PathGao force-pushed the stack-test/321-width-preference branch from dc75e0a to 7b5b2a4 Compare August 2, 2026 05:53
@PathGao
PathGao force-pushed the stack-test/321-width-preference branch from 7b5b2a4 to acf6878 Compare August 2, 2026 05:54
@PathGao
PathGao marked this pull request as ready for review August 2, 2026 06:07
@PathGao
PathGao force-pushed the stack-test/321-width-preference branch from acf6878 to c384e24 Compare August 2, 2026 08:23
@PathGao
PathGao force-pushed the stack-test/321-width-preference branch from c384e24 to c94c0ad Compare August 2, 2026 16:30
@PathGao
PathGao merged commit 9ba685d into master Aug 2, 2026
10 checks passed
@PathGao
PathGao deleted the stack-test/321-width-preference branch August 2, 2026 18:31
PathGao added a commit that referenced this pull request Aug 6, 2026
`buildExportDocument` wrote `.markdown-body { max-width: 900px }` into
every file the HTML export produced. 900 is not a number the app has
anywhere else: Preview -> Max width (#346-#349, renamed to "Max width" in
#456) is bounded 640-1600 and defaults to 880. So a document read at 640
and a document read at 1600 both left the app at 900, and the one setting
that governs how wide the same document renders everywhere else stopped
at the file dialog. #467 asks for the width to be configurable; it
already is, the export just was not listening.

`exportAsHtml` in MarkdownViewer.svelte now hands the export the value it
already derives for the live preview -- `getPreviewContentWidth(
settings.previewMaxWidth, isFullWidth)`, the same thing that becomes
`--preview-max-width` on the article the user is looking at -- and
`buildExportDocument` interpolates it in place of the constant. One
source of truth, and what leaves the app is the measure it was read at.

Full-width mode is that function's `null`, and it becomes `max-width:
none` rather than the preview's `100%`. The two are equivalent for this
element (`.markdown-body` is a block child of `<body>`, so a percentage
cap resolves to the width it already has), but `none` states the
intention without depending on that reasoning and cannot interact with
`box-sizing`. Checked in a browser on a real exported file: the column
follows the window, `margin: 0 auto` has no slack left to distribute,
and the `padding: 40px !important` still holds the text off the edge.

The number is normalized through `normalizePreviewMaxWidth` at the point
where it stops being a number and becomes a CSS declaration.
`previewMaxWidth` is restored from localStorage, and a corrupted or
hand-edited key must not be able to interpolate itself raw into the
exported stylesheet; an unusable value degrades to the app default the
same way the preview's does.

The print/PDF route is untouched and stays untouched: `@media print` in
styles.css already forces `.markdown-body` to `max-width: 100%
!important` with its own .75in padding, so printing an exported file
never saw the 900 and does not see the setting either. There is a test
for that, because the two routes staying separate is now a property
worth pinning rather than an accident.

scripts/exportContentWidth.test.ts resolves the stylesheet the export
actually emits instead of matching the template that emits it: a
declaration only means something once it is in the `<style>` block, on a
selector the shipped `<article class="markdown-body">` matches, and last
in the cascade. Two of the tests run the real `exportAsHtml` end to end
on the harness exportRichContent.test.ts established and read the bytes
handed to `save_file_content`, with a decoy `max-width: 900px` planted in
the copied stylesheet so the run also answers "does the export's cap win"
and not merely "is it in the file". The one link that cannot be executed
under the Node runner is the call site itself, since it lives in a
`.svelte` component; that is checked against the source of that single
function via `functionSource`.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant