1 · Classification – each role in a distinct debug color
Arbitrary, deliberately-distinct colors so every role is visible; proves the
@@ -99,7 +103,8 @@ struct HighlighterPreviewGenerator {
private static let legend: String = {
let roles: [(String, String)] = [
- ("keyword", "struct, var, in"), ("type", "ScrollView, Sticker"), ("call", "lowercase callee"),
+ ("keyword", "struct, var, in"), ("type", "ScrollView, View (framework)"),
+ ("projecttype", "StickerListItemView (project)"), ("call", "lowercase callee"),
("variable", "stickers, sticker (use)"), ("member", ".swipeActions, .id"), ("param", "sticker binding"),
("string", "\"Delete\""), ("number", "12"), ("boolean", "true / nil"),
("attribute", "@State"), ("comment", "// …"), ("operator", "=="), ("label", "spacing:, edge:"),
@@ -129,10 +134,11 @@ struct HighlighterPreviewGenerator {
.chip small { color: #777; }
/* Panel 1 – distinct debug colors (one per role). */
- .debug .sk-tok-keyword { color: #C026D3; font-weight: 700; }
- .debug .sk-tok-type { color: #2563EB; }
- .debug .sk-tok-call { color: #EA580C; }
- .debug .sk-tok-variable { color: #16A34A; font-weight: 600; }
+ .debug .sk-tok-keyword { color: #C026D3; font-weight: 700; }
+ .debug .sk-tok-type { color: #2563EB; }
+ .debug .sk-tok-projecttype { color: #059669; font-weight: 600; }
+ .debug .sk-tok-call { color: #EA580C; }
+ .debug .sk-tok-variable { color: #16A34A; font-weight: 600; }
.debug .sk-tok-member { color: #0D9488; }
.debug .sk-tok-param { color: #CA8A04; }
.debug .sk-tok-string { color: #DC2626; }
@@ -144,10 +150,11 @@ struct HighlighterPreviewGenerator {
.debug .sk-tok-label { color: #9333EA; }
/* Panel 2 – the Apple/Xcode palette that core docc.css ships. call = green. */
- .palette.light .sk-tok-keyword { color: #AD3DA4; font-weight: 600; }
- .palette.light .sk-tok-type { color: #703DAA; }
- .palette.light .sk-tok-call { color: #3C7D3C; }
- .palette.light .sk-tok-variable { color: #3C7D3C; }
+ .palette.light .sk-tok-keyword { color: #AD3DA4; font-weight: 600; }
+ .palette.light .sk-tok-type { color: #703DAA; }
+ .palette.light .sk-tok-projecttype { color: #3C7D3C; }
+ .palette.light .sk-tok-call { color: #3C7D3C; }
+ .palette.light .sk-tok-variable { color: #3C7D3C; }
.palette.light .sk-tok-string { color: #D12F1B; }
.palette.light .sk-tok-number { color: #272AD8; }
.palette.light .sk-tok-boolean { color: #AD3DA4; }
@@ -155,10 +162,11 @@ struct HighlighterPreviewGenerator {
.palette.light .sk-tok-comment { color: #707F8C; font-style: italic; }
/* member / param / operator / label inherit the default text color. */
- .palette.dark .sk-tok-keyword { color: #FF7AB2; font-weight: 600; }
- .palette.dark .sk-tok-type { color: #DABAFF; }
- .palette.dark .sk-tok-call { color: #7FD98A; }
- .palette.dark .sk-tok-variable { color: #7FD98A; }
+ .palette.dark .sk-tok-keyword { color: #FF7AB2; font-weight: 600; }
+ .palette.dark .sk-tok-type { color: #DABAFF; }
+ .palette.dark .sk-tok-projecttype { color: #7FD98A; }
+ .palette.dark .sk-tok-call { color: #7FD98A; }
+ .palette.dark .sk-tok-variable { color: #7FD98A; }
.palette.dark .sk-tok-string { color: #FF8170; }
.palette.dark .sk-tok-number { color: #D9C97C; }
.palette.dark .sk-tok-boolean { color: #FF7AB2; }
diff --git a/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift b/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
index aa3eb56..dbd3b14 100644
--- a/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
+++ b/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
@@ -78,6 +78,72 @@ struct SwiftSyntaxHighlighterTests {
self.expectSpan(result, role: "variable", text: "count")
}
+ // MARK: - Framework-vs-project type split (the committed allowlist heuristic)
+
+ @Test("A framework type stays type (purple) – present in the committed allowlist")
+ func frameworkTypeStaysType() {
+ // `ScrollView` is an SDK type in the committed allowlist, so it keeps the framework `type` role.
+ let code = "ScrollView { Text(title) }"
+ let result = self.highlighter.highlight(code: code, language: "swift")
+ self.expectSpan(result, role: "type", text: "ScrollView")
+ self.expectSpan(result, role: "type", text: "Text")
+ }
+
+ @Test("A project type becomes projecttype (green) – absent from the allowlist")
+ func projectTypeBecomesProjectType() {
+ // `StickerListItemView` is a project-defined type (not in the allowlist), so it splits off the
+ // framework purple into the green `projecttype` role – the headline of this refinement.
+ let code = "StickerListItemView(sticker: sticker)"
+ let result = self.highlighter.highlight(code: code, language: "swift")
+ self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
+ }
+
+ @Test("A type in TYPE position is split too (annotation, not just an initializer)")
+ func typePositionIsSplit() {
+ // The base SwiftIDEUtils pass classifies these as `.type` (not via the expression visitors), so
+ // the split must apply to the base mapping as well: `View` framework→type, `Sticker` project→projecttype.
+ let code = "struct Row: View { var items: [Sticker] = [] }"
+ let result = self.highlighter.highlight(code: code, language: "swift")
+ self.expectSpan(result, role: "type", text: "View")
+ self.expectSpan(result, role: "projecttype", text: "Sticker")
+ }
+
+ @Test("additionalFrameworkTypes promotes a name to the framework type role")
+ func additionalFrameworkTypesPromotesToType() {
+ // A site can color its own umbrella/design-system types like the SDK by passing them in. The
+ // same name that is `projecttype` by default becomes framework `type` once added.
+ let code = "StickerListItemView(sticker: sticker)"
+ let promoting = SwiftSyntaxHighlighter(additionalFrameworkTypes: ["StickerListItemView"])
+ let result = promoting.highlight(code: code, language: "swift")
+ self.expectSpan(result, role: "type", text: "StickerListItemView")
+ }
+
+ @Test("The swipe-actions block splits framework vs project types and keeps values green")
+ func swipeBlockFrameworkVsProjectSplit() {
+ // The representative SwiftUI swipe-actions block: SDK container/iteration types stay purple,
+ // the project's row/button types go green, and the value references stay the headline green.
+ let code = """
+ ScrollView {
+ LazyVStack {
+ ForEach(stickers) { sticker in
+ StickerListItemView(sticker: sticker)
+ .swipeActions {
+ DeleteButton(title: "Delete") { }
+ }
+ }
+ }
+ }
+ """
+ let result = self.highlighter.highlight(code: code, language: "swift")
+ self.expectSpan(result, role: "type", text: "ScrollView")
+ self.expectSpan(result, role: "type", text: "LazyVStack")
+ self.expectSpan(result, role: "type", text: "ForEach")
+ self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
+ self.expectSpan(result, role: "projecttype", text: "DeleteButton")
+ self.expectSpan(result, role: "variable", text: "stickers")
+ self.expectSpan(result, role: "variable", text: "sticker")
+ }
+
// MARK: - Roles taken straight from the base SwiftIDEUtils classification
@Test("Keywords, strings, numbers, comments, and attributes use the base classification")
@@ -107,7 +173,8 @@ struct SwiftSyntaxHighlighterTests {
let result = self.highlighter.highlight(code: code, language: "swift")
#expect(!result.isEmpty)
self.expectSpan(result, role: "variable", text: "stickers")
- self.expectSpan(result, role: "type", text: "StickerListItemView")
+ // `StickerListItemView` is a project type (absent from the framework allowlist) → projecttype.
+ self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
}
@Test("Empty input returns empty output")
From d993ce809899840149ccffd6111fe9182ea607de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cihat=20G=C3=BCnd=C3=BCz?=
Date: Thu, 18 Jun 2026 16:55:57 +0200
Subject: [PATCH 4/7] Point WWDCNotes references to the live wwdcnotes.com
domain
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.
---
Plugin/blueprints/INDEX.md | 2 +-
README.md | 2 +-
Sources/SiteKit/Pipeline/SiteBuilder.swift | 2 +-
Tests/SiteKitTests/BaseURLOverrideTests.swift | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Plugin/blueprints/INDEX.md b/Plugin/blueprints/INDEX.md
index b17133d..073c80d 100644
--- a/Plugin/blueprints/INDEX.md
+++ b/Plugin/blueprints/INDEX.md
@@ -26,7 +26,7 @@ Read `.md` first, then copy files from `/`.
| `Podcast` | Episode pages, audio player, chapters, iTunes RSS | Podcast shows, interview series | [Podcast.md](Podcast.md) | [appstore-tagebuch.de](https://appstore-tagebuch.de) |
| `Newsletter` | Email newsletter with issue archive, signup forms, email rendering | Topic newsletters, curated digests, weekly/monthly roundups | [Newsletter.md](Newsletter.md) | [evolutionkit.dev](https://evolutionkit.dev) |
| `AppLanding` | Single product landing page with hero, features, pricing, reviews | App marketing pages, SaaS products | [AppLanding.md](AppLanding.md) | [translatekit.pages.dev](https://translatekit.pages.dev) |
-| `DocC` | DocC catalog → static, AI-fetchable HTML with a sidebar + full-text search | Documentation sites, API/guide docs | [DocC.md](DocC.md) | [wwdcnotes.fline.dev](https://wwdcnotes.fline.dev) |
+| `DocC` | DocC catalog → static, AI-fetchable HTML with a sidebar + full-text search | Documentation sites, API/guide docs | [DocC.md](DocC.md) | [wwdcnotes.com](https://wwdcnotes.com) |
| `Plain` | Minimal structure, no opinions | Experimentation, custom pipelines | [Plain.md](Plain.md) | – |
---
diff --git a/README.md b/README.md
index 1ed6c82..9e378c0 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ SiteKit ships **9 blueprints** – starter sites you scaffold and customise. Eac
| **Podcast** | Episode pages, audio player, iTunes RSS | [Podcast.md](Plugin/blueprints/Podcast.md) | [appstore-tagebuch.de](https://appstore-tagebuch.de) |
| **Newsletter** | Issue archive, signup forms, email rendering | [Newsletter.md](Plugin/blueprints/Newsletter.md) | [evolutionkit.dev](https://evolutionkit.dev) |
| **AppLanding** | Single product landing page (hero, features, pricing) | [AppLanding.md](Plugin/blueprints/AppLanding.md) | [translatekit.pages.dev](https://translatekit.pages.dev) |
-| **DocC** | DocC catalog → docs site with sidebar + full-text search | [DocC.md](Plugin/blueprints/DocC.md) | [wwdcnotes.fline.dev](https://wwdcnotes.fline.dev) |
+| **DocC** | DocC catalog → docs site with sidebar + full-text search | [DocC.md](Plugin/blueprints/DocC.md) | [wwdcnotes.com](https://wwdcnotes.com) |
| **Plain** | Minimal, no opinions – a blank canvas | [Plain.md](Plugin/blueprints/Plain.md) | – |
Not sure which to pick? The [blueprint catalog](Plugin/blueprints/INDEX.md) has a decision tree and a feature comparison.
diff --git a/Sources/SiteKit/Pipeline/SiteBuilder.swift b/Sources/SiteKit/Pipeline/SiteBuilder.swift
index 17c9760..8d46aaf 100644
--- a/Sources/SiteKit/Pipeline/SiteBuilder.swift
+++ b/Sources/SiteKit/Pipeline/SiteBuilder.swift
@@ -733,7 +733,7 @@ extension SiteBuilder {
enum BaseURLOverrideError: Error, Equatable, CustomStringConvertible {
/// `--base-url` was passed as the last argument, with no value following it.
case missingValue
- /// The value is not an absolute http(s) URL (e.g. `wwdcnotes.fline.dev` without a scheme).
+ /// The value is not an absolute http(s) URL (e.g. `wwdcnotes.com` without a scheme).
case notAnAbsoluteHTTPURL(String)
var description: String {
diff --git a/Tests/SiteKitTests/BaseURLOverrideTests.swift b/Tests/SiteKitTests/BaseURLOverrideTests.swift
index 9a6dc62..cbd37d8 100644
--- a/Tests/SiteKitTests/BaseURLOverrideTests.swift
+++ b/Tests/SiteKitTests/BaseURLOverrideTests.swift
@@ -39,8 +39,8 @@ struct BaseURLOverrideTests {
@Test("Scheme-less value throws instead of silently building broken absolute URLs")
func schemelessValue() {
- #expect(throws: BaseURLOverrideError.notAnAbsoluteHTTPURL("wwdcnotes.fline.dev")) {
- try SiteBuilder.baseURLOverride(from: ["Site", "build", "--base-url", "wwdcnotes.fline.dev"])
+ #expect(throws: BaseURLOverrideError.notAnAbsoluteHTTPURL("wwdcnotes.com")) {
+ try SiteBuilder.baseURLOverride(from: ["Site", "build", "--base-url", "wwdcnotes.com"])
}
}
From 6370ed7be062b60eccc39956661735991835c85d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cihat=20G=C3=BCnd=C3=BCz?=
Date: Thu, 18 Jun 2026 17:37:13 +0200
Subject: [PATCH 5/7] Drop the framework-vs-project type split from the Swift
highlighter
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.
---
Sources/SiteKit/Resources/DocC/docc.css | 21 +-
.../FrameworkTypeAllowlist.swift | 1799 -----------------
.../SwiftSyntaxHighlighter.swift | 42 +-
.../SwiftTokenRoleClassifier.swift | 43 +-
.../SwiftSyntaxHighlighterTests.swift | 55 +-
5 files changed, 49 insertions(+), 1911 deletions(-)
delete mode 100644 Sources/SiteKitSyntaxHighlighting/FrameworkTypeAllowlist.swift
diff --git a/Sources/SiteKit/Resources/DocC/docc.css b/Sources/SiteKit/Resources/DocC/docc.css
index 9b3a3d7..dee169f 100644
--- a/Sources/SiteKit/Resources/DocC/docc.css
+++ b/Sources/SiteKit/Resources/DocC/docc.css
@@ -4138,23 +4138,15 @@ body.sk-docc-shell-body {
font-weight: 600;
}
-/* Framework / known type references: purple. `sk-tok-type` now means a capitalized type whose name is
- in the highlighter's committed framework allowlist (SDK + curated UIKit/AppKit/CoreGraphics/stdlib),
- so `ScrollView` reads purple while a project's own type goes green via sk-tok-projecttype below. */
+/* Type references: purple. Every capitalized type – initializer, annotation, or bare reference –
+ uses this single role, matching the regex highlighter (`ScrollView`, `Text`, and a project's own
+ `StickerListItemView` all read purple). */
.sk-docc-highlight .sk-tok-type {
color: #703DAA;
}
-/* Project (non-framework) type references: green – approximates Xcode, where a project's own
- `StickerListItemView` reads green while SDK types read purple. Placeholder green (matches the
- variable green for now); the exact, distinct-from-variable green is finalised in the colour pass. */
-.sk-docc-highlight .sk-tok-projecttype {
- color: #3C7D3C;
-}
-
-/* Calls: seeded green for "more colour" (it greens project initializers like `StickerListItemView`);
- flip to the type purple for the cleaner look that keeps framework `ForEach` from going green – a
- CSS-only change, no Swift rebuild. */
+/* Free-function calls – a lowercase callee like `print`: green. A capitalized callee is a type
+ initializer and takes the purple `sk-tok-type` above instead. */
.sk-docc-highlight .sk-tok-call {
color: #3C7D3C;
}
@@ -4194,9 +4186,6 @@ body.sk-docc-shell-body {
[data-theme="dark"] .sk-docc-highlight .sk-tok-type {
color: #DABAFF;
}
-[data-theme="dark"] .sk-docc-highlight .sk-tok-projecttype {
- color: #7FD98A;
-}
[data-theme="dark"] .sk-docc-highlight .sk-tok-call {
color: #7FD98A;
}
diff --git a/Sources/SiteKitSyntaxHighlighting/FrameworkTypeAllowlist.swift b/Sources/SiteKitSyntaxHighlighting/FrameworkTypeAllowlist.swift
deleted file mode 100644
index 31db577..0000000
--- a/Sources/SiteKitSyntaxHighlighting/FrameworkTypeAllowlist.swift
+++ /dev/null
@@ -1,1799 +0,0 @@
-import Foundation
-
-/// The committed framework-type allowlist that drives the highlighter's framework-vs-project split.
-///
-/// A capitalized identifier the classifier would mark as a type is looked up here: a name in this set
-/// is a framework / known type and keeps `sk-tok-type` (purple); any other capitalized type is a
-/// project-defined type and becomes `sk-tok-projecttype` (green). This mirrors Xcode, where SDK types
-/// like `ScrollView` read purple while a project's own `StickerListItemView` reads green.
-///
-/// Provenance: extracted once OFFLINE from the installed SDK module `.swiftinterface` public
-/// type-declarations (SwiftUI + SwiftUICore, where `View` / `Text` / `ForEach` actually live, plus
-/// Foundation and Combine), unioned with a curated set of common Swift stdlib / Concurrency, UIKit,
-/// AppKit, and CoreGraphics types (which the SwiftUI/Foundation extraction does not cover, so
-/// `UIView` / `CGRect` would otherwise be misclassified as project types in SwiftUI-interop
-/// snippets). The list is COMMITTED and never re-extracted at build time, so the coloring is
-/// reproducible across machines, CI, and consumers regardless of the SDK installed there. Regenerate
-/// it when bumping the supported SDK / toolchain.
-enum FrameworkTypeAllowlist {
- /// The framework / known-type names. A capitalized type token whose name is in this set renders as
- /// `sk-tok-type`; every other capitalized type renders as `sk-tok-projecttype`. Built once from
- /// `rawList`, so callers pay the parse cost a single time per process.
- static let frameworkTypeNames: Set = Set(
- Self.rawList
- .split(whereSeparator: \.isNewline)
- .lazy
- .map { $0.trimmingCharacters(in: .whitespaces) }
- .filter { !$0.isEmpty }
- )
-
- /// The role class for a capitalized type `name`, given the effective framework set in play (the
- /// committed `frameworkTypeNames`, optionally unioned with a highlighter's `additionalFrameworkTypes`):
- /// `type` for a framework / known type (name in the set), `projecttype` for any other
- /// (project-defined) type. The single decision point for the framework-vs-project split, so the two
- /// assignment sites (the role classifier's expression visitors and the base-classification mapping)
- /// can never disagree on the role strings.
- static func role(forTypeName name: String, in frameworkTypes: Set) -> String {
- frameworkTypes.contains(name) ? "type" : "projecttype"
- }
-
- /// One framework type per line. Kept as a single multi-line string literal (parsed once into the
- /// set above) to avoid both a 1700+-element array-literal compile cost and any resource bundling.
- private static let rawList = """
-AccessibilityActionCategory
-AccessibilityActionKind
-AccessibilityAdjustmentDirection
-AccessibilityAttachmentModifier
-AccessibilityChildBehavior
-AccessibilityCustomContentKey
-AccessibilityDirectTouchOptions
-AccessibilityFocusState
-AccessibilityHeadingLevel
-AccessibilityLabeledPairRole
-AccessibilityQuickActionOutlineStyle
-AccessibilityQuickActionPromptStyle
-AccessibilityQuickActionStyle
-AccessibilityRotorContent
-AccessibilityRotorContentBuilder
-AccessibilityRotorEntry
-AccessibilitySystemRotor
-AccessibilityTechnologies
-AccessibilityTextContentType
-AccessibilityTraits
-AccessibilityZoomGestureAction
-AccessoryBarActionButtonStyle
-AccessoryBarButtonStyle
-AccessoryCircularCapacityGaugeStyle
-AccessoryCircularGaugeStyle
-AccessoryLinearCapacityGaugeStyle
-AccessoryLinearGaugeStyle
-Actions
-ActionSheet
-Actor
-ActorType
-AdaptableTabBarPlacement
-AdaptiveImageGlyphAttribute
-AffineTransform
-AgreementArgumentAttribute
-AgreementConceptAttribute
-Alert
-AlertScene
-AligningContentProviderLayout
-Alignment
-Alignment3D
-AlignmentID
-AlignmentKey
-AlignmentStrategy
-AllCases
-AllSatisfy
-AlternateDescriptionAttribute
-AlternatingRowBackgroundBehavior
-AMPMStyle
-Anchor
-AnchoredLayout
-AnchoredRelativeFormatStyle
-Angle
-Angle2D
-AngularGradient
-Animatable
-AnimatableData
-AnimatableModifier
-AnimatablePair
-AnimatableValues
-Animation
-AnimationCompletionCriteria
-AnimationContext
-AnimationState
-AnimationStateKey
-AnimationTimelineSchedule
-Any
-AnyCancellable
-AnyCompositorContent
-AnyDefinition
-AnyGesture
-AnyGradient
-AnyHashable
-AnyKeyPath
-AnyLayout
-AnyLocation
-AnyLocationBase
-AnyObject
-AnyPublisher
-AnyScrollTargetBehavior
-AnyShape
-AnyShapeStyle
-AnySubscriber
-AnyTabContent
-AnyTransition
-AnyView
-App
-AppStorage
-Argument
-Arithmetic
-ArithmeticOperator
-Array
-ArrayLiteralElement
-ArraySlice
-AssertNoFailure
-Assign
-AssistiveAccess
-AsymmetricTransition
-AsyncBytes
-AsyncCharacterSequence
-AsyncImage
-AsyncImagePhase
-AsyncIterator
-AsyncIteratorProtocol
-AsyncLineSequence
-AsyncMessage
-AsyncPublisher
-AsyncSequence
-AsyncStream
-AsyncThrowingPublisher
-AsyncThrowingStream
-AsyncUnicodeScalarSequence
-AttributeContainer
-AttributeContainerProxy
-Attributed
-AttributedString
-AttributedStringAttributeMutation
-AttributedStringKey
-AttributedStringProtocol
-AttributedStyle
-AttributedSubstring
-AttributedTextFormatting
-AttributedTextFormattingDefinition
-AttributedTextSelection
-AttributedTextValueConstraint
-AttributeDynamicLookup
-AttributeInvalidationCondition
-AttributeMergePolicy
-AttributeRunBoundaries
-Attributes
-AttributeScope
-AttributeScopeCodableConfiguration
-AttributeScopes
-AttributesSlice1
-AttributesSlice2
-AttributesSlice3
-AttributesSlice4
-AttributesSlice5
-Attribution
-Autoconnect
-AutomaticControlGroupStyle
-AutomaticDisclosureGroupStyle
-AutomaticFormStyle
-AutomaticHoverEffect
-AutomaticImmersionStyle
-AutomaticLabeledContentStyle
-AutomaticMenuBarExtraStyle
-AutomaticNavigationSplitViewStyle
-AutomaticNavigationTransition
-AutomaticPresentationSizing
-AutomaticTableStyle
-AutomaticTextEditorStyle
-AXChartDescriptorRepresentable
-Axis
-BackgroundColorAttribute
-BackgroundDisplayMode
-BackgroundProminence
-BackgroundStyle
-BackgroundTask
-BackgroundTaskCancelledReason
-BadgeProminence
-BalancedNavigationSplitViewStyle
-Base64DecodingOptions
-Base64EncodingOptions
-BaselineOffsetAttribute
-BaseMessageIdentifier
-Behavior
-BezierPoint
-BidirectionalCollection
-Bindable
-Binding
-BlendMode
-BlockOperation
-BlurOptions
-BlurReplaceTransition
-Body
-BookmarkCreationOptions
-BookmarkResolutionOptions
-Bool
-BooleanLiteralType
-BorderedButtonMenuStyle
-BorderedButtonStyle
-BorderedListStyle
-BorderedProminentButtonStyle
-BorderedTableStyle
-BorderlessButtonMenuButtonStyle
-BorderlessButtonMenuStyle
-BorderlessButtonStyle
-BorderlessPullDownMenuButtonStyle
-Breakpoint
-Buffer
-BufferingStrategy
-Builder
-Bundle
-BundleDescription
-Button
-ButtonBorderShape
-ButtonMenuStyle
-ButtonRepeatBehavior
-ButtonRole
-ButtonSizing
-ButtonStyle
-ButtonStyleConfiguration
-ButtonToggleStyle
-ByteCount
-ByteCountAttribute
-ByteCountFormatStyle
-ByteCountFormatter
-Cache
-CachePolicy
-Cadence
-CalculationError
-Calendar
-CalendarDayChangedMessage
-Cancellable
-Canvas
-CapitalizationContext
-Capsule
-CardButtonStyle
-CarouselListStyle
-CarouselTabViewStyle
-Case
-CaseIterable
-Catch
-Category
-CGAffineTransform
-CGColor
-CGContext
-CGFloat
-CGGradient
-CGImage
-CGMutablePath
-CGPath
-CGPoint
-CGRect
-CGSize
-CGVector
-Character
-CharacterIndex
-CharacterSet
-CharacterView
-CheckboxToggleStyle
-CheckedContinuation
-CheckpointMessage
-Children
-Chirality
-Circle
-CircularGaugeStyle
-CircularProgressViewStyle
-ClipOptions
-Clock
-ClosedRange
-CocoaError
-Codable
-CodableAttributedStringKey
-CodableConfiguration
-CodableRepresentation
-CodableWithConfiguration
-Code
-CodingKey
-Collation
-Collect
-CollectByCount
-CollectByTime
-Collection
-CollectionContainsCollection
-CollectionIndexSubscript
-CollectionRangeSubscript
-Color
-ColorMatrix
-ColorPicker
-ColorRenderingMode
-Colors
-ColorScheme
-ColorSchemeContrast
-ColorSpace
-ColumnNavigationViewStyle
-ColumnsFormStyle
-CombineIdentifier
-CombineLatest
-CombineLatest3
-CombineLatest4
-CommandGroup
-CommandGroupPlacement
-CommandMenu
-Commands
-CommandsBuilder
-CommonKeyPathKind
-CompactDatePickerStyle
-CompactMap
-CompactMenuControlGroupStyle
-Comparable
-ComparableComparator
-Comparator
-Compared
-CompareOptions
-Comparison
-ComparisonOperator
-Completion
-Component
-ComponentDisplayOption
-ComponentParseStrategy
-Components
-ComponentsFormatStyle
-CompositorContent
-CompositorContentBuilder
-Concatenate
-ConcentricRectangle
-Conditional
-ConditionalCast
-Configuration
-Conjunction
-ConnectablePublisher
-ConnectionAcceptedMessage
-ContainerBackgroundPlacement
-ContainerRelativeShape
-ContainerSizingOptions
-ContainerValueKey
-ContainerValues
-Contains
-ContainsWhere
-Content
-ContentHoverEffect
-ContentMarginPlacement
-ContentMode
-ContentOffset
-ContentShapeKinds
-ContentSizeCategory
-ContentToolbarPlacement
-ContentTransition
-ContentUnavailableView
-Context
-ContextMenu
-ContiguousArray
-ContiguousBytes
-ContinuousClock
-ControlActiveState
-ControlGroup
-ControlGroupStyle
-ControlGroupStyleConfiguration
-ControlSize
-ControlWidget
-ControlWidgetConfiguration
-ControlWidgetConfigurationBuilder
-ControlWidgetTemplate
-ControlWidgetTemplateBuilder
-CookiesChangedMessage
-CoordinateSpace
-CoordinateSpaceProtocol
-Corner
-Count
-CubicKeyframe
-Currency
-CurrencyFormatStyleConfiguration
-CurrentLocaleDidChangeMessage
-CurrentValueLabel
-CurrentValueSubject
-CustomAnimation
-CustomCombineIdentifierConvertible
-CustomDebugStringConvertible
-CustomHoverEffect
-CustomizableToolbarContent
-CustomLocalizedStringResourceConvertible
-CustomNSError
-CustomPresentationDetent
-CustomPronoun
-CustomStringConvertible
-CyclicYear
-Data
-DataAvailableMessage
-DataDecodingStrategy
-DataEncodingStrategy
-DataProtocol
-DataTaskPublisher
-Date
-DateComponents
-DateComponentsFormatter
-DateDecodingStrategy
-DateEncodingStrategy
-DateFieldAttribute
-DateFormatter
-DateInterval
-DateOffset
-DatePicker
-DatePickerComponents
-DatePickerStyle
-DatePickerStyleConfiguration
-DateReference
-DateSeparator
-DateStyle
-DateTimeSeparator
-Day
-DayOfYear
-DayPeriod
-Deallocator
-Debounce
-DebugReplaceableView
-Decimal
-DecimalSeparatorDisplayStrategy
-Decodable
-DecodableAttributedStringKey
-DecodableWithConfiguration
-Decode
-Decoder
-DecodingConfiguration
-DecodingConfigurationProviding
-DefaultButtonLabel
-DefaultButtonStyle
-DefaultDatePickerStyle
-DefaultDateProgressLabel
-DefaultDocumentGroupLaunchActions
-DefaultFocusEvaluationPriority
-DefaultGaugeStyle
-DefaultGlassEffectShape
-DefaultGroupBoxStyle
-DefaultLabelStyle
-DefaultListStyle
-DefaultMenuButtonStyle
-DefaultMenuStyle
-DefaultNavigationViewStyle
-DefaultPickerStyle
-DefaultProgressViewStyle
-DefaultSettingsLinkLabel
-DefaultShareLinkLabel
-DefaultTabLabel
-DefaultTabViewStyle
-DefaultTextFieldStyle
-DefaultToggleStyle
-DefaultToolbarItem
-DefaultWindowStyle
-DefaultWindowToolbarStyle
-DefaultWindowVisibilityToggleLabel
-Deferred
-Definiteness
-DefinitionBuilder
-Delay
-Demand
-DepthAlignment
-DepthAlignmentID
-DepthAlignmentKey
-Description
-DescriptiveNumberFormatConfiguration
-Design
-Determination
-DialogSeverity
-Dictionary
-DictionaryKeyDefaultValueSubscript
-DictionaryKeySubscript
-DidBecomeActiveMessage
-DidBecomeInvalidMessage
-DidChangeMessage
-DidCloseUndoGroupMessage
-DidEnterBackgroundMessage
-DidFinishGatheringMessage
-DidLoadMessage
-DidOpenUndoGroupMessage
-DidRedoChangeMessage
-DidStartGatheringMessage
-DidTerminateMessage
-DidUndoChangeMessage
-DigitalCrownEvent
-DigitalCrownRotationalSensitivity
-Direction
-DirectoryHint
-DisabledTextSelectability
-DisclosureGroup
-DisclosureGroupStyle
-DisclosureGroupStyleConfiguration
-DisclosureTableRow
-DiscontiguousAttributedSubstring
-DiscreteFormatStyle
-Disjunction
-DismissAction
-DismissBehavior
-DismissImmersiveSpaceAction
-DismissSearchAction
-DismissWindowAction
-DispatchGroup
-DispatchQueue
-DispatchSemaphore
-DispatchTime
-DispatchWorkItem
-DisplayProxy
-Divider
-DocumentBaseBox
-DocumentConfiguration
-DocumentGroup
-DocumentGroupLaunchScene
-DocumentLaunchGeometryProxy
-DocumentLaunchView
-Double
-DoubleColumnNavigationViewStyle
-DragConfiguration
-DragDropPreviewsFormation
-DragGesture
-DragSession
-DrawingOptions
-Drop
-DropConfiguration
-DropDelegate
-DropInfo
-DropOperation
-DropProposal
-DropSession
-DropUntilOutput
-DropWhile
-Duration
-DurationFieldAttribute
-DynamicProperty
-DynamicRange
-DynamicTableRowContent
-DynamicTypeSize
-DynamicViewContent
-Edge
-EdgeInsets
-EditableCollectionContent
-EditActions
-EditButton
-EditMode
-Element
-Ellipse
-EllipticalGradient
-EllipticalListStyle
-Empty
-EmptyAnimatableData
-EmptyCommands
-EmptyControlWidgetConfiguration
-EmptyControlWidgetTemplate
-EmptyDefinition
-EmptyHoverEffect
-EmptyHoverEffectContent
-EmptyMatchedTransitionSourceConfiguration
-EmptyModifier
-EmptyTableRowContent
-EmptyView
-EmptyVisualEffect
-EmptyWidgetConfiguration
-EnabledTextSelectability
-Encodable
-EncodableAttributedStringKey
-EncodableWithConfiguration
-Encode
-Encoder
-Encoding
-EncodingConfiguration
-EncodingConfigurationProviding
-EncodingConversionOptions
-End
-Entries
-EnumeratedSequence
-EnumerationOptions
-Environment
-EnvironmentalModifier
-EnvironmentKey
-EnvironmentObject
-EnvironmentValues
-Equal
-Equatable
-EquatableView
-Era
-Error
-ErrorPointer
-ErrorUserInfoKey
-Event
-EventModifiers
-EveryMinuteTimelineSchedule
-ExclusiveGesture
-ExpandedWindowToolbarStyle
-ExplicitTimelineSchedule
-ExpressibleByArrayLiteral
-ExpressibleByDictionaryLiteral
-ExpressibleByIntegerLiteral
-ExpressibleByStringLiteral
-Expression
-ExpressionEvaluate
-ExtendedGraphemeClusterLiteralType
-Fail
-Failure
-FailurePolicy
-FetchedResults
-FetchRequest
-Field
-FieldDatePickerStyle
-FileDialogBrowserOptions
-FileDocument
-FileDocumentConfiguration
-FileDocumentReadConfiguration
-FileDocumentWriteConfiguration
-FileHandle
-FileManager
-FileWrapper
-FillShapeStyle
-FillShapeView
-FillStyle
-Filter
-FilterOptions
-FindContext
-First
-FirstWhere
-FittedPresentationSizing
-FixedTextVariant
-FlatMap
-Flexibility
-Float
-Float16
-FloatDivision
-FloatingPointFormatStyle
-FloatingPointParseStrategy
-FloatLiteralType
-FocusedBinding
-FocusedObject
-FocusedValue
-FocusedValueKey
-FocusedValues
-FocusInteractions
-FocusState
-Font
-FontAttribute
-ForceCast
-ForcedUnwrap
-ForEach
-ForEachSectionCollection
-ForEachSubviewCollection
-ForegroundColorAttribute
-ForegroundStyle
-Form
-FormatInput
-FormatOutput
-FormatString
-FormatStyle
-FormatStyleCapitalizationContext
-FormattingOptions
-FormPresentationSizing
-FormStyle
-FormStyleConfiguration
-FoundationAttributes
-FractionalPartDisplayStrategy
-FrameResizeDirection
-FrameResizePosition
-Frequency
-FullImmersionStyle
-Future
-Gauge
-GaugeStyle
-GaugeStyleConfiguration
-GeometryEffect
-GeometryProxy
-GeometryReader
-GeometryReader3D
-Gesture
-GestureMask
-GestureState
-GestureStateGesture
-Glass
-GlassButtonStyle
-GlassEffectContainer
-GlassEffectTransition
-GlassProminentButtonStyle
-GlobalActor
-GlobalCoordinateSpace
-Gradient
-GradientOptions
-GrammaticalCase
-GrammaticalGender
-GrammaticalNumber
-GrammaticalPerson
-GraphicalDatePickerStyle
-GraphicsContext
-Grid
-GridItem
-GridLayout
-GridRow
-Group
-GroupBox
-GroupBoxStyle
-GroupBoxStyleConfiguration
-GroupedFormStyle
-GroupedListStyle
-GroupedTabViewStyle
-GroupElementsOfContent
-GroupHoverEffect
-Grouping
-GroupSectionsOfContent
-HandGestureShortcut
-HandleEvents
-Hashable
-Hasher
-HelpLink
-HiddenTitleBarWindowStyle
-HierarchicalShapeStyle
-HierarchicalShapeStyleModifier
-HighlightHoverEffect
-HorizontalAlignment
-HorizontalDirection
-HorizontalEdge
-HostDisplayOption
-HostingSheetRepresentation
-Hour
-HourCycle
-HoverEffect
-HoverEffectContent
-HoverEffectGroup
-HoverEffectPhaseOverride
-HoverPhase
-HSplitView
-HStack
-HStackLayout
-HTTPFormatStyle
-HTTPURLResponse
-Icon
-IconOnlyLabelStyle
-ID
-Identifiable
-Identifier
-IdentifierType
-IdentityTransition
-IgnoreOutput
-Image
-ImagePaint
-ImageRenderer
-ImageURLAttribute
-ImmediateScheduler
-ImmersionChangeContext
-ImmersionStyle
-ImmersiveContentBrightness
-ImmersiveEnvironmentBehavior
-ImmersiveSpace
-ImmersiveSpaceContent
-ImmersiveSpaceContentBuilder
-ImmersiveSpaceViewContent
-ImportFromDevicesCommands
-Index
-IndexDisplayMode
-IndexedIdentifierCollection
-IndexPath
-IndexSet
-IndexViewStyle
-Indices
-InflectionAlternativeAttribute
-InflectionConcept
-InflectionRule
-InflectionRuleAttribute
-InlinePickerStyle
-InlinePresentationIntentAttribute
-Input
-InputDevicePose
-InsetGroupedListStyle
-InsetListStyle
-InsetShape
-InsettableShape
-InsetTableStyle
-InspectorCommands
-Instant
-InstantProtocol
-Int
-Int16
-Int32
-Int64
-Int8
-IntDivision
-IntegerFormatStyle
-IntegerLiteralType
-IntegerParseStrategy
-IntentType
-InterfaceOrientation
-Interpolation
-InterpolationOptions
-InterpretedSyntax
-IntervalFormatStyle
-IntRemainder
-ISO8601DateFormatter
-ISO8601FormatStyle
-ItemProviderTableRowModifier
-Iterator
-IteratorProtocol
-JSONDecoder
-JSONEncoder
-JSONSerialization
-Just
-KerningAttribute
-Key
-KeyboardShortcut
-KeyDecodingStrategy
-KeyEncodingStrategy
-KeyEquivalent
-Keyframe
-KeyframeAnimator
-Keyframes
-KeyframesBuilder
-KeyframeTimeline
-KeyframeTrack
-KeyframeTrackContent
-KeyframeTrackContentBuilder
-KeyPath
-KeyPathComparator
-KeyPress
-KeyValueObservingPublisher
-Kind
-Label
-LabeledContent
-LabeledContentStyle
-LabeledContentStyleConfiguration
-LabeledControlGroupContent
-LabeledToolbarItemGroupContent
-LabelStyle
-LabelStyleConfiguration
-Language
-LanguageCode
-LanguageDirection
-LanguageIdentifierAttribute
-Last
-LastWhere
-Layout
-LayoutDirection
-LayoutDirectionBehavior
-LayoutKey
-LayoutProperties
-LayoutSubview
-LayoutSubviews
-LayoutValueKey
-LazyFilterSequence
-LazyHGrid
-LazyHStack
-LazyMapSequence
-LazySequence
-LazyVGrid
-LazyVStack
-Leading
-LegibilityWeight
-LiftHoverEffect
-LimitBehavior
-LimitedAvailabilityConfiguration
-Line
-LinearCapacityGaugeStyle
-LinearGaugeStyle
-LinearGradient
-LinearKeyframe
-LinearProgressViewStyle
-LineStyle
-Link
-LinkAttribute
-LinkButtonStyle
-LinkShapeStyle
-List
-ListFormatStyle
-ListItemDelimiterAttribute
-ListItemTint
-ListSectionSpacing
-ListStyle
-ListType
-LocalCoordinateSpace
-Locale
-Localization
-LocalizationOptions
-LocalizationValue
-LocalizedDateArgumentAttribute
-LocalizedDateIntervalArgumentAttribute
-LocalizedError
-LocalizedNumberFormatAttribute
-LocalizedNumericArgumentAttribute
-LocalizedStringArgumentAttributes
-LocalizedStringKey
-LocalizedStringResource
-LocalizedURLArgumentAttribute
-LocalSession
-Locations
-Logger
-LongPressGesture
-LosslessStringConvertible
-LowDiskSpaceMessage
-MachError
-MagnificationGesture
-MagnifyGesture
-Magnitude
-Main
-MainActor
-MainActorMessage
-MakeConnectable
-ManagedBuffer
-Map
-MapError
-MapKeyPath
-MapKeyPath2
-MapKeyPath3
-MarkdownDecodableAttributedStringKey
-MarkdownParsingOptions
-MarkdownSourcePosition
-MarkdownSourcePositionAttribute
-MarkedValueLabel
-MatchedGeometryEffect
-MatchedGeometryProperties
-MatchedTransitionSourceConfiguration
-MatchingPolicy
-Material
-MaterialActiveAppearance
-MaximumValueLabel
-MeasureInterval
-Measurement
-MeasurementAttribute
-MeasurementFormatUnitUsage
-MeasurementSystem
-Menu
-MenuActionDismissBehavior
-MenuBarExtra
-MenuBarExtraStyle
-MenuButton
-MenuButtonStyle
-MenuControlGroupStyle
-MenuOrder
-MenuPickerStyle
-MenuStyle
-MenuStyleConfiguration
-Merge
-Merge3
-Merge4
-Merge5
-Merge6
-Merge7
-Merge8
-MergeMany
-MeshGradient
-Message
-MessageIdentifier
-MinimumValueLabel
-Minute
-Mirror
-MixedImmersionStyle
-ModifiedContent
-Month
-Morphology
-MorphologyAttribute
-MoveCommandDirection
-MoveKeyframe
-MoveTransition
-Multicast
-MultiDatePicker
-MultiViewRoot
-MutableCollection
-MutableDataProtocol
-MutableURLRequest
-Name
-NamedCoordinateSpace
-Namespace
-NameStyle
-NavigationBarDrawerDisplayMode
-NavigationBarItem
-NavigationControlGroupStyle
-NavigationLink
-NavigationLinkPickerStyle
-NavigationPath
-NavigationSplitView
-NavigationSplitViewColumn
-NavigationSplitViewStyle
-NavigationSplitViewStyleConfiguration
-NavigationSplitViewVisibility
-NavigationStack
-NavigationTransition
-NavigationView
-NavigationViewStyle
-Negation
-NetworkServiceType
-NetworkUnavailableReason
-Never
-NewDocumentAction
-NewDocumentButton
-NilCoalesce
-NilLiteral
-NonConformingFloatDecodingStrategy
-NonConformingFloatEncodingStrategy
-Notation
-NotEqual
-Notification
-NotificationCenter
-Notifications
-NSApplicationDelegateAdaptor
-NSAttributedString
-NSButton
-NSColor
-NSError
-NSErrorPointer
-NSFastEnumerationIterator
-NSFont
-NSGestureRecognizerRepresentable
-NSGestureRecognizerRepresentableContext
-NSGestureRecognizerRepresentableCoordinateSpaceConverter
-NSHostingController
-NSHostingMenu
-NSHostingSceneBridgingOptions
-NSHostingSceneRepresentation
-NSHostingSizingOptions
-NSHostingView
-NSImage
-NSIndexSetIterator
-NSKeyValueObservation
-NSKeyValueObservedChange
-NSKeyValueObservingCustomization
-NSNumber
-NSObject
-NSPredicate
-NSRange
-NSScrollView
-NSSortDescriptor
-NSStackView
-NSString
-NSTableView
-NSTextField
-NSView
-NSViewController
-NSViewControllerRepresentable
-NSViewControllerRepresentableContext
-NSViewRepresentable
-NSViewRepresentableContext
-NSWindow
-NumberFormatAttributes
-NumberFormatStyleConfiguration
-NumberFormatter
-NumberingSystem
-NumberPart
-NumberPartAttribute
-NumberRepresentation
-ObjectIdentifier
-ObjectiveCConvertibleAttributedStringKey
-ObjectiveCValue
-ObjectWillChangePublisher
-Observable
-ObservableObject
-ObservableObjectPublisher
-ObservationRegistrar
-ObservationToken
-ObservedObject
-OffsetShape
-OffsetTransition
-OnInsertTableRowModifier
-OpacityTransition
-OpaquePointer
-OpenDocumentAction
-OpenImmersiveSpaceAction
-OpenSettingsAction
-OpenURLAction
-OpenWindowAction
-Operation
-OperationQueue
-OperationsOutsideApp
-OperationsWithinApp
-Optional
-OptionalFlatMap
-OptionSet
-Orientation
-OrnamentAttachmentAnchor
-OutlineGroup
-OutlineSubgroupChildren
-Output
-OutputFormatting
-PageIndexViewStyle
-PagePresentationSizing
-PageTabViewStyle
-PagingScrollTargetBehavior
-PaletteControlGroupStyle
-PalettePickerStyle
-PaletteSelectionEffect
-ParseableFormatStyle
-ParseInput
-ParseOutput
-ParseStrategy
-PartialKeyPath
-PartialRangeFrom
-PartialRangeThrough
-PartialRangeUpTo
-PartOfSpeech
-PassthroughSubject
-PasteButton
-Path
-Pattern
-PencilDoubleTapGestureValue
-PencilHoverPose
-PencilPreferredAction
-PencilSqueezeGesturePhase
-PencilSqueezeGestureValue
-Percent
-PeriodicTimelineSchedule
-PersonNameComponentAttribute
-PersonNameComponents
-Phase
-PhaseAnimator
-Phases
-PhysicalMetric
-Picker
-PickerStyle
-PinnedScrollableViews
-Pipe
-Placeholder
-PlaceholderContentView
-PlaceholderTextShapeStyle
-PlainButtonStyle
-PlainListStyle
-PlainTextEditorStyle
-PlainTextFieldStyle
-PlainWindowStyle
-PointerStyle
-PopoverAttachmentAnchor
-PopUpButtonPickerStyle
-Position
-POSIXError
-PowerStateDidChangeMessage
-Precision
-Predicate
-PredicateBindings
-PredicateCodableConfiguration
-PredicateCodableKeyPathProviding
-PredicateError
-PredicateEvaluate
-PredicateExpression
-PredicateExpressions
-PredicateRegex
-PreferenceKey
-PreferredColorSchemeKey
-PrefetchStrategy
-PrefixUntilOutput
-PrefixWhile
-Presentation
-PresentationAdaptation
-PresentationBackgroundInteraction
-PresentationContentInteraction
-PresentationDetent
-PresentationIntent
-PresentationIntentAttribute
-PresentationMode
-PresentationSizing
-PresentationSizingContext
-PresentationSizingRoot
-PresentedWindowContent
-PressFeedback
-PreviewContext
-PreviewContextKey
-PreviewDevice
-PreviewModifier
-PreviewModifierContent
-PreviewPlatform
-PreviewProvider
-PrimitiveButtonStyle
-PrimitiveButtonStyleConfiguration
-Print
-Process
-ProcessInfo
-Progress
-ProgressiveImmersionAspectRatio
-ProgressiveImmersionStyle
-ProgressView
-ProgressViewStyle
-ProgressViewStyleConfiguration
-ProjectionTransform
-Prominence
-ProminentDetailNavigationSplitViewStyle
-Promise
-Pronoun
-PronounType
-Properties
-Property
-PropertyListDecoder
-PropertyListEncoder
-PropertyListFormat
-PropertyListSerialization
-ProposedViewSize
-Published
-Publisher
-Publishers
-PullDownButton
-PullDownMenuBarExtraStyle
-PullDownMenuButtonStyle
-PushTransition
-PushWindowAction
-Quarter
-RadialGradient
-RadioGroupPickerStyle
-RandomAccessCollection
-Range
-RangeExpressionContains
-RangeReplaceableCollection
-RangeView
-RasterizationOptions
-RawRepresentable
-RawValue
-ReadCompletionMessage
-ReadingOptions
-ReadToEndOfFileCompletionMessage
-ReceiveOn
-Record
-Recording
-RecoverableError
-Rectangle
-RectangleCornerInsets
-RectangleCornerRadii
-RecurrenceRule
-RedactionReasons
-Reduce
-ReferenceConvertible
-ReferenceFileDocument
-ReferenceFileDocumentConfiguration
-ReferenceType
-ReferenceWritableKeyPath
-ReferentConceptAttribute
-RefreshAction
-RegexOutput
-Region
-Regions
-RelativeDateTimeFormatter
-RelativeFormatStyle
-ReleaseFeedback
-RemoteDeviceIdentifier
-RemoteImmersiveSpace
-RemoveDuplicates
-RenameAction
-RenameButton
-Renderer
-Repeated
-RepeatedTimePolicy
-ReplaceEmpty
-ReplaceError
-ReplacementIndexAttribute
-Representation
-ResetFocusAction
-ResizingMode
-Resolved
-ResolvedHDR
-ResolvedImage
-ResolvedModifier
-ResolvedSymbol
-ResolvedText
-Result
-Retry
-ReversedCollection
-RGBColorSpace
-Root
-RotatedShape
-RotateGesture
-RotationGesture
-RoundedBorderTextEditorStyle
-RoundedBorderTextFieldStyle
-RoundedCornerStyle
-RoundedRectangle
-RoundedRectangularShape
-RoundedRectangularShapeCorners
-RoundingMode
-RoundingRule
-Run
-RunLoop
-Runs
-RunSlice
-SafeAreaRegions
-Scale
-ScaledMetric
-ScaledShape
-ScaleTransition
-Scan
-Scanner
-Scene
-SceneBuilder
-SceneLaunchBehavior
-ScenePadding
-ScenePhase
-SceneRestorationBehavior
-SceneStorage
-Scheduler
-SchedulerOptions
-SchedulerTimeIntervalConvertible
-SchedulerTimeType
-Scope
-Scoped
-ScopedAttributeContainer
-Script
-ScrollableContent
-ScrollAnchorRole
-ScrollBounceBehavior
-ScrollContentOffsetAdjustmentBehavior
-ScrollDismissesKeyboardMode
-ScrollEdgeEffectStyle
-ScrollGeometry
-ScrollIndicatorVisibility
-ScrollInputBehavior
-ScrollInputKind
-ScrollPhase
-ScrollPhaseChangeContext
-ScrollPosition
-ScrollTarget
-ScrollTargetBehavior
-ScrollTargetBehaviorContext
-ScrollTargetBehaviorProperties
-ScrollTargetBehaviorPropertiesContext
-ScrollTransitionConfiguration
-ScrollTransitionPhase
-ScrollView
-ScrollViewProxy
-ScrollViewReader
-SearchDirection
-SearchFieldPlacement
-SearchOptions
-SearchPresentationToolbarBehavior
-SearchScopeActivation
-SearchSuggestionsPlacement
-SearchToolbarBehavior
-SearchUnavailableContent
-Second
-SecondFraction
-Section
-SectionCollection
-SectionConfiguration
-SectionCustomization
-SectionedFetchRequest
-SectionedFetchResults
-SecureField
-SegmentedPickerStyle
-SelectionFeedback
-SelectionShapeStyle
-Sendable
-SensoryFeedback
-SeparatorShapeStyle
-Sequence
-SequenceAllSatisfy
-SequenceContains
-SequenceContainsWhere
-SequenceGesture
-SequenceMaximum
-SequenceMinimum
-SequenceStartsWith
-Set
-SetFailureType
-Settings
-SettingsLink
-Shader
-ShaderFunction
-ShaderLibrary
-Shading
-ShadowOptions
-ShadowStyle
-Shape
-ShapeRole
-ShapeStyle
-ShapeView
-Share
-ShareLink
-SharePreview
-SharingBehavior
-SidebarAdaptableTabViewStyle
-SidebarCommands
-SidebarListStyle
-SidebarRowSize
-SignDisplayStrategy
-SimultaneousGesture
-SingleAttributeTransformer
-Sink
-Size
-SizeDependentTextVariant
-SizeLimitExceededMessage
-Slice
-Slider
-SliderTick
-SliderTickBuilder
-SliderTickContent
-SliderTickContentForEach
-SlideTransition
-SnapshotData
-SnapshotReason
-SnapshotResponse
-SortComparator
-SortDescriptor
-SortOrder
-Source
-Spacer
-SpacerSizing
-SpatialEventCollection
-SpatialEventGesture
-SpatialTapGesture
-Spring
-SpringKeyframe
-SpringLoadingBehavior
-SquareAzimuth
-SquareBorderTextFieldStyle
-StackNavigationViewStyle
-StandaloneMonth
-StandaloneQuarter
-StandaloneWeekday
-StandardComparator
-StandardPredicateExpression
-State
-StateObject
-StaticString
-Stepper
-StepperFieldDatePickerStyle
-Stop
-Stopwatch
-Storage
-Strategy
-Stride
-StrikethroughStyleAttribute
-String
-StringCaseInsensitiveCompare
-StringContainsRegex
-StringInterpolation
-StringLiteralType
-StringLocalizedCompare
-StringLocalizedStandardContains
-StringStyle
-StrokeBorderShapeView
-StrokeShapeView
-StrokeStyle
-Style
-Subdivision
-Subject
-SubmitLabel
-SubmitTriggers
-SubscribeOn
-Subscriber
-Subscribers
-Subscription
-Subscriptions
-SubscriptionView
-Subsequence
-SubSequence
-Substring
-Subview
-SubviewsCollection
-SubviewsCollectionSlice
-SurroundingsEffect
-SuspendingClock
-SwiftUIAttributes
-SwitchToggleStyle
-SwitchToLatest
-Symbol
-SymbolAttribute
-SymbolColorRenderingMode
-SymbolEffectTransition
-SymbolRenderingMode
-SymbolVariableValueMode
-SymbolVariants
-SystemClockDidChangeMessage
-SystemFormatStyle
-SystemTimeZoneDidChangeMessage
-Tab
-TabBarMinimizeBehavior
-TabBarOnlyTabViewStyle
-TabBarPlacement
-TabContent
-TabContentBuilder
-TabCustomization
-TabCustomizationBehavior
-Table
-TableColumn
-TableColumnAlignment
-TableColumnBody
-TableColumnBuilder
-TableColumnContent
-TableColumnCustomization
-TableColumnCustomizationBehavior
-TableColumnForEach
-TableColumnSortComparator
-TableForEachContent
-TableHeaderRowContent
-TableOutlineGroupContent
-TableRow
-TableRowBody
-TableRowBuilder
-TableRowContent
-TableRowValue
-TableStyle
-TableStyleConfiguration
-TabPlacement
-TabRole
-TabSearchActivation
-TabSection
-TabValue
-TabView
-TabViewBottomAccessoryPlacement
-TabViewCustomization
-TabViewStyle
-TapGesture
-Task
-TaskGroup
-TaskPriority
-Template
-TemplateRenderingMode
-TermOfAddress
-Text
-TextAlignment
-TextAttribute
-TextEditingCommands
-TextEditor
-TextEditorStyle
-TextEditorStyleConfiguration
-TextField
-TextFieldLink
-TextFieldStyle
-TextFormattingCommands
-TextInputDictationActivation
-TextInputDictationBehavior
-TextInputFormattingControlPlacement
-TextProxy
-TextRenderer
-TextSelectability
-TextSelection
-TextSelectionAffinity
-TextStyle
-TextVariantPreference
-ThermalStateDidChangeMessage
-Thread
-Threshold
-Throttle
-ThrowingTaskGroup
-TicksCollection
-TimeDataSource
-TimeFormatStyle
-TimeGroupingStrategy
-TimeInterval
-TimelineSchedule
-TimelineScheduleMode
-TimelineView
-TimelineViewDefaultContext
-Timeout
-Timer
-TimerPublisher
-TimeSeparator
-TimeStyle
-TimeZone
-TimeZoneSeparator
-TintShapeStyle
-Title
-TitleAndIconLabelStyle
-TitleBarWindowStyle
-TitleDisplayMode
-TitleOnlyLabelStyle
-Toggle
-ToggleStyle
-ToggleStyleConfiguration
-ToolbarCommands
-ToolbarContent
-ToolbarContentBuilder
-ToolbarCustomizationBehavior
-ToolbarCustomizationOptions
-ToolbarDefaultItemKind
-ToolbarItem
-ToolbarItemGroup
-ToolbarItemPlacement
-ToolbarLabelStyle
-ToolbarPlacement
-ToolbarRole
-ToolbarSpacer
-ToolbarTitleDisplayMode
-ToolbarTitleMenu
-TopLevelDecoder
-TopLevelEncoder
-Touch
-TouchBar
-TouchBarItemPresence
-TrackingAttribute
-Transaction
-TransactionKey
-Transferable
-TransformedShape
-Transition
-TransitionPhase
-TransitionProperties
-TransitionStyle
-Tree
-TruncationMode
-TryAllSatisfy
-TryCatch
-TryCompactMap
-TryComparison
-TryContainsWhere
-TryDropWhile
-TryFilter
-TryFirstWhere
-TryLastWhere
-TryMap
-TryPrefixWhile
-TryReduce
-TryRemoveDuplicates
-TryScan
-TupleDefinition
-TupleSliderTickContent
-TupleTableColumnContent
-TupleTableRowContent
-TupleView
-TypeCheck
-TypedPayloadError
-TypesettingLanguage
-TypographicBounds
-UbiquityIdentityDidChangeMessage
-UIApplication
-UIBezierPath
-UIButton
-UICollectionView
-UICollectionViewCell
-UIColor
-UIDevice
-UIEdgeInsets
-UIFont
-UIGestureRecognizer
-UIGestureRecognizerRepresentable
-UIGestureRecognizerRepresentableContext
-UIGestureRecognizerRepresentableCoordinateSpaceConverter
-UIHostingController
-UIImage
-UILabel
-UINavigationController
-UInt
-UInt16
-UInt32
-UInt64
-UInt8
-UIPanGestureRecognizer
-UIScreen
-UIScrollView
-UISegmentedControl
-UISlider
-UIStackView
-UISwitch
-UITabBarController
-UITableView
-UITableViewCell
-UITapGestureRecognizer
-UITextField
-UITextView
-UIView
-UIViewController
-UIViewControllerRepresentable
-UIViewRepresentable
-UIWindow
-UIWindowScene
-UnaryMinus
-UnaryViewRoot
-UnderlineStyleAttribute
-UnevenRoundedRectangle
-Unicode
-UnicodeScalarLiteralType
-UnicodeScalarView
-UnifiedCompactWindowToolbarStyle
-UnifiedWindowToolbarStyle
-Unit
-UnitCurve
-UnitDuration
-UnitLength
-UnitMass
-UnitPoint
-UnitPoint3D
-Units
-UnitsFormatStyle
-UnitsStyle
-UnitWidth
-UnsafeBufferPointer
-UnsafeContinuation
-UnsafeMutableBufferPointer
-UnsafeMutablePointer
-UnsafeMutableRawPointer
-UnsafePointer
-UnsafeRawPointer
-URL
-URLComponents
-URLError
-URLQueryItem
-URLRequest
-URLResource
-URLResourceValues
-URLResponse
-URLSession
-URLSessionDataTask
-URLSessionTask
-UsageType
-UserInterfaceSizeClass
-UTF16View
-UTF8View
-UtilityWindow
-UUID
-Value
-ValueConstraint
-Variable
-VariableID
-VariableName
-Variant
-VectorArithmetic
-VerbatimFormatStyle
-VerbatimHour
-VerticalAlignment
-VerticalDirection
-VerticalEdge
-VerticalPageTabViewStyle
-View
-ViewAlignedScrollTargetBehavior
-ViewBuilder
-ViewDimensions
-ViewDimensions3D
-ViewModifier
-Viewpoint3D
-ViewRoot
-ViewSpacing
-ViewThatFits
-Visibility
-VisualEffect
-Void
-VolumeViewpointUpdateStrategy
-VSplitView
-VStack
-VStackLayout
-Week
-Weekday
-Weight
-WheelDatePickerStyle
-WheelPickerStyle
-Widget
-WidgetBundle
-WidgetBundleBuilder
-WidgetConfiguration
-Width
-WillCloseUndoGroupMessage
-WillEnterForegroundMessage
-WillRedoChangeMessage
-WillResignActiveMessage
-WillUndoChangeMessage
-Window
-WindowBackgroundShapeStyle
-WindowDragGesture
-WindowGroup
-WindowIdealSize
-WindowInteractionBehavior
-WindowLayoutRoot
-WindowLevel
-WindowManagerRole
-WindowMenuBarExtraStyle
-WindowPlacement
-WindowPlacementContext
-WindowProxy
-WindowResizability
-WindowStyle
-WindowToolbarFullScreenVisibility
-WindowToolbarStyle
-WindowVisibilityToggle
-WorldAlignmentBehavior
-WorldRecenterPhase
-WorldTrackingLimitation
-Wrapper
-WritableKeyPath
-WritingDirection
-WritingDirectionAttribute
-WritingDirectionStrategy
-WritingOptions
-WritingToolsBehavior
-Year
-YearForWeekOfYear
-ZeroValueUnitsDisplayStrategy
-Zip
-Zip2Sequence
-Zip3
-Zip4
-ZoomNavigationTransition
-ZStack
-ZStackLayout
-"""
-}
diff --git a/Sources/SiteKitSyntaxHighlighting/SwiftSyntaxHighlighter.swift b/Sources/SiteKitSyntaxHighlighting/SwiftSyntaxHighlighter.swift
index 208297d..991f916 100644
--- a/Sources/SiteKitSyntaxHighlighting/SwiftSyntaxHighlighter.swift
+++ b/Sources/SiteKitSyntaxHighlighting/SwiftSyntaxHighlighter.swift
@@ -13,11 +13,10 @@ import SwiftSyntax
/// labels (`label`). It does so purely from the parsed syntax tree – no type-checker or symbol
/// graph – so it is fast and error-tolerant on the partial code fragments common in DocC notes.
///
-/// The classification is SYNTACTIC, not semantic, so the framework-vs-project type split (e.g.
-/// `ScrollView` vs a project's `StickerListItemView`) is APPROXIMATED from a committed framework-type
-/// allowlist rather than a symbol graph: a capitalized type whose name is in the allowlist keeps the
-/// `type` role (framework, purple), any other capitalized type becomes `projecttype` (project, green).
-/// Extend the allowlist per site with `additionalFrameworkTypes`.
+/// The classification is SYNTACTIC, not semantic: every capitalized type (initializer, annotation,
+/// or bare reference) gets the single `type` role, exactly like the regex `CodeHighlighter`. The
+/// extra value this highlighter adds is the EXPRESSION-position roles the regex pass cannot see –
+/// the green `variable` references above all.
///
/// Non-Swift snippets (and nil/empty languages) are delegated to a fallback highlighter – by
/// default the zero-dependency regex `CodeHighlighter` – so a DocC site can inject this single
@@ -25,23 +24,13 @@ import SwiftSyntax
public struct SwiftSyntaxHighlighter: CodeHighlighting {
private let fallback: any CodeHighlighting
- /// The effective framework-type set: the committed `FrameworkTypeAllowlist` unioned with any
- /// `additionalFrameworkTypes` passed at init. Capitalized types in this set render as framework
- /// `type`; all other capitalized types render as project `projecttype`.
- private let frameworkTypes: Set
-
/// Creates a SwiftSyntax-based highlighter.
///
- /// - Parameters:
- /// - fallback: The highlighter used for non-Swift snippets and nil/empty languages. Pass nil
- /// (the default) to use the zero-dependency regex `CodeHighlighter`. Resolved internally so the
- /// default does not reference an internal type across the module boundary.
- /// - additionalFrameworkTypes: Extra type names to treat as framework (purple) types on top of
- /// the committed allowlist, e.g. a site's own design-system or umbrella-framework types it
- /// wants colored like the SDK. Defaults to empty, leaving the behavior unchanged.
- public init(fallback: (any CodeHighlighting)? = nil, additionalFrameworkTypes: Set = []) {
+ /// - Parameter fallback: The highlighter used for non-Swift snippets and nil/empty languages. Pass
+ /// nil (the default) to use the zero-dependency regex `CodeHighlighter`. Resolved internally so
+ /// the default does not reference an internal type across the module boundary.
+ public init(fallback: (any CodeHighlighting)? = nil) {
self.fallback = fallback ?? CodeHighlighter()
- self.frameworkTypes = FrameworkTypeAllowlist.frameworkTypeNames.union(additionalFrameworkTypes)
}
public func highlight(code: String, language: String?) -> String {
@@ -62,7 +51,7 @@ public struct SwiftSyntaxHighlighter: CodeHighlighting {
guard count > 0 else { return "" }
let tree = Parser.parse(source: code)
- let roleMap = SwiftTokenRoleClassifier.classify(tree, frameworkTypes: self.frameworkTypes)
+ let roleMap = SwiftTokenRoleClassifier.classify(tree)
var output = ""
var cursor = 0
@@ -112,10 +101,9 @@ public struct SwiftSyntaxHighlighter: CodeHighlighting {
return "keyword"
case .type:
// A token the base pass already knows sits in TYPE position (`View` in `: View`, `Sticker`
- // in `[Sticker]`). Split it by the framework allowlist like the expression-visitor types, so
- // type annotations get the same framework-vs-project palette as type initializers.
- let name = String(decoding: bytes[lower..
-
- private init(frameworkTypes: Set) {
- self.frameworkTypes = frameworkTypes
- super.init(viewMode: .sourceAccurate)
- }
-
- /// Classifies every refinable token in `tree` and returns the offset→role map. `frameworkTypes` is
- /// the effective allowlist that decides, per capitalized type token, framework `type` vs project
- /// `projecttype`.
- static func classify(_ tree: SourceFileSyntax, frameworkTypes: Set) -> [Int: String] {
- let visitor = SwiftTokenRoleClassifier(frameworkTypes: frameworkTypes)
+ /// Classifies every refinable token in `tree` and returns the offset→role map.
+ static func classify(_ tree: SourceFileSyntax) -> [Int: String] {
+ let visitor = SwiftTokenRoleClassifier(viewMode: .sourceAccurate)
visitor.walk(tree)
return visitor.roles
}
// MARK: - Helpers
- /// The role for a capitalized type token (`type` if its name is a framework / known type, else the
- /// project-type `projecttype`), resolved against this classifier's effective framework set.
- private func typeRole(forName name: String) -> String {
- FrameworkTypeAllowlist.role(forTypeName: name, in: self.frameworkTypes)
- }
-
private func byteOffset(of token: TokenSyntax) -> Int {
token.positionAfterSkippingLeadingTrivia.utf8Offset
}
@@ -76,16 +58,14 @@ final class SwiftTokenRoleClassifier: SyntaxVisitor {
// MARK: - Calls
override func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind {
- // The callee identifies what kind of call this is. A capitalized callee is a type
- // initializer (`ScrollView { … }`, `ForEach(…)`, `StickerListItemView(…)`); its name is split
- // against the committed framework allowlist into a framework `type` (purple) or a project
- // `projecttype` (green), approximating Xcode's framework-vs-project palette without a symbol
- // graph. A lowercase callee is a free-function call (`print(…)`). A member callee
- // (`view.swipeActions(…)`) is left to the member-access visitor so the member keeps its
- // `member` role whether or not it is called.
+ // The callee identifies what kind of call this is. A capitalized callee is a type initializer
+ // (`ScrollView { … }`, `ForEach(…)`, `StickerListItemView(…)`) and takes the `type` role. A
+ // lowercase callee is a free-function call (`print(…)`). A member callee (`view.swipeActions(…)`)
+ // is left to the member-access visitor so the member keeps its `member` role whether or not it
+ // is called.
if let reference = node.calledExpression.as(DeclReferenceExprSyntax.self),
self.isIdentifierToken(reference.baseName) {
- let role = self.startsUppercased(reference.baseName.text) ? self.typeRole(forName: reference.baseName.text) : "call"
+ let role = self.startsUppercased(reference.baseName.text) ? "type" : "call"
self.set(role, at: reference.baseName)
}
return .visitChildren
@@ -110,13 +90,12 @@ final class SwiftTokenRoleClassifier: SyntaxVisitor {
// Reached for every declaration reference. Callees and member names were already assigned
// by their parent above, so only fill the ones still unset: a lowercase reference is a value
// (`stickers`, `sticker`) → the headline green `variable`; a capitalized one is a bare type
- // reference (`Color.red`'s `Color`, a metatype) → split by the framework allowlist into a
- // framework `type` or a project `projecttype`.
+ // reference (`Color.red`'s `Color`, a metatype) → the `type` role.
let token = node.baseName
guard self.isIdentifierToken(token) else { return .visitChildren }
let offset = self.byteOffset(of: token)
guard self.roles[offset] == nil else { return .visitChildren }
- self.roles[offset] = self.startsUppercased(token.text) ? self.typeRole(forName: token.text) : "variable"
+ self.roles[offset] = self.startsUppercased(token.text) ? "type" : "variable"
return .visitChildren
}
diff --git a/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift b/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
index dbd3b14..02332c6 100644
--- a/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
+++ b/Tests/SiteKitSyntaxHighlightingTests/SwiftSyntaxHighlighterTests.swift
@@ -78,50 +78,31 @@ struct SwiftSyntaxHighlighterTests {
self.expectSpan(result, role: "variable", text: "count")
}
- // MARK: - Framework-vs-project type split (the committed allowlist heuristic)
+ // MARK: - Capitalized types all map to the single type role
- @Test("A framework type stays type (purple) – present in the committed allowlist")
- func frameworkTypeStaysType() {
- // `ScrollView` is an SDK type in the committed allowlist, so it keeps the framework `type` role.
- let code = "ScrollView { Text(title) }"
- let result = self.highlighter.highlight(code: code, language: "swift")
- self.expectSpan(result, role: "type", text: "ScrollView")
- self.expectSpan(result, role: "type", text: "Text")
- }
-
- @Test("A project type becomes projecttype (green) – absent from the allowlist")
- func projectTypeBecomesProjectType() {
- // `StickerListItemView` is a project-defined type (not in the allowlist), so it splits off the
- // framework purple into the green `projecttype` role – the headline of this refinement.
+ @Test("A project-defined type is classified type, just like an SDK type")
+ func projectDefinedTypeIsType() {
+ // With the framework-vs-project split removed, every capitalized type – SDK or project-defined –
+ // takes the single `type` role, exactly like the regex highlighter.
let code = "StickerListItemView(sticker: sticker)"
let result = self.highlighter.highlight(code: code, language: "swift")
- self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
+ self.expectSpan(result, role: "type", text: "StickerListItemView")
}
- @Test("A type in TYPE position is split too (annotation, not just an initializer)")
- func typePositionIsSplit() {
+ @Test("A type in TYPE position is classified type (annotation, not just an initializer)")
+ func typePositionIsType() {
// The base SwiftIDEUtils pass classifies these as `.type` (not via the expression visitors), so
- // the split must apply to the base mapping as well: `View` framework→type, `Sticker` project→projecttype.
+ // the base mapping must also produce `type`: both `View` and the project's `Sticker`.
let code = "struct Row: View { var items: [Sticker] = [] }"
let result = self.highlighter.highlight(code: code, language: "swift")
self.expectSpan(result, role: "type", text: "View")
- self.expectSpan(result, role: "projecttype", text: "Sticker")
+ self.expectSpan(result, role: "type", text: "Sticker")
}
- @Test("additionalFrameworkTypes promotes a name to the framework type role")
- func additionalFrameworkTypesPromotesToType() {
- // A site can color its own umbrella/design-system types like the SDK by passing them in. The
- // same name that is `projecttype` by default becomes framework `type` once added.
- let code = "StickerListItemView(sticker: sticker)"
- let promoting = SwiftSyntaxHighlighter(additionalFrameworkTypes: ["StickerListItemView"])
- let result = promoting.highlight(code: code, language: "swift")
- self.expectSpan(result, role: "type", text: "StickerListItemView")
- }
-
- @Test("The swipe-actions block splits framework vs project types and keeps values green")
- func swipeBlockFrameworkVsProjectSplit() {
- // The representative SwiftUI swipe-actions block: SDK container/iteration types stay purple,
- // the project's row/button types go green, and the value references stay the headline green.
+ @Test("The swipe-actions block classifies every capitalized type as type and keeps values green")
+ func swipeBlockTypesAndGreenValues() {
+ // The representative SwiftUI swipe-actions block: SDK and project types alike read as `type`,
+ // and the value references stay the headline green `variable`.
let code = """
ScrollView {
LazyVStack {
@@ -138,8 +119,8 @@ struct SwiftSyntaxHighlighterTests {
self.expectSpan(result, role: "type", text: "ScrollView")
self.expectSpan(result, role: "type", text: "LazyVStack")
self.expectSpan(result, role: "type", text: "ForEach")
- self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
- self.expectSpan(result, role: "projecttype", text: "DeleteButton")
+ self.expectSpan(result, role: "type", text: "StickerListItemView")
+ self.expectSpan(result, role: "type", text: "DeleteButton")
self.expectSpan(result, role: "variable", text: "stickers")
self.expectSpan(result, role: "variable", text: "sticker")
}
@@ -173,8 +154,8 @@ struct SwiftSyntaxHighlighterTests {
let result = self.highlighter.highlight(code: code, language: "swift")
#expect(!result.isEmpty)
self.expectSpan(result, role: "variable", text: "stickers")
- // `StickerListItemView` is a project type (absent from the framework allowlist) → projecttype.
- self.expectSpan(result, role: "projecttype", text: "StickerListItemView")
+ // `StickerListItemView` is a capitalized type → the single `type` role.
+ self.expectSpan(result, role: "type", text: "StickerListItemView")
}
@Test("Empty input returns empty output")
From fd79d4deeebe154e830c9b8243209c412f2f8467 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cihat=20G=C3=BCnd=C3=BCz?=
Date: Thu, 18 Jun 2026 17:37:19 +0200
Subject: [PATCH 6/7] Delete the temporary highlighter preview generator
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.
---
.../HighlighterPreviewGenerator.swift | 176 ------------------
1 file changed, 176 deletions(-)
delete mode 100644 Tests/SiteKitSyntaxHighlightingTests/HighlighterPreviewGenerator.swift
diff --git a/Tests/SiteKitSyntaxHighlightingTests/HighlighterPreviewGenerator.swift b/Tests/SiteKitSyntaxHighlightingTests/HighlighterPreviewGenerator.swift
deleted file mode 100644
index 119a36b..0000000
--- a/Tests/SiteKitSyntaxHighlightingTests/HighlighterPreviewGenerator.swift
+++ /dev/null
@@ -1,176 +0,0 @@
-import Testing
-import Foundation
-import SiteKit
-@testable import SiteKitSyntaxHighlighting
-
-/// Generates a self-contained HTML preview of the SwiftSyntax highlighter, for eyeballing the token
-/// classification and the palette. It renders a representative SwiftUI snippet three ways: BEFORE
-/// (the regex highlighter), AFTER with one DISTINCT debug color per role (proves the classification
-/// independent of the palette), and AFTER with the shipped Apple/Xcode palette (light + dark, the
-/// look that core `docc.css` applies).
-///
-/// Not an assertion test – it only writes a file, and only when `SITEKIT_HIGHLIGHTER_PREVIEW_OUT`
-/// points at an output path, so a plain `swift test` stays fast. Run it with:
-///
-/// ```
-/// SITEKIT_HIGHLIGHTER_PREVIEW_OUT=/tmp/highlighter-preview.html swift test --filter HighlighterPreview
-/// ```
-@Suite("HighlighterPreview")
-struct HighlighterPreviewGenerator {
- /// A representative SwiftUI example exercising every role: types, a green variable reference, a
- /// parameter binding, member accesses, argument labels, a boolean, a string, a number, an
- /// attribute, an operator, and a comment.
- static let sample = """
- struct StickerList: View {
- @State private var stickers: [Sticker] = []
-
- var body: some View {
- ScrollView {
- LazyVStack(spacing: 12) {
- // Each row keeps its own swipe actions.
- ForEach(stickers) { sticker in
- StickerListItemView(sticker: sticker)
- .swipeActions(edge: .trailing) {
- DeleteButton(title: "Delete", isDestructive: true) {
- stickers.removeAll { $0.id == sticker.id }
- }
- }
- }
- }
- .swipeActionsContainer()
- }
- }
- }
- """
-
- @Test("generate the highlighter preview HTML")
- func generate() throws {
- guard let outPath = ProcessInfo.processInfo.environment["SITEKIT_HIGHLIGHTER_PREVIEW_OUT"] else {
- return
- }
- let before = CodeHighlighter().highlight(code: Self.sample, language: "swift")
- let after = SwiftSyntaxHighlighter().highlight(code: Self.sample, language: "swift")
- try Self.document(before: before, after: after).write(toFile: outPath, atomically: true, encoding: .utf8)
- print("HIGHLIGHTER_PREVIEW_WROTE \(outPath)")
- }
-
- // MARK: - HTML assembly
-
- private static func document(before: String, after: String) -> String {
- """
-
-
-
-
-
- SiteKit SwiftSyntax highlighter preview
-
-
-
-
SwiftSyntax Swift highlighter preview
-
Each syntactic role is a separate sk-tok-* class, so the palette is a
- pure-CSS concern. Variable references (stickers, the sticker usage)
- classify as variable and render green. Capitalized types
- are split by a committed framework allowlist: framework types (ScrollView,
- View) stay type (purple), project types (StickerListItemView,
- DeleteButton, Sticker) become projecttype
- (green), as in Xcode.
-
-
1 · Classification – each role in a distinct debug color
-
Arbitrary, deliberately-distinct colors so every role is visible; proves the
- classification, not the final look. BEFORE is the regex highlighter (capitalized = type only).
- \(Self.legend)
-
- BEFORE – regex highlighter
-
\(before)
- AFTER – SwiftSyntax roles
-
\(after)
-
-
-
2 · Shipped Apple/Xcode palette (call = green; alternative is call = type)
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.
---
.../SiteKit/Utilities/CodeHighlighting.swift | 59 +++++--------------
1 file changed, 14 insertions(+), 45 deletions(-)
diff --git a/Sources/SiteKit/Utilities/CodeHighlighting.swift b/Sources/SiteKit/Utilities/CodeHighlighting.swift
index f819b65..2e933d5 100644
--- a/Sources/SiteKit/Utilities/CodeHighlighting.swift
+++ b/Sources/SiteKit/Utilities/CodeHighlighting.swift
@@ -78,58 +78,27 @@ extension CodeHighlighting {
public func applyToBodyHTML(_ html: String, defaultLanguage: String?) -> String {
// Match:
...content...
// or
...content...
(no language class)
- // The content may span multiple lines, so .dotMatchesLineSeparators is required.
- guard let regex = try? NSRegularExpression(
- pattern: #"
(.*?)
"#,
- options: [.dotMatchesLineSeparators]
- ) else { return html }
+ // `lang` is nil when the class attribute is absent; `body` may span multiple lines, so the dot
+ // must match newlines. `replacing` rewrites each non-overlapping block and leaves the rest of
+ // the body verbatim.
+ let blockPattern = #/
[^"]*)")?\s*>(?.*?)
/#
+ .dotMatchesNewlines()
- let ns = html as NSString
- var result = ""
- var cursor = 0
+ return html.replacing(blockPattern) { match in
+ // An absent class attribute and an empty `language-` value both fall back to `defaultLanguage`.
+ let language = match.lang.flatMap { $0.isEmpty ? nil : String($0) } ?? defaultLanguage
- let matches = regex.matches(in: html, range: NSRange(location: 0, length: ns.length))
- for match in matches {
- // Append verbatim text before this match.
- let wholeRange = match.range
- result += ns.substring(with: NSRange(location: cursor, length: wholeRange.location - cursor))
+ // The captured content is already HTML-escaped; unescape so the tokenizer works on plain text.
+ let rawContent = HTMLEscaping.unescape(String(match.body))
- // Extract language from `class="language-X"` (group 2). When the class attribute is
- // entirely absent group 1 and group 2 are both empty.
- let language: String?
- if match.range(at: 2).location != NSNotFound {
- let langRaw = ns.substring(with: match.range(at: 2))
- language = langRaw.isEmpty ? defaultLanguage : langRaw
- } else {
- language = defaultLanguage
- }
-
- // The already-escaped code content (group 3).
- let escapedContent: String
- if match.range(at: 3).location != NSNotFound {
- escapedContent = ns.substring(with: match.range(at: 3))
- } else {
- escapedContent = ""
- }
-
- // Unescape then re-highlight so the tokenizer works on plain text.
- let rawContent = HTMLEscaping.unescape(escapedContent)
- let highlighted: String
- let classAttr: String
if let lang = language?.lowercased().trimmingCharacters(in: .whitespaces), !lang.isEmpty {
- highlighted = self.highlight(code: rawContent, language: lang)
- classAttr = " class=\"language-\(HTMLEscaping.escape(lang))\""
+ let highlighted = self.highlight(code: rawContent, language: lang)
+ return "
\(highlighted)
"
} else {
// No language and no default: just re-escape the raw content.
- highlighted = HTMLEscaping.escape(rawContent)
- classAttr = ""
+ let highlighted = HTMLEscaping.escape(rawContent)
+ return "