Skip to content

Commit 0e7a3bf

Browse files
literal expansion logic for the html macro is now publicly available through HTMLKitUtilities.expandHTMLMacro
1 parent d09e6d6 commit 0e7a3bf

File tree

2 files changed

+48
-46
lines changed

2 files changed

+48
-46
lines changed

Sources/HTMLKitMacros/HTMLElement.swift

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,6 @@ import SwiftSyntaxMacros
1212

1313
enum HTMLElementMacro : ExpressionMacro {
1414
static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
15-
let (string, encoding):(String, HTMLEncoding) = expand_macro(context: context, macro: node.macroExpansion!)
16-
func has_no_interpolation() -> Bool {
17-
let has_interpolation:Bool = !string.ranges(of: try! Regex("\\((.*)\\)")).isEmpty
18-
guard !has_interpolation else {
19-
context.diagnose(Diagnostic(node: node, message: DiagnosticMsg(id: "interpolationNotAllowedForDataType", message: "String Interpolation is not allowed for this data type. Runtime values get converted to raw text, which is not the expected result.")))
20-
return false
21-
}
22-
return true
23-
}
24-
func bytes<T: FixedWidthInteger>(_ bytes: [T]) -> String {
25-
return "[" + bytes.map({ "\($0)" }).joined(separator: ",") + "]"
26-
}
27-
switch encoding {
28-
case .utf8Bytes:
29-
guard has_no_interpolation() else { return "" }
30-
return "\(raw: bytes([UInt8](string.utf8)))"
31-
case .utf16Bytes:
32-
guard has_no_interpolation() else { return "" }
33-
return "\(raw: bytes([UInt16](string.utf16)))"
34-
case .utf8CString:
35-
return "\(raw: string.utf8CString)"
36-
37-
case .foundationData:
38-
guard has_no_interpolation() else { return "" }
39-
return "Data(\(raw: bytes([UInt8](string.utf8))))"
40-
41-
case .byteBuffer:
42-
guard has_no_interpolation() else { return "" }
43-
return "ByteBuffer(bytes: \(raw: bytes([UInt8](string.utf8))))"
44-
45-
case .string:
46-
return "\"\(raw: string)\""
47-
case .custom(let encoded):
48-
return "\(raw: encoded.replacingOccurrences(of: "$0", with: string))"
49-
}
50-
}
51-
}
52-
53-
private extension HTMLElementMacro {
54-
// MARK: Expand Macro
55-
static func expand_macro(context: some MacroExpansionContext, macro: MacroExpansionExprSyntax) -> (String, HTMLEncoding) {
56-
guard macro.macroName.text == "html" else {
57-
return ("\(macro)", .string)
58-
}
59-
let data:HTMLKitUtilities.ElementData = HTMLKitUtilities.parseArguments(context: context, children: macro.arguments.children(viewMode: .all))
60-
return (data.innerHTML.map({ String(describing: $0) }).joined(), data.encoding)
15+
return try HTMLKitUtilities.expandHTMLMacro(context: context, macroNode: node.macroExpansion!)
6116
}
6217
}

Sources/HTMLKitUtilities/ParseData.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,44 @@ public extension HTMLKitUtilities {
2424
return String(describing: c)
2525
}).joined()
2626
}
27+
// MARK: Expand #html
28+
static func expandHTMLMacro(context: some MacroExpansionContext, macroNode: MacroExpansionExprSyntax) throws -> ExprSyntax {
29+
let (string, encoding):(String, HTMLEncoding) = expand_macro(context: context, macro: macroNode)
30+
func has_no_interpolation() -> Bool {
31+
let has_interpolation:Bool = !string.ranges(of: try! Regex("\\((.*)\\)")).isEmpty
32+
guard !has_interpolation else {
33+
context.diagnose(Diagnostic(node: macroNode, message: DiagnosticMsg(id: "interpolationNotAllowedForDataType", message: "String Interpolation is not allowed for this data type. Runtime values get converted to raw text, which is not the expected result.")))
34+
return false
35+
}
36+
return true
37+
}
38+
func bytes<T: FixedWidthInteger>(_ bytes: [T]) -> String {
39+
return "[" + bytes.map({ "\($0)" }).joined(separator: ",") + "]"
40+
}
41+
switch encoding {
42+
case .utf8Bytes:
43+
guard has_no_interpolation() else { return "" }
44+
return "\(raw: bytes([UInt8](string.utf8)))"
45+
case .utf16Bytes:
46+
guard has_no_interpolation() else { return "" }
47+
return "\(raw: bytes([UInt16](string.utf16)))"
48+
case .utf8CString:
49+
return "\(raw: string.utf8CString)"
50+
51+
case .foundationData:
52+
guard has_no_interpolation() else { return "" }
53+
return "Data(\(raw: bytes([UInt8](string.utf8))))"
54+
55+
case .byteBuffer:
56+
guard has_no_interpolation() else { return "" }
57+
return "ByteBuffer(bytes: \(raw: bytes([UInt8](string.utf8))))"
58+
59+
case .string:
60+
return "\"\(raw: string)\""
61+
case .custom(let encoded):
62+
return "\(raw: encoded.replacingOccurrences(of: "$0", with: string))"
63+
}
64+
}
2765
// MARK: Parse Arguments
2866
static func parseArguments(
2967
context: some MacroExpansionContext,
@@ -342,6 +380,15 @@ extension HTMLKitUtilities {
342380
context.diagnose(Diagnostic(node: node, message: DiagnosticMsg(id: "unsafeInterpolation", message: "Interpolation may introduce raw HTML.", severity: .warning)))
343381
}
344382
}
383+
384+
// MARK: Expand Macro
385+
static func expand_macro(context: some MacroExpansionContext, macro: MacroExpansionExprSyntax) -> (String, HTMLEncoding) {
386+
guard macro.macroName.text == "html" else {
387+
return ("\(macro)", .string)
388+
}
389+
let data:HTMLKitUtilities.ElementData = HTMLKitUtilities.parseArguments(context: context, children: macro.arguments.children(viewMode: .all))
390+
return (data.innerHTML.map({ String(describing: $0) }).joined(), data.encoding)
391+
}
345392
}
346393

347394
// MARK: Misc

0 commit comments

Comments
 (0)