Skip to content

Commit

Permalink
Fix segmented Text
Browse files Browse the repository at this point in the history
  • Loading branch information
carson-katri committed Aug 3, 2020
1 parent cb63594 commit c0a5806
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
43 changes: 24 additions & 19 deletions Sources/TokamakCore/Views/Text/Text.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,11 @@ public struct Text: View {
let storage: _Storage
let modifiers: [_Modifier]

@Environment(\.self) public var environment
@Environment(\.font) var font
@Environment(\.foregroundColor) var foregroundColor
@Environment(\.redactionReasons) var redactionReasons
@Environment(\.self) var environment

public enum _Storage {
case verbatim(String)
case segmentedText([Text])
case segmentedText([(_Storage, [_Modifier])])
}

public enum _Modifier: Equatable {
Expand All @@ -59,8 +56,7 @@ public struct Text: View {
init(storage: _Storage, modifiers: [_Modifier] = []) {
if case let .segmentedText(segments) = storage {
self.storage = .segmentedText(segments.map {
Self(storage: $0.storage,
modifiers: modifiers + $0.modifiers)
($0.0, modifiers + $0.1)
})
} else {
self.storage = storage
Expand All @@ -81,6 +77,19 @@ public struct Text: View {
}
}

extension Text._Storage {
public var rawText: String {
switch self {
case let .segmentedText(segments):
return segments
.map { $0.0.rawText }
.reduce("", +)
case let .verbatim(text):
return text
}
}
}

/// This is a helper class that works around absence of "package private" access control in Swift
public struct _TextProxy {
public let subject: Text
Expand All @@ -89,24 +98,17 @@ public struct _TextProxy {

public var storage: Text._Storage { subject.storage }
public var rawText: String {
switch subject.storage {
case let .segmentedText(segments):
return segments
.map { Self($0).rawText }
.reduce("", +)
case let .verbatim(text):
return text
}
subject.storage.rawText
}

public var modifiers: [Text._Modifier] {
[
.font(subject.font),
.color(subject.foregroundColor),
.font(subject.environment.font),
.color(subject.environment.foregroundColor),
] + subject.modifiers
}

public var redactionReasons: RedactionReasons { subject.redactionReasons }
public var environment: EnvironmentValues { subject.environment }
}

public extension Text {
Expand Down Expand Up @@ -149,6 +151,9 @@ public extension Text {

extension Text {
public static func _concatenating(lhs: Self, rhs: Self) -> Self {
.init(storage: .segmentedText([lhs, rhs]))
.init(storage: .segmentedText([
(lhs.storage, lhs.modifiers),
(rhs.storage, rhs.modifiers),
]))
}
}
30 changes: 26 additions & 4 deletions Sources/TokamakStaticHTML/Views/Text/Text.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,44 @@ extension Font: StylesConvertible {
}
}

private struct TextSpan: AnyHTML {
let content: String
let attributes: [String: String]

var innerHTML: String? { content }
var tag: String { "span" }
}

extension Text: AnyHTML {
public var innerHTML: String? {
switch _TextProxy(self).storage {
let proxy = _TextProxy(self)
switch proxy.storage {
case let .verbatim(text):
return text
case let .segmentedText(segments):
return segments
.map(\.outerHTML)
.map {
TextSpan(content: $0.0.rawText,
attributes: Self.attributes(from: $0.1,
environment: proxy.environment))
.outerHTML
}
.reduce("", +)
}
}

public var tag: String { "span" }
public var attributes: [String: String] {
let proxy = _TextProxy(self)
let isRedacted = proxy.redactionReasons.contains(.placeholder)
return Self.attributes(from: proxy.modifiers,
environment: proxy.environment)
}
}

extension Text {
static func attributes(from modifiers: [_Modifier],
environment: EnvironmentValues) -> [String: String] {
let isRedacted = environment.redactionReasons.contains(.placeholder)

var font: Font?
var color: Color?
Expand All @@ -114,7 +136,7 @@ extension Text: AnyHTML {
var baseline: CGFloat?
var strikethrough: (Bool, Color?)?
var underline: (Bool, Color?)?
for modifier in proxy.modifiers {
for modifier in modifiers {
switch modifier {
case let .color(_color):
color = _color
Expand Down

0 comments on commit c0a5806

Please sign in to comment.