Skip to content

Commit

Permalink
literal expansion logic for the html macro is now publicly available …
Browse files Browse the repository at this point in the history
…through `HTMLKitUtilities.expandHTMLMacro`
  • Loading branch information
RandomHashTags committed Nov 26, 2024
1 parent d09e6d6 commit 0e7a3bf
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 46 deletions.
47 changes: 1 addition & 46 deletions Sources/HTMLKitMacros/HTMLElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,6 @@ import SwiftSyntaxMacros

enum HTMLElementMacro : ExpressionMacro {
static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
let (string, encoding):(String, HTMLEncoding) = expand_macro(context: context, macro: node.macroExpansion!)
func has_no_interpolation() -> Bool {
let has_interpolation:Bool = !string.ranges(of: try! Regex("\\((.*)\\)")).isEmpty
guard !has_interpolation else {
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.")))
return false
}
return true
}
func bytes<T: FixedWidthInteger>(_ bytes: [T]) -> String {
return "[" + bytes.map({ "\($0)" }).joined(separator: ",") + "]"
}
switch encoding {
case .utf8Bytes:
guard has_no_interpolation() else { return "" }
return "\(raw: bytes([UInt8](string.utf8)))"
case .utf16Bytes:
guard has_no_interpolation() else { return "" }
return "\(raw: bytes([UInt16](string.utf16)))"
case .utf8CString:
return "\(raw: string.utf8CString)"

case .foundationData:
guard has_no_interpolation() else { return "" }
return "Data(\(raw: bytes([UInt8](string.utf8))))"

case .byteBuffer:
guard has_no_interpolation() else { return "" }
return "ByteBuffer(bytes: \(raw: bytes([UInt8](string.utf8))))"

case .string:
return "\"\(raw: string)\""
case .custom(let encoded):
return "\(raw: encoded.replacingOccurrences(of: "$0", with: string))"
}
}
}

private extension HTMLElementMacro {
// MARK: Expand Macro
static func expand_macro(context: some MacroExpansionContext, macro: MacroExpansionExprSyntax) -> (String, HTMLEncoding) {
guard macro.macroName.text == "html" else {
return ("\(macro)", .string)
}
let data:HTMLKitUtilities.ElementData = HTMLKitUtilities.parseArguments(context: context, children: macro.arguments.children(viewMode: .all))
return (data.innerHTML.map({ String(describing: $0) }).joined(), data.encoding)
return try HTMLKitUtilities.expandHTMLMacro(context: context, macroNode: node.macroExpansion!)
}
}
47 changes: 47 additions & 0 deletions Sources/HTMLKitUtilities/ParseData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,44 @@ public extension HTMLKitUtilities {
return String(describing: c)
}).joined()
}
// MARK: Expand #html
static func expandHTMLMacro(context: some MacroExpansionContext, macroNode: MacroExpansionExprSyntax) throws -> ExprSyntax {
let (string, encoding):(String, HTMLEncoding) = expand_macro(context: context, macro: macroNode)
func has_no_interpolation() -> Bool {
let has_interpolation:Bool = !string.ranges(of: try! Regex("\\((.*)\\)")).isEmpty
guard !has_interpolation else {
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.")))
return false
}
return true
}
func bytes<T: FixedWidthInteger>(_ bytes: [T]) -> String {
return "[" + bytes.map({ "\($0)" }).joined(separator: ",") + "]"
}
switch encoding {
case .utf8Bytes:
guard has_no_interpolation() else { return "" }
return "\(raw: bytes([UInt8](string.utf8)))"
case .utf16Bytes:
guard has_no_interpolation() else { return "" }
return "\(raw: bytes([UInt16](string.utf16)))"
case .utf8CString:
return "\(raw: string.utf8CString)"

case .foundationData:
guard has_no_interpolation() else { return "" }
return "Data(\(raw: bytes([UInt8](string.utf8))))"

case .byteBuffer:
guard has_no_interpolation() else { return "" }
return "ByteBuffer(bytes: \(raw: bytes([UInt8](string.utf8))))"

case .string:
return "\"\(raw: string)\""
case .custom(let encoded):
return "\(raw: encoded.replacingOccurrences(of: "$0", with: string))"
}
}
// MARK: Parse Arguments
static func parseArguments(
context: some MacroExpansionContext,
Expand Down Expand Up @@ -342,6 +380,15 @@ extension HTMLKitUtilities {
context.diagnose(Diagnostic(node: node, message: DiagnosticMsg(id: "unsafeInterpolation", message: "Interpolation may introduce raw HTML.", severity: .warning)))
}
}

// MARK: Expand Macro
static func expand_macro(context: some MacroExpansionContext, macro: MacroExpansionExprSyntax) -> (String, HTMLEncoding) {
guard macro.macroName.text == "html" else {
return ("\(macro)", .string)
}
let data:HTMLKitUtilities.ElementData = HTMLKitUtilities.parseArguments(context: context, children: macro.arguments.children(viewMode: .all))
return (data.innerHTML.map({ String(describing: $0) }).joined(), data.encoding)
}
}

// MARK: Misc
Expand Down

0 comments on commit 0e7a3bf

Please sign in to comment.