Skip to content
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

New escape javascript (`) token #1504

Closed
matthewmueller opened this issue Jul 12, 2011 · 32 comments
Closed

New escape javascript (`) token #1504

matthewmueller opened this issue Jul 12, 2011 · 32 comments
Labels

Comments

@matthewmueller
Copy link

I'm building an asset bundler that can merge both coffeescript and javascript together. It works fine placing coffeescript inside javascript -- compile it and stick it in the js file.

The problem I'm running into is when I try to include javascript into coffeescript. My approach was to bring in the javascript, escape with `, and then compile the coffeescript.

The problem is many libraries use ` in comments -- including backbone. One thought is to use ``` to escape javascript like comment blocks in coffeescript.

Please let me know your thoughts on this.

After some discussion: The whole point of this issue is to point out that the single backtick does not always work the way it's intended. Use cases and outside discussion should be irrelevant here. Currently, the backtick does not work if you try to escape a file like backbone or jquery or even a two line javascript file that has a comment that includes a backtick.

Thanks,
Matt

@michaelficarra
Copy link
Collaborator

God, that sounds disgusting.

edit: So, what's the use case here? Large chunks of javascript embedded in coffeescript? Who is doing that?

@matthewmueller
Copy link
Author

No one is writing large chunks of javascript embedded in coffeescript, but people are writing/using tools like Sprockets that need to be able to add javascript to coffeescript files and have it compile correctly.

@michaelficarra
Copy link
Collaborator

Can you give some example code that would use these backtick heredocs?

for prop of obj
  ```
  } while(1) {
  ```

I can only assume these would be used for something like that. As in, a horrible abuse of a feature that's already highly discouraged as it is.

edit: Hopefully this doesn't derail the conversion, but I don't understand a tool like Sprockets. It "turns your messy javascript into clean modules", but I already write clean (for some definitions of clean) modules, what are these "messy javascript" files with paperclips and thumbtacks? And then, amazingly, it produces a single file. The same tool has been around for 40 years now: cat. So what can't be done by just compiling the CS files and concatenating that output with the JS files?

@matthewmueller
Copy link
Author

I think you're missing the point.. Yes, the example you posted is an awful abuse of the feature. That example should not be used even if there is only one backtick for escaping javascript. Hopefully this will clear it up:

You start with something like this in your coffeescript file:

#= require "../lib/backbone.js"

# Backbone will now be available
console.log Backbone

Something like Sprockets reads the require goes in and bundles the assets into a build.js that looks like this:

//     Backbone.js 0.3.3
//     (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
// ..... The entire backbone library ....

// Backbone will now be available
console.log(Backbone);

Make sense?

Edit: Okay. This is not a discussion of Sprockets. The whole point of this issue is to point out that the single backtick does not always work the way it's intended. Use cases and outside discussion should be irrelevant here. Currently, the backtick does not work if you try to escape a file like backbone or jquery or even a two line javascript file that has a comment that includes a backtick.

@michaelficarra
Copy link
Collaborator

So what you're saying is coffee and cat are good enough to do what you're looking for:

  • build.sh:

    coffee -o js/ -c coffee/
    cat vendor/backbone/backbone.js js/myfile.js
    
  • coffee/myfile.coffee:

    console.log Backbone # hey look, it's available!
    

edit: By the way, I'm purposely simplifying your proposal to better understand the most basic reason for its necessity. Don't take it personally. At this point, it looks like this is yet another macro proposal.

edit 2: It looks like we don't properly support backslash-escaping backticks:

$ coffee -bpe '`// \`abc`'
// \`abc;

@jashkenas
Copy link
Owner

Usefulness aside, I think it would be great to support "here-embedded-js" with triple backticks. It makes them just a bit more consistent with all the other quoting operators in the language.

@satyr
Copy link
Collaborator

satyr commented Jul 12, 2011

Note that ``` can only appear in literals in JS, and ``` works fine in both string and regex:

$ node -e '/\`/.test("\`")'
true

Comments do suffer, but aren't essential.

@matthewmueller
Copy link
Author

@satyr

I guess the whole point is that it breaks when there are any backticks in the javascript. You can have perfectly valid javascript that contains a backtick in a literal string or in regex and, as you said, it will break. No this isn't a huge deal, but as @jashkenas mentioned, it makes it more consistent with the language and it fixes these minor issues with a less conflicting operator.

@satyr
Copy link
Collaborator

satyr commented Jul 12, 2011

it breaks when there are any backticks in the javascript

Yes, therefore you need to escape them with backslash when embedding. This is true for whatever escape method we use. With the proposed triple backtick literal, you'd still have to take care of `````s in your embedded JS.

@matthewmueller
Copy link
Author

Yah true, why not just have Coffeescript escape the backticks? Maybe that's what you were thinking. Then one backtick would work just fine. Then it just becomes a debate over the style of the syntax, which I don't know if that would be worth our time for an issue like this :-)

@michaelficarra
Copy link
Collaborator

@satyr and @matthewmueller: see my edit #2 above from a few hours ago. Yes, you can use backslashes to escape backticks, and yes, they're broken.

@bdkjones
Copy link

Hi there. Can we get the triple backtick delimiter added?

I write CodeKit and I cannot tell you how many people have asked me to let them combine Javascript and CoffeeScript files together. The most common case is that they want to stick jQuery at the beginning and then write some CoffeeScript against that library.

If you add the ``` delimiter, as suggested here, providing this capability in build tools would become trivial. Thank you.

@rstacruz
Copy link

Just chiming in to bump this for 2 reasons:

  1. ES6 will have template strings made using backticks, ie, a = Hello, ${name}``.

  2. We've been working on a new js2coffee that uses ``` extensively when "compatibility mode" is on to preserve JS behavior in things it can't translate (eg, ==). It would be nice to make backticks escapable in case they're converting ES6.

@rstacruz
Copy link

Also, GitHub markdown uses backticks to escape code, and it lets you surround text with as many ```s as you need so to allow backticks inside the strings:

code
code with ` backticks
code with `` and ` backticks

@jashkenas
Copy link
Owner

Escapable backticks plus here-backticks would be nice to have.

@runemadsen
Copy link

+1

@jashkenas jashkenas removed this from the as soon as a patch is available milestone Jun 2, 2015
@varblob
Copy link

varblob commented Jul 10, 2015

+1
backticks are becoming a thing in ember for inline template compilation. It would be really nice to be able to escape a backtick either \``-> or the markdown way.

@nickdima
Copy link

nickdima commented Oct 1, 2015

Would changing this line from:

@token 'JS', (script = match[0])[1...-1], 0, script.length

to

@token 'JS', (script = match[0])[1...-1].replace(/\\`/g,'`'), 0, script.length

be enough for escaping backticks?
It seems to work but maybe I'm missing something.

@guigrpa
Copy link

guigrpa commented Oct 9, 2015

This is a really important feature, considering how the lack of convenient JavaScript escaping prevents the use of CoffeeScript with, for example, Relay (a complement to React). I'm currently being forced away of CoffeeScript, and into the extremely verbose realm of ES6, by this single little feature. After 2+ years with CoffeeScript and a huge codebase, it's not so easy :(

An example of what should be possible to embed in CoffeeScript:

var fragments = {
  viewer: () => Relay.QL`
    fragment on Viewer {
      projects { edges { node {
        id, name
      }}}
    }
  `,
};

@michaelficarra, @jashkenas: Any chance this 2-year issue might get some love? ;) It sort of future-proofs CoffeeScript by allowing new features of JavaScript to be usable (if mandatory, as is the case for Relay)

@nickdima
Copy link

nickdima commented Oct 9, 2015

@guigrpa what you could do meanwhile this gets figured out is to keep the queries in a separate JS file and require them from your components. I know the query is supposed to stay inside the component itself but at least it works for now...

@guigrpa
Copy link

guigrpa commented Oct 9, 2015

@nickdima That's a good workaround, thanks!

@guigrpa
Copy link

guigrpa commented Feb 10, 2016

@nickdima What about the fix for escaping backticks you suggested above (Oct 2, 2015)? Did it indeed solve the bug mentioned by @michaelficarra?

@vendethiel
Copy link
Collaborator

It doesn't escape escaped escapes (...), but it should work for simple cases, I guess.

@bdkjones
Copy link

Just to clarify: is there any official strategy for handling backticks (especially those in ES6) or is CoffeeScript kinda saying, "Meh, screw it."? Just trying to plan and can't keep straight the various issues referencing this problem. It's been 4 years, so I'm guessing the CoffeeScript team just doesn't care?

On Feb 10, 2016, at 10:26, Guillermo Grau Panea [email protected] wrote:

@nickdima What about the fix for escaping backticks you suggested above (Oct 2, 2015)? Did it indeed solve the bug mentioned by @michaelficarra?


Reply to this email directly or view it on GitHub.

@bjmiller
Copy link

CS already has the template string feature using double quotes. You don't want to emit an ES6 template string. Just code it to work that way in CS to begin with.

@vendethiel
Copy link
Collaborator

No, I think it's about foo(f``) calling "f" on the raw string

@langri-sha
Copy link

@bjmiller without additional support for escaping backticks, this makes testing JS tag functions in CS impossible, since a template string cannot be provided.

@nickdima wonderful suggesting. This got me out of a tight spot!

@lydell
Copy link
Collaborator

lydell commented Feb 23, 2016

@langri-sha Not impossible, just inconvenient.

> JSON.stringify(((...a)=>a)`a${1}b${2}c${3}${4}`)
"[["a","b","c","",""],1,2,3,4]"

You can test tag functions by calling with an array of all string parts and then each interpolation as separate arguments.

@langri-sha
Copy link

@lydell ahh, thank you for taking the time to explain! It's very obvious once you clearly point it out, but my initial attempt was to escape JS and backslash-escape the backticks therein. It's a harsh blow, not understanding how template strings can be built from other primitives and CS not meeting your expectations at the same time.

reality = [['', '', '', ''], 0, 'bar', quux]
anewhope = `\`${0}${'bar'}${quux}\``
theforceawakens = anewhopepart2 = ```${0}${'bar'}${quux}```

@langri-sha
Copy link

Hello again all. I've found that writing the backtick in one of the supported escape sequences is a quick way to make friends with the compiler. The hexadecimal escape sequence for the backtick is \x60, the unicode is \u0060.

# Smallest example of how to output a backtick in your code.
`\u0060`

Now, this only gets you half way to writing template strings, since JS sources do not support escape sequences and you will get a SyntaxError (writing \ is ILLEGAL). The last bit missing is to pass it to something that can evaluate raw strings as sources, like eval or Function.

horray = "huzzah"
alert `eval("\u0060${horray}!\u0060")` # huzzah!

@huan-ji
Copy link

huan-ji commented May 11, 2016

@langri-sha Any idea how this would work in the case of Relay queries mentioned by @guigrpa ?
Keeping the queries in separate JS files is an option but it isn't the best architecture and isn't a long term solution..

@guigrpa
Copy link

guigrpa commented Jun 2, 2016

@huan-ji Sad to say this, but this was just one of the issues that finally triggered my conversion to ES6. I miss CoffeeScript's terse syntax, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests