From a2889310a5d02ca7520db25f097821146e5bdb4a Mon Sep 17 00:00:00 2001 From: PathGao Date: Fri, 31 Jul 2026 15:43:50 +0800 Subject: [PATCH] feat(settings): configure preview content width --- scripts/previewWidth.test.ts | 9 ++++++ src/lib/components/Settings.svelte | 47 ++++++++++++++++++++++++++++-- src/lib/utils/i18n.ts | 4 +++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/scripts/previewWidth.test.ts b/scripts/previewWidth.test.ts index 8634cee..4d56c56 100644 --- a/scripts/previewWidth.test.ts +++ b/scripts/previewWidth.test.ts @@ -12,6 +12,7 @@ import { const settingsSource = readFileSync(new URL('../src/lib/stores/settings.svelte.ts', import.meta.url), 'utf8'); const viewerSource = readFileSync(new URL('../src/lib/MarkdownViewer.svelte', import.meta.url), 'utf8'); +const settingsComponentSource = readFileSync(new URL('../src/lib/components/Settings.svelte', import.meta.url), 'utf8'); test('preview width defaults and clamps persisted numeric values', () => { assert.equal(DEFAULT_PREVIEW_MAX_WIDTH, 880); @@ -47,3 +48,11 @@ test('preview layout derives width and ToC geometry from the same preference', ( assert.match(viewerSource, /--preview-max-width:/); assert.match(viewerSource, /max-width: var\(--preview-max-width, 880px\)/); }); + +test('Settings exposes a bounded preview-width input and reset action', () => { + assert.match(settingsComponentSource, /id="preview-max-width"/); + assert.match(settingsComponentSource, /min=\{MIN_PREVIEW_MAX_WIDTH\}/); + assert.match(settingsComponentSource, /max=\{MAX_PREVIEW_MAX_WIDTH\}/); + assert.match(settingsComponentSource, /bind:value=\{settings\.previewMaxWidth\}/); + assert.match(settingsComponentSource, /settings\.resetPreviewMaxWidth\(\)/); +}); diff --git a/src/lib/components/Settings.svelte b/src/lib/components/Settings.svelte index dddfe64..27bedb9 100644 --- a/src/lib/components/Settings.svelte +++ b/src/lib/components/Settings.svelte @@ -9,6 +9,12 @@ import type { LanguageCode } from '../utils/i18n.js'; import { getEditorToolbarTools } from '../utils/editorToolbar.js'; import { getTitlebarToolbarActions, type TitlebarToolbarPlacement } from '../utils/titlebarToolbar.js'; + import { + DEFAULT_PREVIEW_MAX_WIDTH, + MAX_PREVIEW_MAX_WIDTH, + MIN_PREVIEW_MAX_WIDTH, + normalizePreviewMaxWidth, + } from '../utils/previewWidth.js'; let { show = false, @@ -19,6 +25,10 @@ let activeCategory = $state<'editor' | 'preview' | 'appearance' | 'toolbars' | 'files'>('editor'); let highlightMenuOpen = $state(false); + + function updatePreviewMaxWidth(value: unknown) { + settings.previewMaxWidth = normalizePreviewMaxWidth(value); + } const highlightColors = [ { value: 'default', color: 'var(--color-accent-fg)' }, { value: 'yellow', color: '#ffd000' }, @@ -901,12 +911,43 @@

{t('settings.previewSettings', settings.language)}

+
+ +
+
+ + updatePreviewMaxWidth(settings.previewMaxWidth)} + class="number-input" + style="width: 62px" + /> + +
+ px · {MIN_PREVIEW_MAX_WIDTH}–{MAX_PREVIEW_MAX_WIDTH} · {t('settings.default', settings.language)} {DEFAULT_PREVIEW_MAX_WIDTH} +
+
+
diff --git a/src/lib/utils/i18n.ts b/src/lib/utils/i18n.ts index 01bcb05..a960ca8 100644 --- a/src/lib/utils/i18n.ts +++ b/src/lib/utils/i18n.ts @@ -79,8 +79,10 @@ export const translations: Record = { confirmBeforeSave: 'Ask for confirmation before saving', resetEditorSettings: 'Reset editor settings', resetFontSettings: 'Reset font settings', + resetPreviewSettings: 'Reset preview settings', font: 'Font', fontSize: 'Font Size', + previewMaxWidth: 'Preview max width', wrapColumn: 'Wrap Column', wordWrap: 'Word Wrap', lineNumbers: 'Line Numbers', @@ -417,8 +419,10 @@ export const translations: Record = { appearanceSettings: '外观设置', resetEditorSettings: '重置编辑器设置', resetFontSettings: '重置字体设置', + resetPreviewSettings: '重置预览设置', font: '字体', fontSize: '字体大小', + previewMaxWidth: '预览最大宽度', wrapColumn: '换行列', wordWrap: '自动换行', lineNumbers: '行号',