-
Notifications
You must be signed in to change notification settings - Fork 4
CS2 Discussion: Features: Tagged template literals #28
Comments
Good catch! This is definitely something that needs work. Would it make sense to replace the current literal-JS syntax? Or should we rather introduce a different syntax for template strings? |
See also: jashkenas/coffeescript#1504 (comment) |
I also submitted a bug report for this on the Coffeescript repo: jashkenas/coffeescript#4301 |
FYI, I got tagged template literals working in my browser-side Coffeescript project by encapsulating use of this es6 functionality in its own javascript class. So - for the first time - my project contains both coffeescript and javascript files, which are all brought together in a browserify + broccoli build step.
|
CoffeeScript interpolates with Currently, code such as @greghuc is that the feature you're suggesting we build, or do I misunderstand? |
@rattrayalex yes, I'm imagining that
You could argue that alternative escaping is the better solution, given escaping is the root cause of the break. I haven't done a deep dive on this, but the issue is really with ES6 tagged template literals, not template literals. ES6 template literals are equivalent to CS string interpolation. But tagged template literals are a new kind of beast. They involve all 'arguments' to the interpolated string being passed to the supplied function, which then processes them. Example from MDN:
Might be worth backing away from this, and treating this as an issue with Javascript escaping in Coffeescript. |
Sorry, what does this have to do with escaping? Is it just a question of the syntax? I don't see why use of the backtick is required for this feature. |
To restate, it is currently not possible to use ES6 template literals or tagged template literals inside Coffeescript (in an escaped javascript block). This is because ES6 template laterals use backticks in their syntax, and Coffeescript already uses backticks to define the start and end of the javascript block. As such, the Coffeescript compiler breaks. So see this, copy and paste the following into "Coffee to JS" http://js2coffee.thomaskalka.de, and view the error:
So current Coffeescript is broken for use of this ES6 feature. |
Ah, gotcha. So there are two things we could do (non-exclusively):
They both sound fairly straightforward to me, though I don't know enough about the relevant parts of the coffeescript compiler to say. |
The escaping thing is just an outright bug in CoffeeScript, that’s been open since 2011: jashkenas/coffeescript#1504 But there’s more interest in it lately since the advent of template literals. Basically it seems like there’s a consensus desire to be able to escape backticks, as well as add a triple-backtick delimiter for backticked blocks. That seems like a worthy improvement. But fixing escaped backticks just enables a hacky workaround to using tagged template literals; it’s a far cry from supporting the feature itself in CoffeeScript syntax. Theoretically, the efforts could proceed in parallel; we could build support for @greghuc, would you mind posting a proposal for what the CoffeeScript syntax should be for tagged template literals? Including what the expected JavaScript output would be. Would we support tagged template literal blocks, e.g. Also, would you like to take the lead in implementing this feature in the current compiler? It’s one of only three items in the Top Priority tier of our features list, as the only ES2015+ features we’ve found so far that imperil interoperability. |
@GeoffreyBooth I'll start off by posting a proposal for tagged template literals. I'll aim to have this done by next weekend (by Sunday Sept 18th). Initial thoughts:
Regarding taking the lead on implementing this feature, I'm hypothetically up for it. I'll make a decision once it's clearer what the scope is (once we've agreed on the feature proposal), and how much spare time I have for open-source coding. |
@greghuc I agree with everything except I’m neutral on the “compiles to ‘polyfill’ JavaScript” part. I think we need to make a broader philosophical decision on whether newly-built features should still be compiling down to ES5, or should just output ESNext and leave the shimming to a tool like Babel. For modules and classes it hasn’t been an issue, since shimming modules is way beyond our capabilities and the current I think as a group in this repo we’ve already reached a consensus that a future version of the CoffeeScript compiler should output as much ESNext syntax as possible, leaving the shimming to other tools. I proposed a flag for enabling such output, so it can be built gradually over time and not break backward compatibility. Assuming @jashkenas signs off on such a plan, it would then be CoffeeScript’s stated goal to output modern ECMAScript whenever possible, which implies that new features we add now should just go ahead and output ESNext. Ideally they would output both, an ESNext version if the So I guess would you be okay will building tagged template literals that output at least as ESNext? And if you want to take on the added challenge of outputting ES5, that’s awesome. |
@GeoffreyBooth I think outputting tagged template literals in ESNext is actually the nicest option:
I considered the polyfill approach, as I didn't think outputting ESNext would be an option. So I'd be happy aiming for ESNext output for first implementation. But I'll start with the proposal first. |
@greghuc that sounds great. I don’t think this feature even needs a flag; like generators or modules, using the new syntax opts into getting ESNext output. We only need to worry about flags if you wanted to build both possible outputs. |
My preferred plan would be for a CoffeeScript 2.0 to implement and output modern ECMAScript — as soon as those features are shipping in real browsers and Node. I think that to output them earlier than that point (to rely on chains of transpilers, and promises to implement the spec as its written but before its implemented) would be foolish. |
Triple quotes is used in a lot of languages to allow not escaping the single quote. Couldn't something be used here? I.e. triple backticks? |
@nilskp yes, see above. |
@rattrayalex Ah, yes. I didn't read the thread carefully enough. |
Why foolish? That seems like an odd indictment of this entire effort. |
I think what he's saying is that CS2 shouldn't try to confirm to the spec for ES2016 before ES2016 is actually implemented in Node 7 (which would give time for the kinks to be worked out? make sure the feature will actually make it to the language?). |
You can also put such things behind a different branch, ie esnext. I get it, the idea is really about only putting things into the language that will actually be adopted. However we can "Anticipate" future features by placing it in an unstable or experimental branch. Perhaps we should do a formal proposal for the release process. CS2(CS3, CS4 etc.) branches would include breaking changes (for instance classes) and any currently existing (Implemented in Babel?) high priority items that are already shipping in browsers. The ESNext branch would implement soft targets or features that are nearly complete in browsers. The experimental branch would be implementations of low priority ES6/7 targets that aren't fully defined. I also wouldn't mind having tagged "Stable" versions. |
Based on some of @jashkenas’ other comments, I think that what he means by waiting for browser implementation is not that he feels that people should rely on the Getting back to template literals, support is widespread in evergreen browsers: So I think this feature is safe to implement. Per this comment, unless anyone objects to @jashkenas, we’re going to skip the ES3 version of template literals and go straight to ESNext. @greghuc are you going to implement both tagged template literals and regular template literals? You’re welcome to do both if you’re up to the challenge, though if we compile |
As discussed, I've written up a proposal for adding ES6 'tagged template literal' support to Coffeescript. Executive summary follows, followed by more detail (code examples, etc). Opinions welcome. Executive summaryTemplate literals and tagged template literals are a new feature in ES6:
The current situation with Coffeescript:
Proposals for Coffeescript to interoperate/adopt ES6 template literals:
Three final observations:
Executive summary ends. Bug-fix: ensure ES6 template literals can be used in CS embedded Javascript blocksES6 template literals cannot be used in an embedded Javascript block, since the new syntax uses backticks. Backticks are already used by Coffeescript to define the start and end of the JS block. This example blows up:
The proposed fix is for Coffeescript to allow embedded Javascript blocks to be delineated with 3-backticks markdown-style, and not escape backticks in the Javascript block. E.g.:
Reasoning:
New feature: adopt ES6 tagged template literals in CSSummary of ES6 template literals An ES6 'template literal' is a string literal that can include interpolated expressions, and can be multi-line. Example:
An ES6 'tagged template literal' is a template literal, but prefixed with a function reference. The function is called to generate the output string, being supplied with the template literal in the form of expressions and the text between them. Example:
So the simpler 'template literal' can be seen as a tagged template literal with an invisible 'normal' function that just concatenates the given text-parts and expressions together. Coffeescript proposal The proposal is for Coffeescript to 'natively' adopt tagged template literals. The implementation will augment existing Coffeescript behaviour for single-line, multi-line and block strings. As such, the implementation will slightly differ from ES6 for multi-line block-strings, due to the spacing differences. Single-line string:
Multiline string:
Block string:
Differences between Coffeescript strings and ES6 string literalsCoffeescript already supported multi-line strings with 'block strings'. In ES6, multi-line strings are now supported with string literals. But the two differ in terms of spacing. Example: CS block string:
ES6 multi-line string literal:
To completely align Coffeescript string behaviour with ES6 template literals, the spacing semantics of a Coffeescript block-string would need changing to match a multi-line ES6 template literal. This change would be backwards incompatible, so has not been proposed. Coffeescript bug? Can't nest block-strings inside block stringsI found an example where ES6 tagged template literals are nested inside one another. To support this, Coffeescript must also be able to nested interpolated strings. I did some testing, and discovered that CS cannot nest block strings. Bug? Busted:
Works:
|
@greghuc this is heroic. In the interest of organizing our discussion, would you mind splitting some of these out into separate issues? I’m not sure template literals and tagged template literals should really be discussed separately, so we could keep those here; but the block-backticks operator could get its own issue, as could the bug about nested block strings (that should perhaps be a bug issue on the main coffeescript repo). BTW if you want to type three backticks in a code block in GitHub, you can use its other code block syntax, which is indenting with four spaces:
|
A few little things here:
|
@greghuc To try to answer your questions:
|
@greghuc I invited you to become a collaborator on https://github.com/GeoffreyBooth/coffeescript. You’re welcome to use a new branch on that repo to implement this, if you want me or @lydell or @JimPanic to have write access to your branch. Or you’re more than welcome to work in your own fork. When the branch is ready for a PR, please submit it against the soon-to-be-created |
@GeoffreyBooth I've spun out 2 new issues from the tagged template literals work:
|
So I'll make a start on adding tagged template literals to Coffeescript next week (Sept 26 onwards), as per the proposal in this thread. My time for open-source commits is constrained, so I'm not providing an ETA for completion right now. This will also be my first time changing Coffeescript, so there'll be a ramp-up period whilst I understand how it works. Are there any pointers for getting an overview of the Coffeescript compiler? |
Hi @greghuc, I put up https://github.com/GeoffreyBooth/coffeescript/wiki/How-parsing-works which was consolidated from a few helpful comments left for me while I was working on the modules PR. I plan to remove the specific references to modules and move it to the regular coffeescript repo wiki soon. There are other good pages there too: https://github.com/jashkenas/coffeescript/wiki I also created https://github.com/GeoffreyBooth/coffeescript-gulp to automate compiling and testing. |
Hey I don't know where else to put this so: I'm working on a new Hapi.js project the last few days. Decided to do it in ES2015 since a couple of junior devs are helping me. HOLY CRAP I MISS COFFEESCRIPT. All these damned extra braces and semicolons and such, clutterin' up my code. And the lack of easy key/value list comprehension. Etc. So, thanks so much for participating here. Know that your work is appreciated. |
Released in CoffeeScript 1.12.0. |
Migrated to jashkenas/coffeescript#4925 |
Current Coffeescript is incompatible with template literals, specifically tagged template literals. As such, direct support for template literals should be considered for coffeescript nextgen.
Specifically, calling a tagged template literal looks this:
Coffeescript already uses backticks to embed javascript:
Unless I've missed a trick, it's currently impossible to use a tagged template literal in Coffeescript by embedding the relevant ES6 javascript.
FYI, I ran into this problem when exploring the newish bel DOM templating library. Since it uses tagged template strings, I believe it's inoperable with current Coffeescript. This is the first time I've seen incompatibility between Coffeescript and Javascript..
The text was updated successfully, but these errors were encountered: