-
-
Notifications
You must be signed in to change notification settings - Fork 86
fix: unpaired apostrophe in JavaScript comments #370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
ccd2f84
b335b27
038fd66
c29c0ac
bc1e1d1
34d8d6b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,8 @@ const singleQuoteReg = /'(?:\\[\s\w"'\\`]|[^\n\r'\\])*?'/g; | |
|
|
||
| const doubleQuoteReg = /"(?:\\[\s\w"'\\`]|[^\n\r"\\])*?"/g; | ||
|
|
||
| const lineTerminatorReg = /(?:\r\n|[\n\r\u2028\u2029])/g; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The regex itself seems correct to me. There might be a way to use the The regex consumes CRLF when it is found, which is potentially helpful, because it'll move the search needle entirely past the linebreak to the following line's content.. although makes the code slightly less platform-agnostic. |
||
|
|
||
| /** Escape special regular expression characters inside a string */ | ||
|
|
||
| function escapeRegExp(string: string) { | ||
|
|
@@ -109,7 +111,7 @@ export function parse(this: Eta, str: string): Array<AstObject> { | |
| ); | ||
|
|
||
| const parseCloseReg = new RegExp( | ||
| "'|\"|`|\\/\\*|(\\s*(-|_)?" + escapeRegExp(config.tags[1]) + ")", | ||
| "'|\"|`|\\/\\*|\\/\\/|(\\s*(-|_)?" + escapeRegExp(config.tags[1]) + ")", | ||
| "g", | ||
| ); | ||
|
|
||
|
|
@@ -161,6 +163,14 @@ export function parse(this: Eta, str: string): Array<AstObject> { | |
| ParseErr("unclosed comment", str, closeTag.index); | ||
| } | ||
| parseCloseReg.lastIndex = commentCloseInd; | ||
| } else if (char === "//") { | ||
| lineTerminatorReg.lastIndex = parseCloseReg.lastIndex; | ||
| const match = lineTerminatorReg.exec(str); | ||
| if (match) { | ||
| parseCloseReg.lastIndex = match.index + match[0].length; | ||
| } else { | ||
| parseCloseReg.lastIndex = str.length; | ||
| } | ||
|
rtritto marked this conversation as resolved.
|
||
| } else if (char === "'") { | ||
| singleQuoteReg.lastIndex = closeTag.index; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -34,6 +34,22 @@ describe("parse test", () => { | |||||
| ]); | ||||||
| }); | ||||||
|
|
||||||
| it("works with unpaired apostrophe in single-line comment", () => { | ||||||
| const buff = eta.parse("hi <% // comment with unpaired apostrophe' \n %>"); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One more request for a test case: please could we add a (negative) test case where a single-line comment extends all the way to the end of the template? In other words, something like: This should raise an The reason I'm asking: I think it might be possible to |
||||||
| expect(buff).toEqual([ | ||||||
| "hi ", | ||||||
| { val: "// comment with unpaired apostrophe' \n ", t: "e" }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bgub I'm learning the codebase and parsing behaviour in order to provide feedback to @rtritto about this pull request. From what I've understood so far: a parse result with That's probably fine, although I wonder: could we omit the parsed comments entirely, and skip evaluation of them? (saving a few evaluations, potentially for large/descriptive text such as license templates or lengthy explanatory comments?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now think that this would only affect comments inside template blocks - e.g. within I wouldn't expect many or extensive comments within those, generally -- so perhaps there is not much likely performance improvement (in typical usage) available here. |
||||||
| ]); | ||||||
| }); | ||||||
|
|
||||||
| it("works with unpaired apostrophe in multiline comment", () => { | ||||||
| const buff = eta.parse("hi <% /* comment with unpaired apostrophe' */ %>"); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rtritto your fix works for double-quotes in addition to apostrophes, and I think that might be worth demonstrating too. Another set of scenarios I'll look into is cases where there are mixed |
||||||
| expect(buff).toEqual([ | ||||||
| "hi ", | ||||||
| { val: "/* comment with unpaired apostrophe' */ ", t: "e" }, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NB: the parsed
Suggested change
(this affects the previous test case expectations too) |
||||||
| ]); | ||||||
| }); | ||||||
|
|
||||||
| it("parses with simple template literal", () => { | ||||||
| // biome-ignore lint/suspicious/noTemplateCurlyInString: intentional | ||||||
| const buff = eta.parse("hi <%= `template %> ${value}` %>"); | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me think that we might be missing the
U+2028/U+2029line terminators from the end-quote regex patterns (singleQuoteReg,doubleQuoteReg). I haven't explored this yet but would like to.