Skip to content

Commit 65e1fb3

Browse files
update unit tests; now begins the fixing
1 parent 8922cf3 commit 65e1fb3

File tree

12 files changed

+1411
-863
lines changed

12 files changed

+1411
-863
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,7 @@ Tags.*
3030
XmlRender.*
3131
InterpolationLookup.d
3232
InterpolationLookup.o
33-
InterpolationLookup.swiftdeps*
33+
InterpolationLookup.swiftdeps*
34+
LiteralElements.d
35+
LiteralElements.o
36+
LiteralElements.swiftdeps*

Sources/HTMLKit/HTMLKit.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Created by Evan Anderson on 9/14/24.
66
//
77

8-
import HTMLKitUtilities
8+
@_exported import HTMLKitUtilities
99

1010
#if canImport(Foundation)
1111
import struct Foundation.Data
@@ -25,35 +25,35 @@ public extension StringProtocol {
2525
}
2626

2727
@freestanding(expression)
28-
public macro escapeHTML<T: ExpressibleByStringLiteral>(_ innerHTML: T...) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
28+
public macro escapeHTML<T: ExpressibleByStringLiteral>(_ innerHTML: T...) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
2929

3030
// MARK: HTML Representation
3131
@freestanding(expression)
3232
public macro html<T: ExpressibleByStringLiteral>(
3333
lookupFiles: [StaticString] = [],
3434
attributes: [HTMLElementAttribute] = [],
3535
xmlns: T? = nil,
36-
_ innerHTML: HTML...
37-
) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
36+
_ innerHTML: HTMLElement...
37+
) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
3838

3939
@freestanding(expression)
40-
public macro htmlUTF8Bytes<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> [UInt8] = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
40+
public macro htmlUTF8Bytes<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> [UInt8] = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
4141

4242
@freestanding(expression)
43-
public macro htmlUTF16Bytes<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> [UInt16] = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
43+
public macro htmlUTF16Bytes<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> [UInt16] = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
4444

4545
@freestanding(expression)
46-
public macro htmlUTF8CString<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> ContiguousArray<CChar> = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
46+
public macro htmlUTF8CString<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> ContiguousArray<CChar> = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
4747

4848
#if canImport(Foundation)
4949
@freestanding(expression)
50-
public macro htmlData<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> Data = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
50+
public macro htmlData<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> Data = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
5151
#endif
5252

5353
@freestanding(expression)
54-
public macro htmlByteBuffer<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> ByteBuffer = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
54+
public macro htmlByteBuffer<T: ExpressibleByStringLiteral>(lookupFiles: [StaticString] = [], attributes: [HTMLElementAttribute] = [], xmlns: T? = nil, _ innerHTML: T...) -> ByteBuffer = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")
5555

5656
// MARK: Elements
5757

5858
@freestanding(expression)
59-
public macro custom<T: ExpressibleByStringLiteral>(tag: String, isVoid: Bool, attributes: [HTMLElementAttribute] = [], _ innerHTML: T...) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElement")
59+
public macro custom<T: ExpressibleByStringLiteral>(tag: String, isVoid: Bool, attributes: [HTMLElementAttribute] = [], _ innerHTML: T...) -> T = #externalMacro(module: "HTMLKitMacros", type: "HTMLElementMacro")

Sources/HTMLKitMacros/HTMLElement.swift

Lines changed: 148 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import struct Foundation.Data
1616

1717
import struct NIOCore.ByteBuffer
1818

19-
enum HTMLElement : ExpressionMacro {
19+
enum HTMLElementMacro : ExpressionMacro {
2020
static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> ExprSyntax {
2121
let string:String = expand_macro(context: context, macro: node.macroExpansion!)
2222
var set:Set<HTMLElementType?> = [.htmlUTF8Bytes, .htmlUTF16Bytes, .htmlUTF8CString, .htmlByteBuffer]
@@ -58,7 +58,7 @@ enum HTMLElement : ExpressionMacro {
5858
}
5959
}
6060

61-
private extension HTMLElement {
61+
private extension HTMLElementMacro {
6262
// MARK: Expand Macro
6363
static func expand_macro(context: some MacroExpansionContext, macro: MacroExpansionExprSyntax) -> String {
6464
guard let elementType:HTMLElementType = HTMLElementType(rawValue: macro.macroName.text) else {
@@ -385,8 +385,17 @@ private extension HTMLElement {
385385
value = HTMLElementAttribute.Extra.htmlValue(enumName: enumName(elementType: elementType, key: key), for: value)
386386
return (value, .enumCase)
387387
} else {
388-
if function.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text == "StaticString" {
389-
return (function.arguments.first!.expression.stringLiteral!.string, .string)
388+
if let decl:String = function.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text {
389+
switch decl {
390+
case "StaticString":
391+
return (function.arguments.first!.expression.stringLiteral!.string, .string)
392+
default:
393+
if let element:HTMLElement = parse(rawValue: "\(function.calledExpression)") {
394+
let string:String = element.description
395+
return (string, string.contains("\\(") ? .interpolation : .string)
396+
}
397+
break
398+
}
390399
}
391400
return ("\(function)", .interpolation)
392401
}
@@ -533,18 +542,18 @@ extension HTMLElementAttribute.Extra {
533542
static func htmlValue(enumName: String, for enumCase: String) -> String { // only need to check the ones where the htmlValue is different from the rawValue
534543
switch enumName {
535544
case "ariaattribute": return ariaattribute(rawValue: enumCase)?.htmlValue ?? "???"
536-
case "command": return command(rawValue: enumCase)!.htmlValue
537-
case "contenteditable": return contenteditable(rawValue: enumCase)!.htmlValue
538-
case "crossorigin": return crossorigin(rawValue: enumCase)!.htmlValue
539-
case "download": return download(rawValue: enumCase)!.htmlValue
540-
case "formenctype": return formenctype(rawValue: enumCase)!.htmlValue
541-
case "hidden": return hidden(rawValue: enumCase)!.htmlValue
542-
case "httpequiv": return httpequiv(rawValue: enumCase)!.htmlValue
543-
case "inputtype": return inputtype(rawValue: enumCase)!.htmlValue
544-
case "numberingtype": return numberingtype(rawValue: enumCase)!.htmlValue
545-
case "referrerpolicy": return referrerpolicy(rawValue: enumCase)!.htmlValue
546-
case "rel": return rel(rawValue: enumCase)!.htmlValue
547-
case "sandbox": return sandbox(rawValue: enumCase)!.htmlValue
545+
case "command": return command(rawValue: enumCase)!.htmlValue!
546+
case "contenteditable": return contenteditable(rawValue: enumCase)!.htmlValue!
547+
case "crossorigin": return crossorigin(rawValue: enumCase)!.htmlValue!
548+
case "download": return download(rawValue: enumCase)!.htmlValue!
549+
case "formenctype": return formenctype(rawValue: enumCase)!.htmlValue!
550+
case "hidden": return hidden(rawValue: enumCase)!.htmlValue!
551+
case "httpequiv": return httpequiv(rawValue: enumCase)!.htmlValue!
552+
case "inputtype": return inputtype(rawValue: enumCase)!.htmlValue!
553+
case "numberingtype": return numberingtype(rawValue: enumCase)!.htmlValue!
554+
case "referrerpolicy": return referrerpolicy(rawValue: enumCase)!.htmlValue!
555+
case "rel": return rel(rawValue: enumCase)!.htmlValue!
556+
case "sandbox": return sandbox(rawValue: enumCase)!.htmlValue!
548557
case "height", "width":
549558
let values:[Substring] = enumCase.split(separator: "("), key:String = String(values[0]), value:String = String(values[1])
550559
return value[value.startIndex..<value.index(before: value.endIndex)] + CSSUnitType(rawValue: key)!.suffix
@@ -592,3 +601,126 @@ extension HTMLElementAttribute.Extra {
592601
}
593602
}
594603
}
604+
605+
// MARK: Parse from rawValue
606+
extension HTMLElementMacro {
607+
static func parse(rawValue: String) -> HTMLElement? {
608+
guard let key:Substring = rawValue.split(separator: "(").first else { return nil }
609+
switch key {
610+
case "a": return a(rawValue: rawValue)
611+
case "abbr": return abbr(rawValue: rawValue)
612+
case "address": return address(rawValue: rawValue)
613+
case "area": return area(rawValue: rawValue)
614+
case "article": return article(rawValue: rawValue)
615+
case "aside": return aside(rawValue: rawValue)
616+
case "audio": return audio(rawValue: rawValue)
617+
case "b": return b(rawValue: rawValue)
618+
case "base": return base(rawValue: rawValue)
619+
case "bdi": return bdi(rawValue: rawValue)
620+
case "bdo": return bdo(rawValue: rawValue)
621+
case "blockquote": return blockquote(rawValue: rawValue)
622+
case "body": return body(rawValue: rawValue)
623+
case "br": return br(rawValue: rawValue)
624+
case "button": return button(rawValue: rawValue)
625+
case "canvas": return canvas(rawValue: rawValue)
626+
case "caption": return caption(rawValue: rawValue)
627+
case "cite": return cite(rawValue: rawValue)
628+
case "code": return code(rawValue: rawValue)
629+
case "col": return col(rawValue: rawValue)
630+
case "colgroup": return colgroup(rawValue: rawValue)
631+
case "data": return data(rawValue: rawValue)
632+
case "datalist": return datalist(rawValue: rawValue)
633+
case "dd": return dd(rawValue: rawValue)
634+
case "del": return del(rawValue: rawValue)
635+
case "details": return details(rawValue: rawValue)
636+
case "dfn": return dfn(rawValue: rawValue)
637+
case "dialog": return dialog(rawValue: rawValue)
638+
case "div": return div(rawValue: rawValue)
639+
case "dl": return dl(rawValue: rawValue)
640+
case "dt": return dt(rawValue: rawValue)
641+
case "em": return em(rawValue: rawValue)
642+
case "embed": return embed(rawValue: rawValue)
643+
case "fencedframe": return fencedframe(rawValue: rawValue)
644+
case "fieldset": return fieldset(rawValue: rawValue)
645+
case "figcaption": return figcaption(rawValue: rawValue)
646+
case "figure": return figure(rawValue: rawValue)
647+
case "footer": return footer(rawValue: rawValue)
648+
case "form": return form(rawValue: rawValue)
649+
case "h1": return h1(rawValue: rawValue)
650+
case "h2": return h2(rawValue: rawValue)
651+
case "h3": return h3(rawValue: rawValue)
652+
case "h4": return h4(rawValue: rawValue)
653+
case "h5": return h5(rawValue: rawValue)
654+
case "h6": return h6(rawValue: rawValue)
655+
case "head": return head(rawValue: rawValue)
656+
case "header": return header(rawValue: rawValue)
657+
case "hgroup": return hgroup(rawValue: rawValue)
658+
case "hr": return hr(rawValue: rawValue)
659+
case "i": return i(rawValue: rawValue)
660+
case "iframe": return iframe(rawValue: rawValue)
661+
case "img": return img(rawValue: rawValue)
662+
case "input": return input(rawValue: rawValue)
663+
case "ins": return ins(rawValue: rawValue)
664+
case "kbd": return kbd(rawValue: rawValue)
665+
case "label": return label(rawValue: rawValue)
666+
case "legend": return legend(rawValue: rawValue)
667+
case "li": return li(rawValue: rawValue)
668+
case "link": return link(rawValue: rawValue)
669+
case "main": return main(rawValue: rawValue)
670+
case "map": return map(rawValue: rawValue)
671+
case "mark": return mark(rawValue: rawValue)
672+
case "menu": return menu(rawValue: rawValue)
673+
case "meta": return meta(rawValue: rawValue)
674+
case "meter": return meter(rawValue: rawValue)
675+
case "nav": return nav(rawValue: rawValue)
676+
case "noscript": return noscript(rawValue: rawValue)
677+
case "object": return object(rawValue: rawValue)
678+
case "ol": return ol(rawValue: rawValue)
679+
case "optgroup": return optgroup(rawValue: rawValue)
680+
case "option": return option(rawValue: rawValue)
681+
case "output": return output(rawValue: rawValue)
682+
case "p": return p(rawValue: rawValue)
683+
case "picture": return picture(rawValue: rawValue)
684+
case "portal": return portal(rawValue: rawValue)
685+
case "pre": return pre(rawValue: rawValue)
686+
case "progress": return progress(rawValue: rawValue)
687+
case "q": return q(rawValue: rawValue)
688+
case "rp": return rp(rawValue: rawValue)
689+
case "rt": return rt(rawValue: rawValue)
690+
case "ruby": return ruby(rawValue: rawValue)
691+
case "s": return s(rawValue: rawValue)
692+
case "samp": return samp(rawValue: rawValue)
693+
case "script": return script(rawValue: rawValue)
694+
case "search": return search(rawValue: rawValue)
695+
case "section": return section(rawValue: rawValue)
696+
case "select": return select(rawValue: rawValue)
697+
case "slot": return slot(rawValue: rawValue)
698+
case "small": return small(rawValue: rawValue)
699+
case "source": return source(rawValue: rawValue)
700+
case "span": return span(rawValue: rawValue)
701+
case "strong": return strong(rawValue: rawValue)
702+
case "style": return style(rawValue: rawValue)
703+
case "sub": return sub(rawValue: rawValue)
704+
case "summary": return summary(rawValue: rawValue)
705+
case "sup": return sup(rawValue: rawValue)
706+
case "table": return table(rawValue: rawValue)
707+
case "tbody": return tbody(rawValue: rawValue)
708+
case "td": return td(rawValue: rawValue)
709+
case "template": return template(rawValue: rawValue)
710+
case "textarea": return textarea(rawValue: rawValue)
711+
case "tfoot": return tfoot(rawValue: rawValue)
712+
case "th": return th(rawValue: rawValue)
713+
case "thead": return thead(rawValue: rawValue)
714+
case "time": return time(rawValue: rawValue)
715+
case "title": return title(rawValue: rawValue)
716+
case "tr": return tr(rawValue: rawValue)
717+
case "track": return track(rawValue: rawValue)
718+
case "u": return u(rawValue: rawValue)
719+
case "ul": return ul(rawValue: rawValue)
720+
//case "var": return var(rawValue: rawValue)
721+
case "video": return video(rawValue: rawValue)
722+
case "wbr": return wbr(rawValue: rawValue)
723+
default: return nil
724+
}
725+
}
726+
}

Sources/HTMLKitMacros/HTMLKitMacros.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ extension DiagnosticMsg : FixItMessage {
2929
@main
3030
struct HTMLKitMacros : CompilerPlugin {
3131
let providingMacros:[any Macro.Type] = [
32-
HTMLElement.self
32+
HTMLElementMacro.self
3333
]
3434
}

0 commit comments

Comments
 (0)