Skip to content

Commit e2a937e

Browse files
committed
node group support
1 parent 837a5a4 commit e2a937e

File tree

4 files changed

+35
-9
lines changed

4 files changed

+35
-9
lines changed

Sources/SwiftHtml/Components/DocumentRenderer.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,26 @@ public struct DocumentRenderer {
4141
let spaces = String(repeating: " ", count: level * indent)
4242
switch tag.node.type {
4343
case .standard:
44-
var children = tag.children.map { render(tag: $0, level: level + 1) }.joined(separator: newline)
45-
if !children.isEmpty {
46-
children = newline + children + newline + spaces
47-
}
48-
return spaces + renderOpening(tag) + (tag.node.contents ?? "") + children + renderClosing(tag)
44+
return spaces + renderOpening(tag) + (tag.node.contents ?? "") + renderChildren(tag, level: level, spaces: spaces) + renderClosing(tag)
4945
case .comment:
5046
return spaces + "<!--" + (tag.node.contents ?? "") + "-->"
5147
case .empty:
5248
return spaces + renderOpening(tag)
49+
case .group:
50+
return spaces + renderChildren(tag, level: level, spaces: spaces)
51+
}
52+
}
53+
54+
private func renderChildren(_ tag: Tag, level: Int, spaces: String) -> String {
55+
var children = tag.children.map { render(tag: $0, level: level + 1) }.joined(separator: newline)
56+
if !children.isEmpty {
57+
children = newline + children + newline + spaces
5358
}
59+
return children
5460
}
5561

5662
private func renderOpening(_ tag: Tag) -> String {
57-
"<" + tag.node.name! + (tag.node.attributes.isEmpty ? "" : " ") + renderAttributes(tag.node.attributes) + ">"
63+
return "<" + tag.node.name! + (tag.node.attributes.isEmpty ? "" : " ") + renderAttributes(tag.node.attributes) + ">"
5864
}
5965

6066
private func renderClosing(_ tag: Tag) -> String {

Sources/SwiftHtml/Components/Node.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ public struct Node {
1717
/// non-container tags
1818
case empty // <br>
1919
/// invisible node for grouping other nodes
20-
///
21-
/// NOTE: this feature is implemented on the tag level, nodes are basic components
22-
// case group // *invisible group*<h1>lorem</h1><p>ipsum</p>*invisible group*
20+
case group // *invisible group*<h1>lorem</h1><p>ipsum</p>*invisible group*
2321
}
2422

2523
public let type: NodeType

Sources/SwiftHtml/Components/TagBuilder.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ public enum TagBuilder {
1111
public static func buildBlock(_ components: [Tag]...) -> [Tag] {
1212
components.flatMap { $0 }
1313
}
14+
15+
public static func buildBlock(_ components: [Tag]...) -> Tag {
16+
Tag(.init(type: .empty), children: components.flatMap { $0 })
17+
}
1418

1519
public static func buildExpression(_ expression: Tag) -> [Tag] {
1620
[expression]

Tests/SwiftHtmlTests/TagBuilderTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,23 @@ final class TagBuilderTests: XCTestCase {
9090
</div>
9191
""")
9292
}
93+
94+
func testGroupBuilder() {
95+
let doc = Document(.unspecified) {
96+
Main {
97+
H1("Lorem ipsum")
98+
P("Dolor sit amet")
99+
}
100+
}
101+
102+
XCTAssertEqual(DocumentRenderer().render(doc), """
103+
<main>
104+
<h1>Lorem ipsum</h1>
105+
<p>Dolor sit amet</p>
106+
</main>
107+
""")
108+
}
109+
110+
93111
}
94112

0 commit comments

Comments
 (0)