From 07c642afa5ad6d051d9241b16d6f966810a9a7fe Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 13 May 2023 16:08:31 +0200 Subject: [PATCH 1/3] add escaping with "$" --- Sources/LeafKit/LeafLexer/LeafLexer.swift | 12 +++++++++++- Tests/LeafKitTests/LeafTests.swift | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Sources/LeafKit/LeafLexer/LeafLexer.swift b/Sources/LeafKit/LeafLexer/LeafLexer.swift index 09228fd0..066759f7 100644 --- a/Sources/LeafKit/LeafLexer/LeafLexer.swift +++ b/Sources/LeafKit/LeafLexer/LeafLexer.swift @@ -160,7 +160,7 @@ internal struct LeafLexer { case .comma: return .parameterDelimiter case .quote: - let read = src.readWhile { $0 != .quote && $0 != .newLine } + let read = readWithEscapingQuotes(src: &src) guard src.peek() == .quote else { throw LexerError(.unterminatedStringLiteral, src: src, lexed: lexed) } @@ -269,4 +269,14 @@ internal struct LeafLexer { return .parameter(.variable(name: name)) } } + + private func readWithEscapingQuotes(src: inout LeafRawTemplate) -> String { + let read = src.readWhile { $0 != .quote && $0 != .newLine } + if read.last == "$" && src.peek() == .quote { + src.pop() + return read.dropLast() + "\"" + readWithEscapingQuotes(src: &src) + } else { + return read + } + } } diff --git a/Tests/LeafKitTests/LeafTests.swift b/Tests/LeafKitTests/LeafTests.swift index cc4b17b0..36a7c687 100644 --- a/Tests/LeafKitTests/LeafTests.swift +++ b/Tests/LeafKitTests/LeafTests.swift @@ -191,6 +191,16 @@ final class LeafTests: XCTestCase { try XCTAssertEqual(render(template, [:]), expected) } + func testEscapingQuote() throws { + let template = """ + #("foo $"bar$"") + """ + let expected = """ + foo "bar" + """ + try XCTAssertEqual(render(template), expected) + } + func testCount() throws { let template = """ count: #count(array) From 9e370ed584b602c082aa65db0b923ba7048072b8 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 18 May 2023 20:34:19 +0200 Subject: [PATCH 2/3] Add new constant --- Sources/LeafKit/Exports.swift | 1 + Sources/LeafKit/LeafLexer/LeafLexer.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/LeafKit/Exports.swift b/Sources/LeafKit/Exports.swift index b1503b3c..498bb815 100644 --- a/Sources/LeafKit/Exports.swift +++ b/Sources/LeafKit/Exports.swift @@ -110,4 +110,5 @@ extension Character { static let ampersand = "&".first! static let vertical = "|".first! static let underscore = "_".first! + static let dollarSign = "$".first! } diff --git a/Sources/LeafKit/LeafLexer/LeafLexer.swift b/Sources/LeafKit/LeafLexer/LeafLexer.swift index 066759f7..651865a8 100644 --- a/Sources/LeafKit/LeafLexer/LeafLexer.swift +++ b/Sources/LeafKit/LeafLexer/LeafLexer.swift @@ -272,7 +272,7 @@ internal struct LeafLexer { private func readWithEscapingQuotes(src: inout LeafRawTemplate) -> String { let read = src.readWhile { $0 != .quote && $0 != .newLine } - if read.last == "$" && src.peek() == .quote { + if read.last == .dollarSign && src.peek() == .quote { src.pop() return read.dropLast() + "\"" + readWithEscapingQuotes(src: &src) } else { From 2035ea2470b551c0ff1407470e1ab905177f1cd7 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 13 Jun 2023 21:19:06 +0200 Subject: [PATCH 3/3] Change escaping to double back slash --- Sources/LeafKit/Exports.swift | 1 - Sources/LeafKit/LeafLexer/LeafLexer.swift | 2 +- Tests/LeafKitTests/LeafTests.swift | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/LeafKit/Exports.swift b/Sources/LeafKit/Exports.swift index 498bb815..b1503b3c 100644 --- a/Sources/LeafKit/Exports.swift +++ b/Sources/LeafKit/Exports.swift @@ -110,5 +110,4 @@ extension Character { static let ampersand = "&".first! static let vertical = "|".first! static let underscore = "_".first! - static let dollarSign = "$".first! } diff --git a/Sources/LeafKit/LeafLexer/LeafLexer.swift b/Sources/LeafKit/LeafLexer/LeafLexer.swift index 651865a8..206209a0 100644 --- a/Sources/LeafKit/LeafLexer/LeafLexer.swift +++ b/Sources/LeafKit/LeafLexer/LeafLexer.swift @@ -272,7 +272,7 @@ internal struct LeafLexer { private func readWithEscapingQuotes(src: inout LeafRawTemplate) -> String { let read = src.readWhile { $0 != .quote && $0 != .newLine } - if read.last == .dollarSign && src.peek() == .quote { + if read.last == .backSlash && src.peek() == .quote { src.pop() return read.dropLast() + "\"" + readWithEscapingQuotes(src: &src) } else { diff --git a/Tests/LeafKitTests/LeafTests.swift b/Tests/LeafKitTests/LeafTests.swift index 36a7c687..292ac343 100644 --- a/Tests/LeafKitTests/LeafTests.swift +++ b/Tests/LeafKitTests/LeafTests.swift @@ -193,7 +193,7 @@ final class LeafTests: XCTestCase { func testEscapingQuote() throws { let template = """ - #("foo $"bar$"") + #("foo \\"bar\\"") """ let expected = """ foo "bar"