Skip to content

Commit 0b9beea

Browse files
fixed multiline functions and members now get interpolated correctly
- they previously broke string declarations
1 parent 2bd2705 commit 0b9beea

File tree

2 files changed

+148
-9
lines changed

2 files changed

+148
-9
lines changed

Sources/HTMLKitUtilities/ParseData.swift

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,10 @@ extension HTMLKitUtilities {
295295
break
296296
}
297297
}
298-
return .interpolation("\(function)")
298+
return .interpolation(merge_func_into_single_line(function))
299299
}
300300
if let member:MemberAccessExprSyntax = expression.memberAccess {
301-
return .interpolation("\(member)")
301+
return .interpolation(merge_member_into_single_line(member))
302302
}
303303
if let array:ArrayExprSyntax = expression.array {
304304
let separator:String
@@ -389,6 +389,53 @@ extension HTMLKitUtilities {
389389
let data:HTMLKitUtilities.ElementData = HTMLKitUtilities.parseArguments(context: context, children: macro.arguments.children(viewMode: .all))
390390
return (data.innerHTML.map({ String(describing: $0) }).joined(), data.encoding)
391391
}
392+
393+
// MARK: Merge
394+
static func merge_member_into_single_line(_ member: MemberAccessExprSyntax) -> String {
395+
var string:String = "\(member)"
396+
string.removeAll { $0.isWhitespace }
397+
return string
398+
}
399+
static func merge_func_into_single_line(_ function: FunctionCallExprSyntax) -> String {
400+
var string:String = "\(function.calledExpression)"
401+
string.removeAll { $0.isWhitespace }
402+
var args:String = ""
403+
var is_first:Bool = true
404+
for argument in function.arguments {
405+
var arg:String
406+
if let label = argument.label {
407+
arg = "\(label)"
408+
while arg.first?.isWhitespace ?? false {
409+
arg.removeFirst()
410+
}
411+
if !is_first {
412+
arg.insert(",", at: arg.startIndex)
413+
}
414+
arg += ": "
415+
var expr:String
416+
if let f:FunctionCallExprSyntax = argument.expression.functionCall {
417+
expr = merge_func_into_single_line(f)
418+
} else if let m:MemberAccessExprSyntax = argument.expression.memberAccess {
419+
expr = merge_member_into_single_line(m)
420+
} else {
421+
expr = "\(argument.expression)"
422+
}
423+
while expr.first?.isWhitespace ?? false {
424+
expr.removeFirst()
425+
}
426+
arg += expr
427+
} else {
428+
arg = "\(argument)"
429+
while arg.first?.isWhitespace ?? false {
430+
arg.removeFirst()
431+
}
432+
}
433+
args += arg
434+
is_first = false
435+
}
436+
args = "(" + args + ")"
437+
return string + args
438+
}
392439
}
393440

394441
// MARK: Misc

Tests/HTMLKitTests/InterpolationTests.swift

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,94 @@ struct InterpolationTests {
1919
#expect(string == "<a href=\"\(test)\">Test</a>")
2020
}
2121

22-
@Test func multiline_with_interpolation() {
23-
let test:String = "again"
22+
@Test func multiline_decl_interpolation() {
23+
let test:String = "prophecy"
2424
let string:String = #html(
2525
div(
2626
"dune ",
2727
test
2828
)
2929
)
30-
#expect(string == "<div>dune again</div>")
30+
#expect(string == "<div>dune prophecy</div>")
31+
}
32+
33+
@Test func multiline_func_interpolation() {
34+
var string:String = #html(
35+
div(
36+
"Bikini Bottom: ",
37+
InterpolationTests.spongebobCharacter(
38+
"spongebob"
39+
),
40+
", ",
41+
InterpolationTests.spongebobCharacter("patrick"
42+
),
43+
", ",
44+
InterpolationTests.spongebobCharacter(
45+
"squidward"),
46+
", ",
47+
InterpolationTests
48+
.spongebobCharacter(
49+
"krabs"
50+
),
51+
", ",
52+
InterpolationTests.sandyCheeks (),
53+
", ",
54+
InterpolationTests
55+
.spongebobCharacter(
56+
"pearl krabs"
57+
)
58+
)
59+
)
60+
#expect(string == "<div>Bikini Bottom: Spongebob Squarepants, Patrick Star, Squidward Tentacles, Mr. Krabs, Sandy Cheeks, Pearl Krabs</div>")
61+
62+
string = #html(
63+
div(
64+
"Don't forget ",
65+
InterpolationTests.BikiniBottom.gary(),
66+
"!"
67+
)
68+
)
69+
#expect(string == "<div>Don&#39t forget Gary!</div>")
70+
71+
string = #html(
72+
div(
73+
InterpolationTests
74+
.spongebob(
75+
isBoob:false,
76+
isSquare:
77+
true,
78+
middleName: Shrek
79+
.isLife
80+
.rawValue,
81+
lastName: InterpolationTests
82+
.sandyCheeks()
83+
)
84+
)
85+
)
86+
#expect(string == "<div>Spongeboob</div>")
87+
}
88+
89+
@Test func multiline_member_interpolation() {
90+
var string:String = #html(
91+
div(
92+
"Shrek ",
93+
Shrek.isLove.rawValue,
94+
", Shrek ",
95+
Shrek
96+
.isLife.rawValue
97+
)
98+
)
99+
#expect(string == "<div>Shrek isLove, Shrek isLife</div>")
100+
101+
string = #html(
102+
div(
103+
"Shrek ",
104+
InterpolationTests.Shrek.isLove.rawValue,
105+
", Shrek ",
106+
InterpolationTests.Shrek.isLife.rawValue
107+
)
108+
)
109+
#expect(string == "<div>Shrek isLove, Shrek isLife</div>")
31110
}
32111

33112
@Test func flatten() {
@@ -72,15 +151,28 @@ extension InterpolationTests {
72151
}
73152

74153
extension InterpolationTests {
154+
enum BikiniBottom {
155+
static func gary() -> String { "Gary" }
156+
}
75157
static let spongebob:String = "Spongebob Squarepants"
76158
static let patrick:String = "Patrick Star"
77159
static func spongebobCharacter(_ string: String) -> String {
78160
switch string {
79161
case "spongebob": return "Spongebob Squarepants"
80162
case "patrick": return "Patrick Star"
163+
case "squidward": return "Squidward Tentacles"
164+
case "krabs": return "Mr. Krabs"
165+
case "pearl krabs": return "Pearl Krabs"
166+
case "karen": return "Karen"
81167
default: return "Plankton"
82168
}
83169
}
170+
static func sandyCheeks() -> String {
171+
return "Sandy Cheeks"
172+
}
173+
static func spongebob(isBoob: Bool, isSquare: Bool, middleName: String, lastName: String) -> String {
174+
return "Spongeboob"
175+
}
84176

85177
@Test func third_party_literal() {
86178
var string:String = #html(div(attributes: [.title(InterpolationTests.spongebob)]))
@@ -89,11 +181,11 @@ extension InterpolationTests {
89181
string = #html(div(attributes: [.title(InterpolationTests.patrick)]))
90182
#expect(string == "<div title=\"Patrick Star\"></div>")
91183

92-
var static_string:StaticString = #html(div(attributes: [.title("Mr. Crabs")]))
93-
#expect(static_string == "<div title=\"Mr. Crabs\"></div>")
184+
var static_string:StaticString = #html(div(attributes: [.title("Mr. Krabs")]))
185+
#expect(static_string == "<div title=\"Mr. Krabs\"></div>")
94186

95-
static_string = #html(div(attributes: [.title("Mr. Crabs")]))
96-
#expect(static_string == "<div title=\"Mr. Crabs\"></div>")
187+
static_string = #html(div(attributes: [.title("Mr. Krabs")]))
188+
#expect(static_string == "<div title=\"Mr. Krabs\"></div>")
97189
}
98190
@Test func third_party_func() {
99191
let string:String = #html(div(attributes: [.title(InterpolationTests.spongebobCharacter("patrick"))]))

0 commit comments

Comments
 (0)