-
Notifications
You must be signed in to change notification settings - Fork 2k
Lexer, Nodes: Strings with newlines should be output as template literals with unescaped newlines #5019
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
Comments
@greghuc any thoughts? |
@GeoffreyBooth so I don't have much bandwidth to help at the moment, but I've noted some thoughts below. First of all, I believe Coffeescript should behave exactly like Javascript in terms of tagged template literals - Coffeescript shouldn't be doing anything clever or different. I've done a quick experiment in the Chrome 65 console to see how JS template literals handle newlines, and they are treated like any other character. Newline characters are also present in the string presented to the tagged template function, whether there are explicitly supplied (like "I am a\nnew line") or implicitly supplied (
). So @amozoss, your suggestion that new line characters not be compiled might not make a difference. Take a look at this (from Chrome console):
=> so the template literal strings look the same whether with explicit or implicit new line characters.
=> and they have the same number of characters
=> and when the two template literal forms are supplied to the tagged template function, the textPart looks the same. @amozoss, I think you need to do a bit more digging (in Javascript land) to see if you can really find a bug when react relay is supplied tagged template literals with explicit newlines ("new\nline") vs implicit newlines (
). Because the examples above seem to indicate that there isn't any difference between the two. If you can create a buggy test case, then Coffeescript could take a look at this. The error from relay-coffee-compiler makes me wonder if there's some form of double escaping issue going on. [Cannot parse the unexpected character "\"] suggests that \n is not being parsed as a single newline character, but as a single slash and a single n. |
This is really a string question, not a tagged template literals question. Consider how multiline strings are currently output: '''
first line
second line
''' 'first line\nsecond line'; or """
#{1}
#{2}
""" `${1}\n${2}`; I can see an argument that these should be output as `first line
second line`; `${1}
${2}`; as that would be closer to the user’s original intent. This would also happen to fix the OP’s issue, even while I agree that this issue feels like a downstream bug in |
Yeah, so exports.StringWithInterpolations in node.coffee starts generating multiline-strings as multiline template literals, rather than a single-line template literal with newline chars. Would make the generated JS look nicer. |
Thanks for looking into this. Looking at the graphql spec , the way I understand it is the newline characters shouldn't matter. I dug into relay-compiler (version 1.5.0) a bit (relay-coffee-compiler is just a wrapper of relay-compiler). It uses graphql-js to do the parsing. I logged just before the error is thrown with
It looks like, its escaping the newline chars. It also seemed, by looking at the lexer source code, that it handled unicode line feed ( So I also agree it looks like a problem in relay-compiler. I'll report an issue there. Thanks again for digging in. I do like the idea of matching implicit new lines from coffee to JS. I agree it would make the generated JS look nicer and easier to link back to the coffeescript |
The |
Created an issue facebook/relay#2376 |
@lydell Do you know why the lexer does so much reformatting of strings? I’m looking at functions such as makeDelimitedLiteral and wondering why this logic isn’t happening in I was interested in seeing if I could update |
No, I don’t. It’s always been that way, I think. It’s a good example of CoffeeScript doing too much in the lexer. |
@GeoffreyBooth I did just a quick scan of string parsing in the |
As a workaround, in relay-coffee-compiler I made the following change, which was good enough for my current use case. Its not ideal though. index faa759f..ba90840 100644
--- a/src/parser.coffee
+++ b/src/parser.coffee
@@ -22,6 +22,7 @@ parseFile = (baseDir, file) ->
astDefinitions = []
for template in FindGraphQLTags.memoizedFind(text, baseDir, file, {})
+ template = template.replace /\\n/g, '\n'
ast = GraphQL.parse(new GraphQL.Source(template, file.relPath))
assert ast.definitions.length, Thanks for quick responses and the in-depth help. |
@GeoffreyBooth I have prepared a PR which changes how block strings with interpolation are compiled. But, there are few possible breaking changes I think we should discuss first. a = `
1
${s}
3
` CS current branch: a = """
1
#{s}
3
"""
# a = `1\n ${s}\n 3` So, the newline at the beginning and end of the string are stripped, and the indent is decreased. With my PR the output would be changed, i.e. it would be exactly as the example from the console a = `
1
${s}
3
` Consequently, some test currently fails and needs to be adjusted. test "string", ->
code = """
do ->
#{Array(3).join('for [0..0] then\n ')}
true
""" has to be changed to test "string", ->
code = """
do ->
#{Array(3).join('for [0..0] then\n ')}
true
""" |
I don't think this is a case where we can have breaking changes. We'll have to do the trimming and other adjustments in the nodes so that the output matches. |
@zdenko do you mind posting the branch you had started for this? |
The issue here is that all template tags get to choose if they want the “cooked” or “raw” value of the template literal. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Raw_strings `one
two`
// equivalent to:
`one\ntwo`
anyTag`one
two`
// not necessarily equivalent to:
anyTag`one\ntwo` The Relay compiler uses the the raw value: https://github.com/facebook/relay/blob/78ec175df72f5a13e1061be5dcb9e2aab6255d86/packages/babel-plugin-relay/getValidGraphQLTag.js#L38 Which means that In other words, it is not safe for CoffeeScript to compile tagged strings like this: tag"""
one
two
""" to: tag`one\ntwo`; It has to be: tag`one
two`; because one cannot know how (I stumbled upon this when researching prettier/prettier#4974 and thought I’d stop by and write down my findings). |
See #5211 |
Landed in 2.5.0 🎉 |
When using react relay compiler, Tagged Template Literals have newline characters which causes errors in relay compiler. I've written the sample from the Tagged Template Literal, but included a sample graphql query instead. Would it be possible to compile the literals to not include the new line characters?
Input Code
Sample
Expected Behavior
Ideally it would compile to the following
Current Behavior
Instead it is including newline characters
Possible Solution
Not entirely sure, on the surface it seems like the newline characters change the meaning of the Tagged Template Literal. I can put my literal on one line, but thats not ideal for readability of my graphql query.
Context
When running my code through the relay-coffee-compiler I get the error
When I only put my coffee template literal on one line, relay-coffee-compiler works. i.e.
upperCaseExpr""" query HelloQuery { allLinks { id, url } } """
.Environment
"relay-coffee-compiler": "^0.0.4"
The text was updated successfully, but these errors were encountered: