Skip to content

Commit e8d1856

Browse files
fixed type label only working for input macro; added 3 more unit tests
1 parent 3399db3 commit e8d1856

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ Write HTML using Swift Macros.
44
- Swift Macros are powerful and offer performance benefits
55
- Alternative libraries may not fit all situations and may restrict how the html is generated/manipulated, prone to human error, or cost a constant performance overhead (middleware, rendering, result builders, etc)
66
- HTML macros enforce safety, can be used anywhere, and compile directly to strings which are easily manipulated
7-
- The output is already minified at no performance cost
8-
### Examples
7+
- The output is minified at no performance cost
8+
## Examples
99
```swift
1010
let test:String = #html([
1111
#body([

Sources/HTMLKit/HTMLKit.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4575,12 +4575,7 @@ public macro wbr(
45754575
_ innerHTML: [String] = []) -> String = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
45764576

45774577
// MARK: HTMLElementAttribute
4578-
public struct HTMLElementAttribute : Hashable {
4579-
public let id:String
4580-
4581-
init(_ id: String) {
4582-
self.id = id
4583-
}
4578+
public enum HTMLElementAttribute {
45844579
}
45854580

45864581
// MARK: CSSUnit
@@ -4628,7 +4623,6 @@ public extension HTMLElementAttribute.CSSUnit { // https://www.w3schools.com/css
46284623
}
46294624

46304625
public extension HTMLElementAttribute {
4631-
typealias type = inputmode
46324626
typealias height = CSSUnit
46334627
typealias width = CSSUnit
46344628

Sources/HTMLKitMacros/HTMLElement.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import SwiftSyntaxMacros
1111
struct HTMLElement : ExpressionMacro {
1212
static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
1313
let type:HTMLElementType = HTMLElementType(rawValue: node.macroName.text)!
14-
let data:ElementData = parse_arguments(arguments: node.arguments)
14+
let data:ElementData = parse_arguments(elementType: type, arguments: node.arguments)
1515
var string:String = (type == .html ? "<!DOCTYPE html>" : "") + "<" + type.rawValue + data.attributes + ">" + data.innerHTML
1616
if !type.isVoid {
1717
string += "</" + type.rawValue + ">"
@@ -21,7 +21,7 @@ struct HTMLElement : ExpressionMacro {
2121
}
2222

2323
private extension HTMLElement {
24-
static func parse_arguments(arguments: LabeledExprListSyntax) -> ElementData {
24+
static func parse_arguments(elementType: HTMLElementType, arguments: LabeledExprListSyntax) -> ElementData {
2525
var attributes:[String] = [], innerHTML:[String] = []
2626
for element in arguments.children(viewMode: .all) {
2727
if let child:LabeledExprSyntax = element.as(LabeledExprSyntax.self) {
@@ -30,7 +30,7 @@ private extension HTMLElement {
3030
let tuple:TupleExprSyntax = child.expression.as(TupleExprSyntax.self)!
3131
key += "-\(tuple.elements.first!.expression.as(StringLiteralExprSyntax.self)!.string)"
3232
attributes.append(key + "=\\\"\(tuple.elements.last!.expression.as(StringLiteralExprSyntax.self)!.string)\\\"")
33-
} else if let string:String = parse_attribute(key: key, expression: child.expression) {
33+
} else if let string:String = parse_attribute(elementType: elementType, key: key, expression: child.expression) {
3434
attributes.append(string)
3535
}
3636
} else if let array:ArrayElementListSyntax = child.expression.as(ArrayExprSyntax.self)?.elements { // inner html
@@ -48,7 +48,7 @@ private extension HTMLElement {
4848
}
4949
static func parse_element_macro(expression: MacroExpansionExprSyntax) -> String {
5050
guard let elementType:HTMLElementType = HTMLElementType(rawValue: expression.macroName.text) else { return "\(expression)" }
51-
let data:ElementData = parse_arguments(arguments: expression.arguments)
51+
let data:ElementData = parse_arguments(elementType: elementType, arguments: expression.arguments)
5252
return "<" + elementType.rawValue + data.attributes + ">" + data.innerHTML + (elementType.isVoid ? "" : "</" + elementType.rawValue + ">")
5353
}
5454

@@ -61,7 +61,7 @@ private extension HTMLElement {
6161
}
6262
}
6363

64-
static func parse_attribute(key: String, expression: ExprSyntax) -> String? {
64+
static func parse_attribute(elementType: HTMLElementType, key: String, expression: ExprSyntax) -> String? {
6565
if let boolean:String = expression.as(BooleanLiteralExprSyntax.self)?.literal.text {
6666
return boolean.elementsEqual("true") ? key : nil
6767
}
@@ -79,7 +79,24 @@ private extension HTMLElement {
7979
return yup(value)
8080
}
8181
func member(_ value: String) -> String {
82-
return yup("\\(HTMLElementAttribute." + key + value + ")")
82+
var enumName:String = key
83+
switch elementType.rawValue + key { // better performance than switching key, than switching elementType
84+
case "buttontype":
85+
enumName = "buttontype"
86+
break
87+
case "inputtype":
88+
enumName = "inputmode"
89+
break
90+
case "oltype":
91+
enumName = "numberingtype"
92+
break
93+
case "scripttype":
94+
enumName = "scripttype"
95+
break
96+
default:
97+
break
98+
}
99+
return yup("\\(HTMLElementAttribute." + enumName + value + ")")
83100
}
84101
if let function:FunctionCallExprSyntax = expression.as(FunctionCallExprSyntax.self) {
85102
return member("\(function)")

Tests/HTMLKitTests/HTMLKitTests.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,20 @@ extension HTMLKitTests {
2929
XCTAssertEqual(#html([]), "<!DOCTYPE html><html></html>")
3030
XCTAssertEqual(#html(xmlns: "test", []), "<!DOCTYPE html><html xmlns=\"test\"></html>")
3131
}
32+
func test_element_button() {
33+
XCTAssertEqual(#button(type: .submit), "<button type=\"submit\"></button>")
34+
}
3235
func test_element_canvas() {
3336
XCTAssertEqual(#canvas(height: .percent(4), width: .em(2.69)), "<canvas height=\"4.0%\" width=\"2.69em\"></canvas>")
3437
}
3538
func test_element_input() {
36-
let string:String = #input(type: .text)
37-
XCTAssertEqual(string, "<input type=\"text\">")
39+
XCTAssertEqual(#input(type: .text), "<input type=\"text\">")
40+
}
41+
func test_element_ol() {
42+
XCTAssertEqual(#ol(type: .a), "<ol type=\"a\"></ol>")
43+
}
44+
func test_element_script() {
45+
XCTAssertEqual(#script(type: .classic), "<script type=\"classic\"></script>")
3846
}
3947
}
4048

0 commit comments

Comments
 (0)