Skip to content

Commit 845dfa7

Browse files
committed
move darkmode to swift-html
1 parent 0b5f3d7 commit 845dfa7

File tree

4 files changed

+20
-378
lines changed

4 files changed

+20
-378
lines changed

Sources/CSS+PointFreeHTML/InlineStyle/Color.swift

Lines changed: 0 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -22,145 +22,3 @@ extension HTML {
2222
}
2323
}
2424

25-
extension HTML {
26-
@discardableResult
27-
@_disfavoredOverload
28-
@HTMLBuilder
29-
public func color(
30-
_ color: CSSPropertyTypes.Color.WithDarkMode?,
31-
media: CSSAtRuleTypes.Media? = nil,
32-
pre: String? = nil,
33-
pseudo: Pseudo? = nil
34-
) -> some HTML {
35-
switch color {
36-
case .global:
37-
self.inlineStyle(color, media: media, pre: pre, pseudo: pseudo)
38-
case let .darkMode(color):
39-
self.color(light: color.light, dark: color.dark, media: media, pre: pre, pseudo: pseudo)
40-
case .none:
41-
self
42-
}
43-
}
44-
}
45-
46-
extension CSSPropertyTypes.Color.WithDarkMode: CSSPropertyTypes.Property {
47-
public static var property: String { CSSPropertyTypes.Color.property }
48-
}
49-
50-
extension HTML {
51-
@discardableResult
52-
public func color(
53-
light: CSSTypeTypes.Color,
54-
dark: CSSTypeTypes.Color?,
55-
media: CSSAtRuleTypes.Media? = nil,
56-
pre: String? = nil,
57-
pseudo: Pseudo? = nil
58-
) -> some HTML {
59-
self
60-
.inlineStyle("color", light.description, media: media, pre: pre, pseudo: pseudo)
61-
.inlineStyle("color", dark?.description, media: .prefersColorScheme(.dark), pre: pre, pseudo: pseudo)
62-
}
63-
}
64-
65-
extension CSSPropertyTypes.Color {
66-
public enum WithDarkMode: Sendable, Hashable, GlobalConvertible, ColorConvertible {
67-
68-
case darkMode(CSSPropertyTypes.Color.WithDarkMode.Color)
69-
case global(CSSTypeTypes.Global)
70-
71-
public struct Color: Sendable, Hashable {
72-
public let light: CSSTypeTypes.Color
73-
public let dark: CSSTypeTypes.Color
74-
75-
public init(light: CSSTypeTypes.Color, dark: CSSTypeTypes.Color? = nil) {
76-
self.light = light
77-
if let dark = dark {
78-
self.dark = dark
79-
} else {
80-
self.dark = light.darker()
81-
}
82-
}
83-
}
84-
85-
public static func color(_ color: CSSTypeTypes.Color) -> CSSPropertyTypes.Color.WithDarkMode {
86-
return .init(color)
87-
}
88-
89-
public static func color(_ color: CSSPropertyTypes.Color.WithDarkMode.Color) -> Self {
90-
return .darkMode(color)
91-
}
92-
}
93-
}
94-
95-
extension CSSPropertyTypes.Color.WithDarkMode {
96-
public init(_ color: CSSPropertyTypes.Color) {
97-
switch color {
98-
case .global(let global): self = .global(global)
99-
case .color(let color): self = .init(color)
100-
}
101-
}
102-
}
103-
104-
extension CSSPropertyTypes.Color.WithDarkMode {
105-
public init(_ color: CSSTypeTypes.Color) {
106-
self = .darkMode(.init(light: color))
107-
}
108-
}
109-
110-
extension CSSPropertyTypes.Color.WithDarkMode.Color: CustomStringConvertible {
111-
public var description: String {
112-
let attribute = CSSPropertyTypes.Color.property
113-
return "@media (prefers-color-scheme: light) { \(attribute):\(light) } @media (prefers-color-scheme: dark) { \(attribute):\(dark) }"
114-
}
115-
}
116-
117-
extension CSSPropertyTypes.Color.WithDarkMode: CustomStringConvertible {
118-
public var description: String {
119-
switch self {
120-
case .darkMode(let color): return color.description
121-
case .global(let global): return global.description
122-
}
123-
}
124-
}
125-
126-
extension CSSPropertyTypes.Color.WithDarkMode.Color {
127-
public func map(_ transform: (CSSTypeTypes.Color) -> CSSTypeTypes.Color) -> Self {
128-
.init(
129-
light: transform(light),
130-
dark: transform(dark)
131-
)
132-
}
133-
134-
public func flatMap(_ transform: (CSSTypeTypes.Color) -> CSSPropertyTypes.Color.WithDarkMode.Color) -> Self {
135-
let lightTransformed = transform(light)
136-
let darkTransformed = transform(dark)
137-
138-
return .init(
139-
light: lightTransformed.light,
140-
dark: darkTransformed.dark
141-
)
142-
}
143-
}
144-
145-
extension CSSPropertyTypes.Color {
146-
public func adjustBrightness(by percentage: Double) -> Self {
147-
switch self {
148-
case .color(let color): .color(color.adjustBrightness(by: percentage))
149-
case .global(let global): .global(global)
150-
}
151-
}
152-
}
153-
154-
extension CSSPropertyTypes.Color.WithDarkMode.Color {
155-
public func adjustBrightness(by percentage: Double) -> Self {
156-
self.map { $0.adjustBrightness(by: percentage) }
157-
}
158-
159-
public func darker(by percentage: Double = 0.2) -> Self {
160-
self.map { $0.darker(by: percentage) }
161-
}
162-
163-
public func lighter(by percentage: Double = 0.2) -> Self {
164-
self.map { $0.lighter(by: percentage) }
165-
}
166-
}

Tests/CSS+PointFreeHTML Tests/Color Tests.swift

Lines changed: 18 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -18,138 +18,6 @@ import Testing
1818
.snapshots(record: nil)
1919
)
2020
struct ColorTests {
21-
@Test("Color initializes with standard color")
22-
func colorInitializesWithStandardColor() {
23-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"))
24-
#expect(color.light.description == "#FF0000")
25-
}
26-
27-
@Test("Color initializes with light and dark colors")
28-
func colorInitializesWithLightAndDarkColors() {
29-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
30-
#expect(color.light.description == "#FF0000")
31-
#expect(color.dark.description == "#00FF00")
32-
}
33-
34-
@Test("Color falls back to darker version when dark is omitted")
35-
func colorFallsBackToDarker() {
36-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"))
37-
#expect(color.dark != color.light)
38-
}
39-
40-
@Test("Color description includes media queries")
41-
func colorDescriptionIncludesMediaQueries() {
42-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
43-
let description = color.description
44-
#expect(description.contains("@media (prefers-color-scheme: light)"))
45-
#expect(description.contains("#FF0000"))
46-
#expect(description.contains("@media (prefers-color-scheme: dark)"))
47-
#expect(description.contains("#00FF00"))
48-
}
49-
50-
@Test("Color description includes dark mode even when not explicitly provided")
51-
func colorDescriptionIncludesDarkModeWhenNotExplicit() {
52-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: nil)
53-
let description = color.description
54-
#expect(description.contains("@media (prefers-color-scheme: light)"))
55-
#expect(description.contains("#FF0000"))
56-
#expect(description.contains("@media (prefers-color-scheme: dark)"))
57-
// The dark mode color is automatically generated, so we just check it exists
58-
#expect(description.contains("rgb") || description.contains("#"))
59-
}
60-
61-
@Test("Map transforms both light and dark colors")
62-
func mapTransformsBothColors() {
63-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
64-
let transformed = color.map { _ in .hex("0000FF") }
65-
#expect(transformed.light.description == "#0000FF")
66-
#expect(transformed.dark.description == "#0000FF")
67-
}
68-
69-
@Test("FlatMap transforms colors more complexly")
70-
func flatMapTransformsColorsComplexly() {
71-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
72-
let transformed = color.flatMap { _ in
73-
CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("0000FF"), dark: .hex("FF00FF"))
74-
}
75-
#expect(transformed.light.description == "#0000FF")
76-
#expect(transformed.dark.description == "#FF00FF")
77-
}
78-
79-
@Test("AdjustBrightness changes color brightness")
80-
func adjustBrightnessChangesColorBrightness() {
81-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
82-
let brightened = color.adjustBrightness(by: 0.2)
83-
#expect(brightened.light != color.light)
84-
#expect(brightened.dark != color.dark)
85-
}
86-
87-
@Test("Darker makes colors darker")
88-
func darkerMakesColorsDarker() {
89-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
90-
let darkened = color.darker(by: 0.3)
91-
#expect(darkened.light != color.light)
92-
#expect(darkened.dark != color.dark)
93-
}
94-
95-
@Test("Lighter makes colors lighter")
96-
func lighterMakesColorsLighter() {
97-
let color = CSSPropertyTypes.Color.WithDarkMode.Color(light: .hex("FF0000"), dark: .hex("00FF00"))
98-
let lightened = color.lighter(by: 0.3)
99-
#expect(lightened.light != color.light)
100-
#expect(lightened.dark != color.dark)
101-
}
102-
103-
@Test("WithDarkMode global type works correctly")
104-
func withDarkModeGlobalTypeWorksCorrectly() {
105-
let global = CSSPropertyTypes.Color.WithDarkMode.initial
106-
#expect(global.description == "initial")
107-
}
108-
109-
@Test("WithDarkMode enum description passes through correct values")
110-
func withDarkModeEnumDescriptionPassesValues() {
111-
let colorCase = CSSPropertyTypes.Color.WithDarkMode.color(
112-
.init(light: .hex("FF0000"), dark: .hex("00FF00"))
113-
)
114-
let globalCase = CSSPropertyTypes.Color.WithDarkMode.inherit
115-
116-
#expect(colorCase.description.contains("@media"))
117-
#expect(colorCase.description.contains("#FF0000"))
118-
#expect(globalCase.description == "inherit")
119-
}
120-
121-
@Test("HTML color method with pseudo-class parameter")
122-
func htmlColorMethodWithPseudoClassParameter() {
123-
124-
let test = HTMLDocument {
125-
div
126-
.color(.hex("FF0000"), pseudo: .hover)
127-
128-
}
129-
130-
let html = String(bytes: test.render(), encoding: .utf8)!
131-
#expect(html.contains(":hover"))
132-
#expect(html.contains("color:#FF0000"))
133-
134-
}
135-
136-
@Test("Color adjustBrightness method works for color case")
137-
func ColorAdjustBrightnessForColorCase() {
138-
let color = CSSPropertyTypes.Color.color(.hex("FF0000"))
139-
let brightened = color.adjustBrightness(by: 0.2)
140-
141-
#expect(brightened.description != color.description)
142-
}
143-
144-
@Test("Color adjustBrightness method preserves global case")
145-
func ColorAdjustBrightnessPreservesGlobalCase() {
146-
let global = CSSPropertyTypes.Color.inherit
147-
let adjusted = global.adjustBrightness(by: 0.2)
148-
149-
#expect(adjusted.description == global.description)
150-
#expect(adjusted.description == "inherit")
151-
}
152-
15321
@Test("HTML element renders with named color properly")
15422
func htmlElementWithNamedColorRendersCorrectly() {
15523
assertInlineSnapshot(
@@ -175,70 +43,28 @@ struct ColorTests {
17543
"""
17644
}
17745
}
46+
47+
@Test("HTML color method with pseudo-class parameter")
48+
func htmlColorMethodWithPseudoClassParameter() {
17849

179-
@Test("HTML color with Color renders properly")
180-
func htmlColorMethodWithColorWorks() {
181-
assertInlineSnapshot(
182-
of: HTMLDocument {
183-
div
184-
.color(CSSPropertyTypes.Color.color(.hex("FF0000")))
185-
},
186-
as: .html
187-
) {
188-
"""
189-
<!doctype html>
190-
<html lang="en">
191-
<head>
192-
<style>
193-
.color-bQ3ZC1{color:#FF0000}
50+
let test = HTMLDocument {
51+
div
52+
.color(.hex("FF0000"), pseudo: .hover)
19453

195-
</style>
196-
</head>
197-
<body>
198-
<div class="color-bQ3ZC1">
199-
</div>
200-
</body>
201-
</html>
202-
"""
20354
}
204-
}
20555

206-
@Test("HTML element with light/dark colors renders properly")
207-
func htmlElementWithLightDarkColorsAppliesBoth() {
208-
assertInlineSnapshot(
209-
of: HTMLDocument {
210-
div
211-
.color(light: .hex("FF0000"), dark: .hex("00FF00"))
212-
},
213-
as: .html
214-
) {
215-
"""
216-
<!doctype html>
217-
<html lang="en">
218-
<head>
219-
<style>
220-
.color-bQ3ZC1{color:#FF0000}
221-
@media (prefers-color-scheme: dark){
222-
.color-mvQv5{color:#00FF00}
223-
}
56+
let html = String(bytes: test.render(), encoding: .utf8)!
57+
#expect(html.contains(":hover"))
58+
#expect(html.contains("color:#FF0000"))
22459

225-
</style>
226-
</head>
227-
<body>
228-
<div class="color-bQ3ZC1 color-mvQv5">
229-
</div>
230-
</body>
231-
</html>
232-
"""
233-
}
23460
}
235-
236-
@Test("HTML color with media query renders properly")
237-
func htmlColorMethodWithMediaQueryParameter() {
61+
62+
@Test("HTML color with Color renders properly")
63+
func htmlColorMethodWithColorWorks() {
23864
assertInlineSnapshot(
23965
of: HTMLDocument {
24066
div
241-
.color(.blue, media: .print)
67+
.color(CSSPropertyTypes.Color.color(.hex("FF0000")))
24268
},
24369
as: .html
24470
) {
@@ -247,18 +73,19 @@ struct ColorTests {
24773
<html lang="en">
24874
<head>
24975
<style>
250-
@media print{
251-
.color-oD7XM1{color:blue}
252-
}
76+
.color-bQ3ZC1{color:#FF0000}
25377
25478
</style>
25579
</head>
25680
<body>
257-
<div class="color-oD7XM1">
81+
<div class="color-bQ3ZC1">
25882
</div>
25983
</body>
26084
</html>
26185
"""
26286
}
26387
}
88+
89+
90+
26491
}

0 commit comments

Comments
 (0)