-
Notifications
You must be signed in to change notification settings - Fork 22
/
LeafNodes.swift
176 lines (137 loc) · 4.42 KB
/
LeafNodes.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import Foundation
import Vapor
private let maximumPermalinkLength = 2000
extension ConstraintGroup {
struct LeafNode: Codable {
let constraints: [Constraint.LeafNode]
let permalink: String?
let footnotes: [Footnote.LeafNode]
}
func leafNode(includePermalink: Bool = false) -> LeafNode {
var permalink: String? {
let trimmed = raw.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
return (trimmed?.count ?? 0) < maximumPermalinkLength ? trimmed : nil
}
return .init(
constraints: constraints.map { $0.leafNode(annotations: annotations) },
permalink: includePermalink ? permalink : nil,
footnotes: footnotes.map { $0.leafNode() }
)
}
}
extension Constraint {
struct LeafNode: Codable {
let identity: Instance.LeafNode
let first: LayoutItemAttribute.LeafNode
let second: LayoutItemAttribute.LeafNode?
let relation: Relation.LeafNode
let constant: Constant.LeafNode?
let multiplier: Multiplier.LeafNode
let description: String
let footnote: Footnote.LeafNode?
}
func leafNode(annotations: [Instance: Annotation]) -> LeafNode {
let showConstant = constant.value != 0.0 || second == nil
return .init(
identity: identity.leafNode(),
first: first.leafNode(annotation: annotations[first.layoutItem]),
second: second?.leafNode(annotation: second.flatMap { annotations[$0.layoutItem] }),
relation: relation.leafNode(),
constant: showConstant ? constant.leafNode(includePositivePrefix: second != nil) : nil,
multiplier: multiplier.leafNode(),
description: htmlDescription(annotations: annotations),
footnote: footnote?.leafNode()
)
}
}
extension LayoutItemAttribute {
struct LeafNode: Codable {
let instance: Instance.LeafNode
let attribute: Attribute.LeafNode
}
func leafNode(annotation: Annotation?) -> LeafNode {
return .init(
instance: layoutItem.leafNode(annotation: annotation),
attribute: attribute.leafNode()
)
}
}
extension Instance {
struct LeafNode: Codable {
let address: String
let className: String
let name: String
let suffix: String?
let color: Color.LeafNode
let initial: String
let identifier: String?
}
func leafNode(annotation: Annotation? = nil) -> LeafNode {
let firstAlphanumeric = prettyName.unicodeScalars.first { CharacterSet.alphanumerics.contains($0) }
let initial = firstAlphanumeric.map { String($0).uppercased() } ?? ""
return .init(
address: address,
className: className,
name: prettyName,
suffix: annotation.map { $0.uniquingSuffix },
color: (annotation?.color ?? .defaultColor).leafNode(),
initial: initial,
identifier: identifier
)
}
}
extension Attribute {
struct LeafNode: Codable {
let name: String
let includesMargin: Bool
}
func leafNode() -> LeafNode {
return .init(
name: rawValue,
includesMargin: includesMargin
)
}
}
extension Constraint.Relation {
typealias LeafNode = String
func leafNode() -> LeafNode {
return rawValue
}
}
extension Multiplier {
typealias LeafNode = String?
func leafNode() -> LeafNode {
guard value != 1.0 else { return nil }
return "* \(format(number: value, maximumFractionDigits: 3))"
}
}
extension Constant {
struct LeafNode: Codable {
let value: String
let prefix: String?
}
func leafNode(includePositivePrefix: Bool) -> LeafNode {
return .init(
value: format(number: abs(value)),
prefix: value < 0 ? "- " : includePositivePrefix ? "+ " : nil
)
}
}
extension Color {
typealias LeafNode = String
func leafNode() -> LeafNode {
return rgb
}
}
extension Footnote {
struct LeafNode: Codable {
let marker: String
let text: String
}
func leafNode() -> LeafNode {
return .init(
marker: marker,
text: htmlText
)
}
}