Skip to content

Commit 96c4b79

Browse files
almost got it completely working...
1 parent e4e5085 commit 96c4b79

File tree

7 files changed

+259
-300
lines changed

7 files changed

+259
-300
lines changed

Sources/HTMLKitUtilities/HTMLElementAttribute.swift

Lines changed: 43 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// Created by Evan Anderson on 11/19/24.
66
//
77

8+
import SwiftSyntax
9+
810
public enum HTMLElementAttribute : Hashable {
911
case accesskey(String? = nil)
1012

@@ -55,15 +57,18 @@ public enum HTMLElementAttribute : Hashable {
5557
@available(*, deprecated, message: "General consensus considers this \"bad practice\" and you shouldn't mix your HTML and JavaScript. This will never be removed and remains deprecated to encourage use of other techniques. Learn more at https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_—_dont_use_these.")
5658
case event(Extra.event, _ value: String? = nil)
5759

58-
public init?(rawValue: String) {
59-
guard rawValue.last == ")" else { return nil }
60-
let key:Substring = rawValue.split(separator: "(")[0]
61-
func string() -> String { HTMLElementAttribute.string(key: key, rawValue: rawValue) }
62-
func boolean() -> Bool { HTMLElementAttribute.boolean(key: key, rawValue: rawValue) }
63-
func enumeration<T : HTMLInitializable>() -> T { HTMLElementAttribute.enumeration(key: key, rawValue: rawValue) }
64-
func int() -> Int { HTMLElementAttribute.int(key: key, rawValue: rawValue) }
65-
func array_string() -> [String] { HTMLElementAttribute.array_string(key: key, rawValue: rawValue) }
66-
func float() -> Float { HTMLElementAttribute.float(key: key, rawValue: rawValue) }
60+
// MARK: init rawValue
61+
public init?(key: String, _ function: FunctionCallExprSyntax) {
62+
let expression:ExprSyntax = function.arguments.first!.expression
63+
func string() -> String { expression.stringLiteral!.string }
64+
func boolean() -> Bool { expression.booleanLiteral!.literal.text == "true" }
65+
func enumeration<T : HTMLInitializable>() -> T {
66+
let function:FunctionCallExprSyntax = expression.functionCall!
67+
return T(key: function.calledExpression.memberAccess!.declName.baseName.text, arguments: function.arguments)!
68+
}
69+
func int() -> Int { Int(expression.integerLiteral!.literal.text) ?? -1 }
70+
func array_string() -> [String] { expression.array!.elements.map({ $0.expression.stringLiteral!.string }) }
71+
func float() -> Float { Float(expression.floatLiteral!.literal.text) ?? -1 }
6772
switch key {
6873
case "accesskey": self = .accesskey(string())
6974
case "ariaattribute": self = .ariaattribute(enumeration())
@@ -107,6 +112,7 @@ public enum HTMLElementAttribute : Hashable {
107112
}
108113
}
109114

115+
// MARK: key
110116
public var key : String {
111117
switch self {
112118
case .accesskey(_): return "accesskey"
@@ -162,6 +168,7 @@ public enum HTMLElementAttribute : Hashable {
162168
}
163169
}
164170

171+
// MARK: htmlValue
165172
public var htmlValue : String? {
166173
switch self {
167174
case .accesskey(let value): return value
@@ -211,55 +218,27 @@ public enum HTMLElementAttribute : Hashable {
211218
extension HTMLElementAttribute {
212219
public enum Extra {
213220
}
214-
215-
static func literal(key: Substring, rawValue: String) -> String {
216-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex)
217-
return String(rawValue[rawValue.index(start, offsetBy: key.count + 2)..<end])
218-
}
219-
static func string(key: Substring, rawValue: String) -> String {
220-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex), end_minus_one:String.Index = rawValue.index(before: end)
221-
return String(rawValue[rawValue.index(start, offsetBy: key.count + 2)..<end_minus_one])
222-
}
223-
static func boolean(key: Substring, rawValue: String) -> Bool {
224-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex)
225-
return rawValue[rawValue.index(start, offsetBy: key.count + 1)..<end] == "true"
226-
}
227-
static func enumeration<T : HTMLInitializable>(key: Substring, rawValue: String) -> T {
228-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex)
229-
return T(rawValue: String(rawValue[rawValue.index(start, offsetBy: key.count + 2)..<end]))!
230-
}
231-
static func int(key: Substring, rawValue: String) -> Int {
232-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex)
233-
return Int(rawValue[rawValue.index(start, offsetBy: key.count + 1)..<end])!
234-
}
235-
static func array_string(key: Substring, rawValue: String) -> [String] {
236-
let string:String = string(key: key, rawValue: rawValue)
237-
let ranges:[Range<String.Index>] = try! string.ranges(of: Regex("\"([^\"]+)\"")) // TODO: fix? (doesn't parse correctly if the string contains escaped quotation marks)
238-
return ranges.map({
239-
let item:String = String(string[$0])
240-
return String(item[item.index(after: item.startIndex)..<item.index(before: item.endIndex)])
241-
})
242-
}
243-
static func float(key: Substring, rawValue: String) -> Float {
244-
let start:String.Index = rawValue.startIndex, end:String.Index = rawValue.index(before: rawValue.endIndex)
245-
return Float(rawValue[rawValue.index(start, offsetBy: key.count + 1)..<end])!
246-
}
247221
}
248222
public protocol HTMLInitializable : Hashable {
249-
init?(rawValue: String)
223+
init?(key: String, arguments: LabeledExprListSyntax)
250224

251225
var key : String { get }
252226
var htmlValue : String? { get }
253227
}
254228
public extension HTMLInitializable where Self: RawRepresentable, RawValue == String {
255229
var key : String { rawValue }
256230
var htmlValue : String? { rawValue }
231+
232+
init?(key: String, arguments: LabeledExprListSyntax) {
233+
guard let value:Self = .init(rawValue: key) else { return nil }
234+
self = value
235+
}
257236
}
258237
public extension HTMLElementAttribute.Extra {
259238
typealias height = HTMLElementAttribute.CSSUnit
260239
typealias width = HTMLElementAttribute.CSSUnit
261240

262-
// MARK: aria attributes (states and properties)
241+
// MARK: aria attributes
263242
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes
264243
enum ariaattribute : HTMLInitializable {
265244
case activedescendant(String)
@@ -333,15 +312,17 @@ public extension HTMLElementAttribute.Extra {
333312
case valuenow(Float)
334313
case valuetext(String)
335314

336-
public init?(rawValue: String) {
337-
guard rawValue.last == ")" else { return nil }
338-
let key:Substring = rawValue.split(separator: "(")[0]
339-
func string() -> String { HTMLElementAttribute.string(key: key, rawValue: rawValue) }
340-
func boolean() -> Bool { HTMLElementAttribute.boolean(key: key, rawValue: rawValue) }
341-
func enumeration<T : HTMLInitializable>() -> T { HTMLElementAttribute.enumeration(key: key, rawValue: rawValue) }
342-
func int() -> Int { HTMLElementAttribute.int(key: key, rawValue: rawValue) }
343-
func array_string() -> [String] { HTMLElementAttribute.array_string(key: key, rawValue: rawValue) }
344-
func float() -> Float { HTMLElementAttribute.float(key: key, rawValue: rawValue) }
315+
public init?(key: String, arguments: LabeledExprListSyntax) {
316+
let expression:ExprSyntax = arguments.first!.expression
317+
func string() -> String { expression.stringLiteral!.string }
318+
func boolean() -> Bool { expression.booleanLiteral!.literal.text == "true" }
319+
func enumeration<T : HTMLInitializable>() -> T {
320+
let function:FunctionCallExprSyntax = expression.functionCall!
321+
return T(key: function.calledExpression.memberAccess!.declName.baseName.text, arguments: function.arguments)!
322+
}
323+
func int() -> Int { Int(expression.integerLiteral!.literal.text) ?? -1 }
324+
func array_string() -> [String] { expression.array!.elements.map({ $0.expression.stringLiteral!.string }) }
325+
func float() -> Float { Float(expression.floatLiteral!.literal.text) ?? -1 }
345326
switch key {
346327
case "activedescendant": self = .activedescendant(string())
347328
case "atomic": self = .atomic(boolean())
@@ -723,20 +704,15 @@ public extension HTMLElementAttribute.Extra {
723704
case togglePopover
724705
case custom(String)
725706

726-
public init?(rawValue: String) {
727-
switch rawValue {
707+
public init?(key: String, arguments: LabeledExprListSyntax) {
708+
switch key {
728709
case "showModal": self = .showModal
729710
case "close": self = .close
730711
case "showPopover": self = .showPopover
731712
case "hidePopover": self = .hidePopover
732713
case "togglePopover": self = .togglePopover
733-
default:
734-
if rawValue.starts(with: "custom(\"") && rawValue.hasSuffix("\")") {
735-
let value:String = String(rawValue[rawValue.index(rawValue.startIndex, offsetBy: 8)..<rawValue.index(rawValue.endIndex, offsetBy: -2)])
736-
self = .custom(value)
737-
} else {
738-
return nil
739-
}
714+
case "custom": self = .custom(arguments.first!.expression.stringLiteral!.string)
715+
default: return nil
740716
}
741717
}
742718

@@ -819,16 +795,11 @@ public extension HTMLElementAttribute.Extra {
819795
case empty
820796
case filename(String)
821797

822-
public init?(rawValue: String) {
823-
if rawValue == "empty" {
824-
self = .empty
825-
} else {
826-
if rawValue.starts(with: "filename(\"") && rawValue.hasSuffix("\")") {
827-
let value:String = String(rawValue[rawValue.index(rawValue.startIndex, offsetBy: 10)..<rawValue.index(rawValue.endIndex, offsetBy: -2)])
828-
self = .filename(value)
829-
} else {
830-
return nil
831-
}
798+
public init?(key: String, arguments: LabeledExprListSyntax) {
799+
switch key {
800+
case "empty": self = .empty
801+
case "filename": self = .filename(arguments.first!.expression.stringLiteral!.string)
802+
default: return nil
832803
}
833804
}
834805

0 commit comments

Comments
 (0)