Fix DocC code-highlighting regressions and add a SwiftSyntax highlighter#1
Merged
Conversation
A linked inline code span (a class-less <code> inside an <a>) inherited the
neutral inline-code pill, and on themes carrying a bare `code { color: ... }`
rule it also lost the link color outright, so a linked symbol looked identical
to plain code. Add a descendant rule (specificity 0,2,2) that gives the linked
pill the accent color, a visible underline, and an accent-dominant border and
tint, so it reads as a link in every scheme while keeping the pill shape.
The syntax-highlight token colors were all derived from var(--color-accent)
via color-mix, which collapsed to near-monochrome under a strongly saturated
accent: keyword, type, string and number all read as one hue and only comments
stood apart. Decouple the palette into curated, light/dark-aware hues per token
(green strings, teal types, violet numbers, magenta attributes); the keyword
stays the accent as the one brand-tied signal and comments stay muted. Dark
variants flip under [data-theme="dark"], matching the generated token layer.
Every fixed hue is checked for WCAG AA on the code surface in both modes.
The regex highlighter only recognizes keywords, strings, comments, numbers, attributes, and capitalized type names, so DocC code blocks read flat: value references, calls, members, and parameters are all left uncolored. This adds a semantic-near alternative that classifies Swift tokens by their syntactic role, most visibly turning variable references green, for an Xcode-like palette. Introduce a `CodeHighlighting` protocol seam. The zero-dependency regex `CodeHighlighter` remains the default conformer, and the shared `applyToBodyHTML` block-rewriting plumbing moves onto the protocol so every conformer reuses it. `DocCLoader` now holds an injected highlighter (default regex), and `SiteBuilder.docc(…, highlighter:)` exposes the injection point. The SwiftSyntax highlighter lives in its own `SiteKitSyntaxHighlighting` product and target, depending on only `SwiftParser`, `SwiftSyntax`, and `SwiftIDEUtils` (not the macro/compiler-plugin modules). Target-based dependency resolution keeps swift-syntax out of any build that uses only the base `SiteKit` product, so non-DocC sites pay no added build cost. It uses the syntactic classification as a base and refines generic identifiers via a syntax-tree visitor into type, call, variable, member, param, boolean, and label roles; non-Swift snippets fall back to the regex highlighter. Classification is purely syntactic, so all type references share one class (no framework-vs-project split). Seed core `docc.css` with a fixed Apple/Xcode palette for every role class in light and dark, and pin the highlighted code-block surface so the fixed colors keep their WCAG contrast regardless of the site accent.
The SwiftSyntax highlighter colored every capitalized type with the one purple `type` role, so an SDK type and a project's own type looked alike. Xcode instead reads SDK types (ScrollView, ForEach) purple and a project's own types (StickerListItemView, DeleteButton) green. Approximate that split with a committed framework-type allowlist, since isolated DocC snippets carry no symbol graph. A capitalized type whose name is in the allowlist keeps `sk-tok-type`; any other capitalized type becomes the new `sk-tok-projecttype` role (green). The split is applied at every point the type role is assigned (the expression visitors for initializers and bare references, and the base classification for type annotations), so type-position types are split too. The allowlist is a committed Swift literal (1755 names) parsed once into a Set, never re-extracted at build time, so the coloring is reproducible across machines, CI, and consumers regardless of the installed SDK. It covers SwiftUI, SwiftUICore, Foundation, Combine, Swift stdlib and Concurrency, plus curated UIKit, AppKit, and CoreGraphics types so SwiftUI-interop names like UIView and CGRect read as framework types. Sites can extend the set with a new non-breaking init parameter, SwiftSyntaxHighlighter(additionalFrameworkTypes:), to color their own umbrella or design-system types like the SDK. The core docc.css gains a placeholder green for the new role in light and dark.
The WWDCNotes documentation site is now live in production at wwdcnotes.com (built with SiteKit), so the README and DocC-blueprint showcase links, the base-URL doc-comment example, and the BaseURLOverride test fixture now use wwdcnotes.com instead of the staging wwdcnotes.fline.dev host.
Jeehut
commented
Jun 18, 2026
Jeehut
left a comment
Member
Author
There was a problem hiding this comment.
Please note that I also wonder what'll happen to non-Swift code in DocC rendered sites like wwdcnotes.com – they should fallback to the other (previous) highlighting logic, no?
The optional SwiftSyntax highlighter classified capitalized types against a committed 1755-name framework allowlist, rendering SDK types purple (sk-tok-type) and everything else green (sk-tok-projecttype). Resolving every type through a hand-maintained allowlist is large, error-prone, and drifts with each SDK bump. Map every capitalized type (initializer, annotation, or bare reference) to the single sk-tok-type role, matching the regex highlighter. Delete the allowlist file, the additionalFrameworkTypes init parameter, and the sk-tok-projecttype CSS (light and dark). The highlighter keeps the syntactic roles the regex pass cannot produce, above all the green variable references.
HighlighterPreviewGenerator was scaffolding for eyeballing the token palette during the highlighter's colour pass: it wrote a self-contained HTML preview only when an environment variable pointed at an output path. The palette has landed, so the generator is no longer needed in the test target.
applyToBodyHTML located each <pre><code>...</code></pre> block with an NSRegularExpression and rebuilt the result by hand: NSString bridging, manual cursor arithmetic, and NSNotFound group checks. Swap in a Swift Regex literal with named lang and body captures and drive the rewrite through String.replacing(_:with:). The optional lang capture is nil exactly when the class attribute is absent, which folds the NSNotFound and empty-language cases into one expression and drops the cursor bookkeeping. The match semantics are unchanged: the existing applyToBodyHTML tests (tagged, default-language, no-default passthrough, escaping, and the // in a string case) stay green.
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.
Overview
SiteKit's DocC theme had two regressions versus Apple's own DocC rendering, surfaced on wwdcnotes.com: a linked inline
codespan was no longer distinguishable from a plain one, and fenced-code syntax highlighting collapsed to near-monochrome on strongly saturated accent colours. This branch fixes both, and adds an optional SwiftSyntax-based highlighter for sites that want richer, Xcode-like Swift colouring (green variable references, calls, members).Everything here lives inside the SiteKit package (core CSS + a new optional product). Consuming sites (e.g. WWDCNotes) only opt in and bump their pin – no fix code lives downstream.
What changes
<code>renders in the accent colour with an underline, clearly distinct from a plain inline-code pill. (Coredocc.css.)color-mix, which collapsed to near-monochrome on a saturated accent (the reported "colour-poor" regression). They are now a fixed Apple/Xcode-style palette (pink keywords, purple types, red strings, blue numbers, …) on a pinned Apple-near-white code surface, scoped to highlighted DocC blocks so non-DocC output is untouched. This applies to the default regex highlighter, so every DocC site gets it. (Coredocc.css.)SiteKitSyntaxHighlightingproduct) – the default regex highlighter colours keywords/strings/comments/numbers/attributes/capitalised types. This opt-in highlighter additionally classifies Swift tokens by syntactic role via SwiftSyntax, most visibly colouring variable references green (like Xcode), plus calls/members/params. It lives in its own product/target depending only onSwiftParser/SwiftSyntax/SwiftIDEUtils; a consumer using only the baseSiteKitproduct never compiles swift-syntax. The default stays the regex highlighter – you opt in viaSiteBuilder.docc(…, highlighter:).Design
A
CodeHighlightingprotocol abstracts the per-snippet highlighter. The zero-dependency regexCodeHighlighteris the default conformer;DocCLoadertakes an injected highlighter exposed viaSiteBuilder.docc(…, highlighter:). The optionalSwiftSyntaxHighlighteruses SwiftIDEUtils' syntactic classification as a base and refines identifiers via aSyntaxVisitorinto call / member / variable / param / boolean roles from the parse-tree shape. Non-Swift code falls back to the regex highlighter. Classification is purely syntactic (no symbol graph) – it reads token roles, not type ownership, so all type references share one colour.In scope / Out of scope
.docc(highlighter:)opt-in + deploy pin) – a consumer change applied after this is released. The version number / changelog – decided at release time, not in this branch. A possible follow-up: bringing some recognition improvements into the default regex highlighter.Dependency / build cost
swift-syntax (
SwiftParser/SwiftSyntax/SwiftIDEUtilsonly – no macro / compiler-plugin modules) is a dependency of the optionalSiteKitSyntaxHighlightingtarget only. Verified empirically: a consumer depending solely on the baseSiteKitproduct compiles 0 swift-syntax object files (SE-0226 target-based dependency pruning). The build-cost delta (~+30s user-CPU) applies only to sites that opt in.How I verified
swift test: 872 tests / 76 suites green.Regexblock-rewrite was probed by breaking the opening-tag match → tests fail → restored → green.SiteKitproduct builds with 0 swift-syntax object files.Notes for reviewers
CodeHighlighter+ the Apple palette inSources/SiteKit/Resources/DocC/docc.css. The opt-in lives inSources/SiteKitSyntaxHighlighting/;CodeHighlighting.swiftis the seam.