diff --git a/docs/themes/navy/layout/partial/all-contributors.swig b/docs/themes/navy/layout/partial/all-contributors.swig
index 64804020fc..1524163497 100644
--- a/docs/themes/navy/layout/partial/all-contributors.swig
+++ b/docs/themes/navy/layout/partial/all-contributors.swig
@@ -67,6 +67,7 @@
![BaNgan](https://avatars.githubusercontent.com/u/10071857?v=4?s=100) |
![Mahyar Pasarzangene](https://avatars.githubusercontent.com/u/16485039?v=4?s=100) |
![Tomáš Hübelbauer](https://avatars.githubusercontent.com/u/6831144?v=4?s=100) |
+ ![Jason Garber](https://avatars.githubusercontent.com/u/73866?v=4?s=100) |
diff --git a/src/parser/tokenizer.spec.ts b/src/parser/tokenizer.spec.ts
index f66f803563..4719ad5d77 100644
--- a/src/parser/tokenizer.spec.ts
+++ b/src/parser/tokenizer.spec.ts
@@ -199,15 +199,6 @@ describe('Tokenizer', function () {
})
})
describe('#readTagToken()', () => {
- it('should skip quoted delimiters', function () {
- const html = '{% assign a = "%} {% }} {{" %}'
- const tokenizer = new Tokenizer(html)
- const token = tokenizer.readTagToken()
-
- expect(token).toBeInstanceOf(TagToken)
- expect(token.name).toBe('assign')
- expect(token.args).toBe('a = "%} {% }} {{"')
- })
})
describe('#readOutputToken()', () => {
it('should skip quoted delimiters', function () {
diff --git a/src/parser/tokenizer.ts b/src/parser/tokenizer.ts
index 5e69b11d71..87d3ca0a50 100644
--- a/src/parser/tokenizer.ts
+++ b/src/parser/tokenizer.ts
@@ -140,9 +140,10 @@ export class Tokenizer {
return token
}
- readToDelimiter (delimiter: string) {
+ readToDelimiter (delimiter: string, respectQuoted = false) {
+ this.skipBlank()
while (this.p < this.N) {
- if ((this.peekType() & QUOTE)) {
+ if (respectQuoted && (this.peekType() & QUOTE)) {
this.readQuoted()
continue
}
@@ -156,7 +157,7 @@ export class Tokenizer {
const { file, input } = this
const { outputDelimiterRight } = options
const begin = this.p
- if (this.readToDelimiter(outputDelimiterRight) === -1) {
+ if (this.readToDelimiter(outputDelimiterRight, true) === -1) {
throw this.error(`output ${this.snapshot(begin)} not closed`, begin)
}
return new OutputToken(input, begin, this.p, options, file)
diff --git a/test/e2e/issues.spec.ts b/test/e2e/issues.spec.ts
index 268911c278..24895a5f61 100644
--- a/test/e2e/issues.spec.ts
+++ b/test/e2e/issues.spec.ts
@@ -431,4 +431,27 @@ describe('Issues', function () {
const fn = () => engine.parseAndRenderSync("{%- assign module = '' | split '' -%}")
expect(fn).toThrow(/expected ":" after filter name/)
})
+ it('#628 Single or double quote breaks comments', () => {
+ const template = `{%- liquid
+ # Show a message that's customized to the product type
+
+ assign product_type = product.type | downcase
+ assign message = ''
+
+ case product_type
+ when 'health'
+ assign message = 'This is a health potion!'
+ when 'love'
+ assign message = 'This is a love potion!'
+ else
+ assign message = 'This is a potion!'
+ endcase
+
+ echo message
+-%}`
+ const engine = new Liquid()
+ const product = { type: 'love' }
+ const result = engine.parseAndRenderSync(template, { product })
+ expect(result).toEqual('This is a love potion!')
+ })
})
diff --git a/test/integration/tags/inline-comment.spec.ts b/test/integration/tags/inline-comment.spec.ts
index cb1d272f78..5f81e60406 100644
--- a/test/integration/tags/inline-comment.spec.ts
+++ b/test/integration/tags/inline-comment.spec.ts
@@ -17,6 +17,16 @@ describe('tags/inline-comment', function () {
const html = await liquid.parseAndRender(src)
return expect(html).toBe('foo')
})
+ it('should allow single quotes', async function () {
+ const src = "B{% # that's %}A"
+ const html = await liquid.parseAndRender(src)
+ return expect(html).toBe('BA')
+ })
+ it('should allow double quotes', async function () {
+ const src = 'B{% # that"s %}A'
+ const html = await liquid.parseAndRender(src)
+ return expect(html).toBe('BA')
+ })
it('should handle hash without trailing whitespace', async function () {
const src = '{% #some comment %}'
const html = await liquid.parseAndRender(src)