Skip to content

Commit 4401664

Browse files
chunking logic fix for interpolation; more result type unit tests
1 parent 605c657 commit 4401664

File tree

3 files changed

+154
-73
lines changed

3 files changed

+154
-73
lines changed

Sources/HTMLKitParse/ExpandHTMLMacro.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,33 +228,40 @@ extension HTMLExpansionResultTypeAST {
228228
endingIndex += 1
229229
offset = 1
230230
}
231-
var endIndex = encodedResult.index(encodedResult.startIndex, offsetBy: endingIndex, limitedBy: encodedResult.endIndex) ?? encodedResult.endIndex
232-
let range = encodedResult.index(encodedResult.startIndex, offsetBy: i)..<endIndex
233-
var slice = encodedResult[range]
231+
let sliceStartIndex = encodedResult.index(encodedResult.startIndex, offsetBy: i)
232+
var sliceEndIndex = encodedResult.index(encodedResult.startIndex, offsetBy: endingIndex, limitedBy: encodedResult.endIndex) ?? encodedResult.endIndex
233+
let sliceRange = sliceStartIndex..<sliceEndIndex
234+
var slice = encodedResult[sliceRange]
234235
var interpolation:String? = nil
235-
if let interp = interpolationMatches.first, range.contains(interp.range.lowerBound) { // chunk contains interpolation
236+
if let interp = interpolationMatches.first, sliceRange.contains(interp.range.lowerBound) { // chunk contains interpolation
236237
var normalized = normalizeInterpolation(encodedResult[interp.range], withQuotationMarks: false)
237-
if !range.contains(interp.range.upperBound) {
238-
endIndex = encodedResult.index(before: interp.range.lowerBound)
239-
if slice.startIndex < endIndex {
240-
slice = slice[slice.startIndex..<endIndex]
238+
if !sliceRange.contains(interp.range.upperBound) { // interpolation literal is cut short
239+
sliceEndIndex = encodedResult.index(before: interp.range.lowerBound)
240+
if sliceStartIndex < sliceEndIndex {
241+
slice = slice[sliceStartIndex..<sliceEndIndex]
241242
} else {
242243
slice = ""
243244
normalized = "\"\(normalized)\""
244245
}
245246
interpolation = normalized
246-
i += encodedResult.distance(from: range.upperBound, to: interp.range.upperBound)
247+
i = encodedResult.distance(from: encodedResult.startIndex, to: interp.range.upperBound) + 1
247248
} else {
248249
interpolation = nil
249250
slice.remove(at: interp.range.upperBound) // "
250251
slice.replaceSubrange(interp.range, with: normalized)
251252
slice.remove(at: slice.index(before: interp.range.lowerBound)) // "
252253
}
253254
interpolationMatches.removeFirst()
255+
if slice == "\"" && interpolation != nil {
256+
slice = ""
257+
interpolation = "\"\(interpolation!)\""
258+
}
254259
} else {
255260
interpolation = nil
256261
}
257-
i += chunkSize + offset
262+
if interpolation == nil {
263+
i += chunkSize + offset
264+
}
258265
if slice.isEmpty && interpolation == nil || encoding == .string && slice.count == 1 && slice[slice.startIndex] == "\"" {
259266
continue
260267
}

Tests/HTMLKitTests/HTMLKitTests.swift

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -84,69 +84,6 @@ struct HTMLKitTests {
8484
}*/
8585
}
8686

87-
// MARK: Representations
88-
extension HTMLKitTests {
89-
@Test
90-
func representations() {
91-
let yeah = "yeah"
92-
let _:String = #html(resultType: .literal) {
93-
div("oh yeah")
94-
}
95-
let _:String = #html(resultType: .literal) {
96-
div("oh \(yeah)")
97-
}
98-
/*let _:String = #html(resultType: .literalOptimized) {
99-
div("oh yeah")
100-
}
101-
let _:String = #html(resultType: .literalOptimized) {
102-
div("oh \(yeah)")
103-
}*/
104-
105-
let _:[String] = #html(resultType: .chunks()) {
106-
div("oh yeah")
107-
}
108-
let _:[StaticString] = #html(resultType: .chunks()) {
109-
div("oh yeah")
110-
}
111-
let _:[String] = #html(resultType: .chunks(chunkSize: 3)) {
112-
div("oh \(yeah)")
113-
}
114-
115-
let _:AsyncStream<String> = #html(resultType: .stream()) {
116-
div("oh yeah")
117-
}
118-
let _:AsyncStream<StaticString> = #html(resultType: .stream()) {
119-
div("oh yeah")
120-
}
121-
let _:AsyncStream<String> = #html(resultType: .stream(chunkSize: 3)) {
122-
div("oh yeah")
123-
}
124-
let _:AsyncStream<StaticString> = #html(resultType: .stream(chunkSize: 3)) {
125-
div("oh yeah")
126-
}
127-
let _:AsyncStream<String> = #html(resultType: .stream(chunkSize: 3)) {
128-
div("oh\(yeah)")
129-
}
130-
131-
let _:AsyncStream<String> = #html(resultType: .streamAsync()) {
132-
div("oh yeah")
133-
}
134-
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3)) {
135-
div("oh yeah")
136-
}
137-
let _:AsyncStream<String> = #html(resultType: .streamAsync({ _ in
138-
try await Task.sleep(for: .milliseconds(50))
139-
})) {
140-
div("oh yeah")
141-
}
142-
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3, { _ in
143-
try await Task.sleep(for: .milliseconds(50))
144-
})) {
145-
div("oh yeah")
146-
}
147-
}
148-
}
149-
15087
// MARK: StaticString Example
15188
extension HTMLKitTests {
15289
@Test func example1() {
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
#if compiler(>=6.0)
3+
4+
import HTMLKit
5+
import Testing
6+
7+
@Suite
8+
struct ResultTypeTests {
9+
let yeah = "yeah"
10+
let expected = "<div>oh yeah</div>"
11+
}
12+
13+
// MARK: Literal
14+
extension ResultTypeTests {
15+
@Test
16+
func resultTypeLiteral() {
17+
var literal:String = #html(resultType: .literal) {
18+
div("oh yeah")
19+
}
20+
#expect(literal == expected)
21+
22+
literal = #html(resultType: .literal) {
23+
div("oh \(yeah)")
24+
}
25+
#expect(literal == expected)
26+
27+
literal = #html(resultType: .literal) {
28+
div("oh \(yeah)", yeah)
29+
}
30+
#expect(literal == "<div>oh yeahyeah</div>")
31+
}
32+
}
33+
34+
// MARK: Literal optimized
35+
extension ResultTypeTests {
36+
@Test
37+
func resultTypeLiteralOptimized() {
38+
/*let _:String = #html(resultType: .literalOptimized) {
39+
div("oh yeah")
40+
}
41+
let _:String = #html(resultType: .literalOptimized) {
42+
div("oh \(yeah)")
43+
}*/
44+
}
45+
}
46+
47+
// MARK: Chunks
48+
extension ResultTypeTests {
49+
@Test
50+
func resultTypeChunks() {
51+
let _:[StaticString] = #html(resultType: .chunks()) {
52+
div("oh yeah")
53+
}
54+
55+
let expected = "<div>oh yeah</div>"
56+
var chunks:[String] = #html(resultType: .chunks()) {
57+
div("oh yeah")
58+
}
59+
#expect(chunks == [expected])//
60+
61+
chunks = #html(resultType: .chunks(chunkSize: 3)) {
62+
div("oh \(yeah)")
63+
}
64+
#expect(chunks.joined() == expected)
65+
66+
chunks = #html(resultType: .chunks(chunkSize: 3)) {
67+
div("oh \(yeah)", yeah)
68+
}
69+
#expect(chunks.joined() == "<div>oh yeahyeah</div>")
70+
71+
chunks = #html(resultType: .chunks(chunkSize: 3)) {
72+
div("oh ", yeah, yeah)
73+
}
74+
#expect(chunks.joined() == "<div>oh yeahyeah</div>")
75+
76+
chunks = #html(resultType: .chunks(chunkSize: 3)) {
77+
div("oh ", yeah)
78+
}
79+
#expect(chunks == ["<di", "v>o", "h ", yeah, "</d", "iv>"])
80+
}
81+
}
82+
83+
// MARK: Stream
84+
extension ResultTypeTests {
85+
@Test
86+
func resultTypeStream() {
87+
let _:AsyncStream<String> = #html(resultType: .stream()) {
88+
div("oh yeah")
89+
}
90+
let _:AsyncStream<StaticString> = #html(resultType: .stream()) {
91+
div("oh yeah")
92+
}
93+
let _:AsyncStream<String> = #html(resultType: .stream(chunkSize: 3)) {
94+
div("oh yeah")
95+
}
96+
let _:AsyncStream<StaticString> = #html(resultType: .stream(chunkSize: 3)) {
97+
div("oh yeah")
98+
}
99+
let _:AsyncStream<String> = #html(resultType: .stream(chunkSize: 3)) {
100+
div("oh \(yeah)")
101+
}
102+
let _:AsyncStream<String> = #html(resultType: .stream(chunkSize: 3)) {
103+
div("oh \(yeah)", yeah)
104+
}
105+
}
106+
}
107+
108+
// MARK: Stream async
109+
extension ResultTypeTests {
110+
@Test
111+
func resultTypeStreamAsync() {
112+
let _:AsyncStream<String> = #html(resultType: .streamAsync()) {
113+
div("oh yeah")
114+
}
115+
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3)) {
116+
div("oh yeah")
117+
}
118+
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3)) {
119+
div("oh \(yeah)")
120+
}
121+
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3)) {
122+
div("oh \(yeah)", yeah)
123+
}
124+
let _:AsyncStream<String> = #html(resultType: .streamAsync({ _ in
125+
try await Task.sleep(for: .milliseconds(50))
126+
})) {
127+
div("oh yeah")
128+
}
129+
let _:AsyncStream<String> = #html(resultType: .streamAsync(chunkSize: 3, { _ in
130+
try await Task.sleep(for: .milliseconds(50))
131+
})) {
132+
div("oh yeah")
133+
}
134+
}
135+
}
136+
137+
#endif

0 commit comments

Comments
 (0)