Skip to content

Carry the theme's link decoration through to the screen - #168

Open
paulscan wants to merge 1 commit into
nodes-app:mainfrom
paulscan:feat/theme-link-text-attributes
Open

Carry the theme's link decoration through to the screen#168
paulscan wants to merge 1 commit into
nodes-app:mainfrom
paulscan:feat/theme-link-text-attributes

Conversation

@paulscan

@paulscan paulscan commented Aug 31, 2026

Copy link
Copy Markdown

Setting MarkdownEditorTheme.link has no visible effect. NSTextView layers its linkTextAttributes over every .link range at display time, on top of whatever foreground the styler set. AppKit's default paints them with .linkColor (system blue). A custom link color gets computed, emitted into [StyledRange], applied to the text storage, and then silently overridden on screen.

An embedder that sets theme.link = .white on a dark canvas still sees a blue link. This makes building color themes difficult.

What's fixed

MarkdownEditorTheme now exposes a computed linkTextAttributes. It carries the theme's link color, a configurable underline style, and the same pointing-hand cursor AppKit's default carries. NativeTextViewWrapper assigns it in makeNSView and refreshes it in updateNSView alongside the existing insertionPointColor refresh.

The theme also controls the underline through MarkdownEditorTheme.linkUnderlineStyle, which defaults to .single. That matches AppKit's stock look. Setting it to [] drops the underline for palettes where it reads as clutter, such as a monospace canvas or a poster-style page.

Passing a theme built with defaults leaves the rendered result pixel-identical to before.

Tests

Tests/MarkdownEngineTests/LinkTextAttributesTests.swift covers:

  • The default theme's attributes match AppKit's stock link look:
    .linkColor, .single underline, pointing-hand cursor.
  • A custom link color reaches the attributes.
  • Setting linkUnderlineStyle to [] or .thick propagates
    through.

swift build and swift test are green.

Setting `MarkdownEditorTheme.link` had no visible effect. `NSTextView`
layers its `linkTextAttributes` over every `.link` range at display time
— on top of whatever foreground the styler set — and AppKit's default
paints them `.linkColor` blue. So a custom link ink was computed,
emitted into `[StyledRange]`, applied to text storage, and then silently
overridden on screen. An embedder with a light body over a dark canvas
that set `theme.link = .white` still got a blue link.

`MarkdownEditorTheme` gains a computed `linkTextAttributes` (theme link
ink + theme underline + pointing-hand cursor — the same decoration
AppKit's default carries), and `NativeTextViewWrapper` assigns it in
`makeNSView` and refreshes it in `updateNSView` alongside the existing
`insertionPointColor` refresh. The theme owns the underline too:
`linkUnderlineStyle` defaults to `.single` (AppKit's stock look), and
`[]` drops it entirely for palettes where an underlined link reads as
clutter (a Mono canvas, a poster-style page). Passing a theme built
with default values leaves the rendered result pixel-identical to
before.

`Tests/MarkdownEngineTests/LinkTextAttributesTests.swift` pins the
three sides: the default theme's attributes match AppKit's stock link
look (`.linkColor` + `.single` underline + pointing-hand cursor), a
custom `link` color reaches the attributes verbatim, and setting
`linkUnderlineStyle` to `[]` or `.thick` propagates through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LNvrf6TPFQ571njp1G98wt
@paulscan
paulscan marked this pull request as ready for review August 31, 2026 00:40
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