feat(mac): restore syntax highlighting in AppKit code blocks - #449
Merged
Conversation
Two PRs merged into main on the same day: one added the `requestTimeout(tag:)` case to `T3Error` so a wedged RPC handler cannot pin the UI, and one added `UserFacingError`'s exhaustive switch over `T3Error`. Neither saw the other, so `main` no longer compiles. A request timeout is not a rejected session and not a dead transport — the connection still answers `Ping` — so it gets its own message rather than being folded into the reconnect advice or the generic fallback. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The SwiftUI renderer highlighted fenced code through the vendored HighlightSwift bridge; the AppKit port typeset every fence in `labelColor` and the feature was silently lost. Bring it back on the native path without putting JavaScript anywhere near `configure`. `configure` runs inside `tableView(_:viewFor:)`, so it only schedules: a settle delay collapses a streaming fence's per-delta reconfigurations into a single highlight once the block stops growing, and a generation token — bumped by every configure and reset — drops any result that comes back after the cell has been recycled onto another block. The highlight contributes colors and nothing else. `AppKitCodeHighlight` turns the highlighter's attributed result into UTF-16 foreground spans and refuses to emit any when the returned text no longer matches the block, because highlight.js round trips through generated HTML and one lost character would shift every subsequent range. Applying spans writes `.foregroundColor` over the existing storage, so the string, the font, and `measuredHeight(for:)` are all untouched. Palettes are baked per theme rather than dynamic, so the request carries the view's own `effectiveAppearance` and `viewDidChangeEffectiveAppearance` re-resolves it — the same reason PR #441 moved this view's chrome colors into `updateLayer`. Work stays bounded: unmapped and plaintext fences never enter JavaScript at all (matching the retired path, which did not fall back to automatic detection), and anything above `MarkdownPresentationEngine.maximumCodeCharacters` stays monochrome. `CodeHighlighter` now caches the untranslated AppKit-scoped result and translates to the SwiftUI attribute scope only for its SwiftUI callers, so both renderers share one cache, one language mapping, and one size bound instead of growing a second highlighter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-highlight # Conflicts: # apps/mac/Sources/SurgeCodeMac/Support/UserFacingError.swift
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.
Summary
Code blocks have rendered monochrome since the AppKit port. Highlighting is back, done right for a reusable-cell world:
tableView(_:viewFor:)); a 120 ms settle debounce collapses a streaming fence's per-delta reconfigures into one highlight; a generation token drops results that land on a recycled cell.measuredHeightare byte-identical before/after (test-asserted), so row heights never move.effectiveAppearanceand refresh on appearance change (same pattern as fix(mac): AppKit markdown emphasis/appearance and sidebar selection fixes #441's chrome fix in this file).CodeHighlighternow caches the scope-neutral result and serves AppKit and SwiftUI callers from one cache, one language map, one size bound (4 KB engine cap before anything enters JS, on top of the existing 128 KB cap).New suite AppKitCodeHighlightTests (6 tests: multi-color output, light/dark palettes, stale-generation drop, monochrome fallbacks, mismatched-text rejection, UTF-16/emoji offsets).
Carries the #447 compile fix (byte-identical commit; merges clean either order).
Follow-up noted by the implementer: threading
fragment.isStreamingTailinto the code view's configure would let settled blocks highlight immediately instead of after the 120 ms debounce — deferred to avoid crossing into #448's files.Area
apps/mac— native macOS appapps/windowsapps/mobileapps/serverRelease size
size:XSsize:Ssize:Msize:Lsize:XLVerification
pnpm run verifyafter the last edit (Swift-only diff → full Swift suite): pass🤖 Generated with Claude Code