Skip to content

Scale graphics with text and add click-to-enlarge previews - #29

Merged
b451c merged 1 commit into
b451c:mainfrom
arvearve:fix/graphics-scaling-preview
Sep 10, 2026
Merged

Scale graphics with text and add click-to-enlarge previews#29
b451c merged 1 commit into
b451c:mainfrom
arvearve:fix/graphics-scaling-preview

Conversation

@arvearve

@arvearve arvearve commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Embedded images and Mermaid diagrams previously kept fixed dimensions when document text size changed. This change scales graphics and image captions with the text, and lets readers click either graphic type to open a window-filling preview.

Closes #28.

Changes

  • Scale inline graphics from their fitted baseline, preserving aspect ratio and capping them at the document column width. Graphics also shrink when text size decreases in a narrow window.
  • Include text scale and content width in Mermaid snapshot cache keys so cached diagrams cannot restore an outdated size.
  • Present image and Mermaid previews at document-window level, with Escape/Done dismissal and inactive document controls underneath. Preserve Mermaid zoom controls and load a higher-resolution local image thumbnail for the enlarged preview.
  • Add QuickMD/test-image-scaling.md, an image-width regression test, and a standalone WebKit check using the actual Mermaid template.

Validation

  • Local Debug build and all 187 XCTest cases passed:
    xcodebuild -project QuickMD/QuickMD.xcodeproj -scheme QuickMD \
      -configuration Debug -destination 'platform=macOS' \
      CODE_SIGNING_ALLOWED=NO test
  • swift scripts/check-mermaid-scaling.swift passed proportional scaling, narrow-column shrinking, and preview-fit checks. Before the fix, Mermaid remained 356 points wide at 75%, 100%, and 150%; afterward it measured 267, 356, and 534 points.
  • Checked PNG and Mermaid preview opening, dismissal, and Mermaid zoom controls in the local app.

Inline enlargement stops at the column width; clicking opens the preview using the available window space.

b451c added a commit that referenced this pull request Sep 10, 2026
…ocus-ring bleed, themed overlay

- Mermaid: take the snapshot only when the web view's frame matches the
  reported height. A diagram that first rendered below the fold posted its
  height (70 pt) while the un-placed cell still had the 200 pt default frame;
  the 646×200 bitmap (diagram + blank space) was cached under the scale/width
  key and, because #29 seeds `diagramHeight` from `cached.size.height`, every
  re-creation of the block pinned its row at 200 pt. The page's resize
  listener posts again once the frame catches up, and the snapshot fires then.
  Reproduced with log instrumentation, verified fixed on fresh open + scroll.
- Preview: drop first responder before covering the document. AppKit draws
  focus rings above every view, so the sidebar collapse button (first
  responder after launch with keyboard navigation on) kept its ring visible
  through the overlay.
- Preview: document theme background and text colour instead of the system
  background — a dark custom theme under a light appearance no longer opens a
  white panel. `GraphicPreview.diagram` carries the theme.
- Fixture `QuickMD/test-image-scaling.md` moved out of the public tree into
  the local `test-files/` set (repo convention; images live next to it).
- CHANGELOG (Added / Fixed, credit @arvearve #28 #29), README feature line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oPbKHjsi1HB3RWgxxFTKz
@b451c
b451c merged commit 19a9ba1 into b451c:main Sep 10, 2026
3 checks passed
@b451c

b451c commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Merged locally with --no-ff (19a9ba1) and pushed to main - thank you, this is a well-built change: the scale-from-fitted-baseline rule, the cache keys that include scale and width, and the WebKit check script all held up under review and in an end-to-end run on the app (zoom 100 -> 125 -> 100, narrow window, previews via real clicks). Closes #28.

Follow-up on top of it (91aceb9), three things found in that run:

  1. Mermaid snapshot taken before the frame caught up. A diagram that first rendered below the fold posted its height (70 pt) while the not-yet-placed cell still had the 200 pt default frame, so the snapshot was 646x200 (diagram plus blank space). Because the block now seeds diagramHeight from cached.size.height, every later re-creation of that block pinned the row at 200 pt (reproduced with log instrumentation: snapshot 646x200 frame=200 current=70). The coordinator now takes the snapshot only when webView.frame.height matches the reported height; the template's resize listener posts again once the frame catches up, and the snapshot fires then.
  2. Focus ring bleeding through the preview: AppKit draws focus rings above every view, so the sidebar collapse button (first responder after launch with keyboard navigation on) kept its ring visible over the overlay. The document drops first responder before presenting.
  3. The overlay used the system background; it now uses the document theme's background and text colour, so a dark custom theme under a light appearance no longer opens a white panel.

Also moved QuickMD/test-image-scaling.md into the local fixture set (test-files/ is where the manual fixtures live, next to their images) - the WebKit check script stays in scripts/. Will ship in the next release with credit in the CHANGELOG.

b451c added a commit that referenced this pull request Sep 10, 2026
The SVG half of #30 without the WebKit renderer or any vendored library:
the block's markup is handed to NSImage as data and CoreSVG draws it
(`public.svg-image` is a supported NSImage type on every release we
target; scripts and external references in the markup are ignored by the
decoder, non-SVG text yields nil).

- Parser: a ```svg fence (case-insensitive, like ```mermaid) becomes
  `.svgImage(source:)` with id "svg-N".
- `Views/SVGBlockView.swift`: decodes off-main, shows the image scaled with
  the zoom through `BlockLayout.ImageBlock.displayWidth` (never wider than
  the column) but, unlike a bitmap, capped at its own declared size × zoom
  so icons stay icon-sized; click opens the #29 window-filling preview;
  undecodable markup shows a notice.
- `SVGImageDecoder.swift`: the one decode shared by the block and by
  `PrintableSVGView` (print / PDF: a plain SwiftUI `Image`, so ImageRenderer
  draws it as a vector; garbage degrades to the styled code block like a
  failed Mermaid render). Kept out of the view file so the test target,
  which compiles model files only, can exercise it.
- Measurer: `.reported` row seeded like `.image`; anchor signature "s|";
  search skips SVG markup (a hit inside a path could be neither shown nor
  highlighted).
- Tests: parser (svg / SVG fence → block, verbatim markup), decoder
  (declared size, viewBox-only, size-less, inert script, garbage, HTML),
  measurer fixture and kind checks include the new block. 195 tests.
- README (Inline SVG feature line, tree, feature list), CHANGELOG (Added,
  suggested by @arvearve in #30).

Verified in the app (Debug, AX-driven): declared 320×120 at 100 % → 400×150
at 125 %; a 1600-wide viewBox capped at 600 → column width at 125 %; a 24 pt
icon → 30 pt; garbage → notice; linked .svg still renders; preview opens
vector-sharp; PDF export shows the blocks as images and the garbage block
as code.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oPbKHjsi1HB3RWgxxFTKz
b451c added a commit that referenced this pull request Sep 10, 2026
Graphics follow the zoom and open in a window-filling preview (#28/#29
@arvearve), ordered lists share one text edge (#27 @rosekanari), fenced
```svg blocks render natively, the 1.8.0 layout fallback is removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oPbKHjsi1HB3RWgxxFTKz
@b451c

b451c commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Shipped in v1.10.0: https://github.com/b451c/quickmd/releases/tag/v1.10.0 - credited in the CHANGELOG and release notes. Thank you!

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.

Scale embedded graphics with text and add click-to-enlarge previews

2 participants