16 ms·
Show HN: Decaffeinate converts CoffeeScript projects to modern JS
- tyrw 9y agoI'm assuming "modern JavaScript" means ES6. Has anyone used this, and does it produce readable code?
- alangpierce 9y agoYeah, "modern JS" is meant to be the catch-all term for ES6/ES7/ES2015/ES2016/ES2017. In this case, you need ES2016 to run code produced by decaffeinate, but anything in the latest language version or at stage 4 is fair game and might be added in the future. Producing readable code is certainly the intent! Realistically, you need to clean some things up by hand to make it pass lint and look nice, but I think overall it does a pretty good job, certainly much better than the CoffeeScript compiler. You can always play around with it by typing/pasting code into the online repl: http://decaffeinate-project.org/repl/ http://decaffeinate-project.org/repl/
- uranian 9y agoYou mean only ES2016 from that list? > Producing readable code is certainly the intent! This is hilarious! Transpiling from the most readable JS alternative to ES6? Then you need to clean up some things, making it ready for yet another transpiler called Babel? And then everything is OK? Show me how you are going to make this pretty: if does.that?.prop?.exist then console.log 'yes, no crash!'
- alangpierce 9y ago> You mean only ES2016 from that list? No, I was intentional about my description. People tend to be informal when talking about JS versions, and all five of those terms might be used to describe decaffeinate's output. IMO it's best to just say that decaffeinate produces JavaScript, and not any particular old version of JavaScript. > Show me how you are going to make this pretty Soak operations (anything with a question mark) are probably the hardest to convert to JavaScript, especially when they're chained. Here's what decaffeinate gives today: http://decaffeinate-project.org/repl/#?evaluate=true&stage=full&code=if%20does.that%3F.prop%3F.exist%20then%20console.log%20'yes%2C%20no%20crash!' http://decaffeinate-project.org/repl/#?evaluate=true&stage=f... And here's an open bug with thoughts on making those look better: https://github.com/decaffeinate/decaffeinate/issues/336 https://github.com/decaffeinate/decaffeinate/issues/336 But many people have still found decaffeinate useful since the vast majority of real-world CoffeeScript (at least from what I've seen) tends to convert pretty well, and even in difficult cases, it's better to safely get it in JavaScript first and then clean it up than to rewrite everything by hand.
- uranian 9y agoif (__guard__(does.that != null ? does.that.prop : undefined, x => x.exist)) { console.log('yes, no crash!'); } function __guard__(value, transform) { return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined; } oh my.. This was 1 line of CS, how to clean this up without a chance of creating bugs? How on earth is ESxxx an improvement on CS anyways? It's just not true, it's a leap back.
- Grue3 9y agoIt produces Javascript, so by definition it cannot produce readable code.
- foxhedgehog 9y agoWasn't JA updating CS again recently? Has anybody tried to use it after using ES6/7?
- alangpierce 9y agoYep, the CoffeeScript folks are working on CoffeeScript 2 (I think JA is participating in some discussions but not actively working on it himself). It's not released officially, but there's a beta, and lots of discussions here: https://github.com/coffeescript6/discuss https://github.com/coffeescript6/discuss
- johnfn 9y agoHasn't the community (finally) learned that simply transposing a better syntax onto JavaScript does not solve or help programmers in a meaningful way like the way that static typing does? Or is me hoping that a community will collectively reach a realization like this a pipe dream?
- gmac 9y agoPatronizing? I've mostly switched to TypeScript from CoffeeScript for the time being, because types are indeed a huge boon, but a better syntax is meaningfully helpful and my preference any day would be for some merger into typed CoffeeScript.
- johnfn 9y agoYeah, I guess TypedCoffeeScript would be better than just one or the other.
- rpeden 9y agoFor what it's worth, I've found that F# has a similar 'feel' to what I'd expect from a typed CoffeeScript. I'm not sure exactly why; it's probably just the look and shape of the code, along with the lack of brackets. Writing React apps in F# using Fable is pretty nice, too.
- leeoniya 9y agohow is this different than running the compiled CS output through lebab [1]? [1] https://github.com/lebab/lebab https://github.com/lebab/lebab
- alangpierce 9y agoYou lose a lot of information going from CS -> ES5 -> ES6, so decaffeinate has an inherent advantage since it knows your original code. With decaffeinate, it converts classes to classes, destructures to destructures, array spread to array spread, etc. Also, the CS output destroys all inline comments and all formatting.
- treyhuffine 9y agoIt's going to be very interesting to see if Atom decides to fully make the move to JavaScript / ES6+
- pier25 9y agoCS is one of the main reasons I haven't contributed more to Atom. I guess when Atom was started it made sense to use CS, not anymore. Hopefully Github will switch to ES6/7 or TS.
- gabrielcsapo 9y agoalso this
- uranian 9y agoInstead of wanting projects to move to a language you know, you can better first learn the language they are written in, and try to understand their decision in the first place. If you know CS very well you would not be so eager to move to Babel transpiler imao. There is also a nice comment in here about a large project that became a misery because of TS. Think twice before you hope!
- alangpierce 9y agoThey're already using JavaScript for all new code, and gradually converting their existing code over using decaffeinate (e.g. https://github.com/atom/atom/commit/30cd83f7aa03c023e6103b648906107796472fe8 https://github.com/atom/atom/commit/30cd83f7aa03c023e6103b64... ). But it's a reasonably big codebase and I imagine moving everything over incrementally will take a while.
- baby 9y agoWhat about moving to web assembly? Would it be relevant? Or is this a Firefox feature only? Or is this not interesting because the point is to write it in javascript?
- 9y ago
- partycoder 9y agoThis is great. I had a hard time dealing with CoffeeScript code. CoffeeScript tools are behind the state of the art in JavaScript.
- Hydraulix989 9y agoThis is a cautionary tale for developers that flock to the flavor-of-the-month tech (CoffeeScript used to be all the rage in 2013!), only to find that the mature tech not only caught up but completely eclipsed it in 2017.
- partycoder 9y agoWell, in justice, CoffeeScript did influence JavaScript. However some of the decisions were in my opinion bad: removing delimiters and making whitespace more "meaningful". That makes it really hard to automatically format code in a way that deterministically doesn't break.
- molszanski 9y agoIMO that was one bad decision in CS1 that they allowed mixed whitespace to compile in the first place. CoffeScipt 2 (which is ES6 compliant) doesn't allow you to compile/transpile any code with mixed indentation. BTW in Atom, I've successfully used atom-beautify with coffee-fmt and coffee-formatter to reformat very bad code with no errors
- partycoder 9y agoThe formatter from IntelliJ would cause the file to not compile at times. Maybe I should have tried Atom. Too late now.
- josephg 9y agoJeremy Ashkenas (author of coffeescript) helped bring es6 up to par. You can see the influence of coffeescript all over es6 in the class syntax, string interpolation and destructuring. It would be wrong to say that the investment we (as an industry) made in coffeescript was a waste. Far from it.
- deleted 9y ago[deleted]
- blitmap 9y agoI don't understand the trend to move from Coffeescript to ES6. I like both, but I write Coffeescript for its concision. I have no issue compiling Coffeescript to ES6 as a separate build step, but I'm not going to write ES6 myself. That said, I'm sure a project like Decaffeinate has brought a lot of beloved Coffeescript projects into the hands of ES6 developers who wanted to contribute.
- coldtea 9y ago>I don't understand the trend to move from Coffeescript to ES6. ES6 is supported natively, it's an actual standard not a language a single person came with, it avoids a build step, it has all of Coffeescript features and more by this point, and Coffeescript's momentum has slowed. Seems a no-brainer. And as for concision, ES6 seems just as concise. At worse you need an extra } or so, which I like to have anyway.
- uranian 9y ago> it has all of Coffeescript features and more No! It seems you've never learned Coffeescript well enough to know the differences, just like too many other ES6 proponents.
- coldtea 9y agoI learned Coffeescript well enough to not care for the differences. There's nothing especially interesting Coffeescript has over ES6/7.
- o_____________o 9y agoI miss the existential operator like the deserts miss the rain foo?.bar?().baz?.boo
- MrLeap 9y agoTruly. That operator has most of the gravity that pulls me towards coffeescript. Lodash things, like _.isNil staunch the bleeding, but it's just.. not the same. I wrote coffeescript for 3 years, and the first 2 or 3 months was a frustrating learning curve. By the end of that job I really drank the koolaid. Coffeescript can be blissful. The complaints about invisible delimiters and stuff resonated with me for the first 2 weeks, but then I just learned it like you learn anything. If you are unsure what's going to happen, add extra parenthesis. I kept a window with js2.coffee on it so I could paste uncanny snippets while I was getting up to speed. After I got over the curve I stopped needing it. I think it was more frustrating in the beginning than learning most things because I knew JS pretty well prior and it felt like I was throwing my experience out the window. I'm glad I did it though. Writing coffeescript was really quite pleasant. Now regular javascript has jumped forward a bit and has somethings coffeescript doesn't, I still feel like the one true web language exists somewhere between them. I'm leading a project right now and every couple of days I get that coffeescript itch. Caffeine is hard to put down once you're addicted.
- nickm12 9y agoCoffeeScript has some nice feature, especially as compared to ES5, but I always found it a tad too clever. The fact that {} are optional in a bunch of places makes it very difficult for me to parse mentally. Other weird coffeescript quirk: "x isnt y" is not semantically to "x is not y".
- jononor 9y agoPeople overuse {}-free object literals in CoffeeScript. In function invocations, and other in-line cases, use {}!
- abritinthebay 9y agoOh thank god. CoffeeScript was an important crutch and stepping stone but we're maybe 2 years past where it has been past it's prime and this will make updating and improving legacy projects a lot easier. Personally was never a fan of it - it used too many Ruby idioms for my taste and produced noisy code that was a pain to debug (at the time) - but it did spur the development & adoption of other, better, systems (ESNext transpilation, TypeScript, etc)
- patrickbolle 9y agoOh how the tables have turned
- kvz 9y agoShameful plug: http://invig.io http://invig.io is a a wrapper around decaffinate, lebab, prettier, eslint, to to squeeze more modernness out of legacy js/coffeescript codebases and make them standardjs.com compliant
- nailer 9y agoThat sounds excellent (especially if it supports await!). Slightly off-topic: I love standardjs.com. It takes an enormous amount of chutzpah to look at jQuery style guidelines, idiomatic.js, AirBnB and every previous JavaScript style guide and declare the name of your own new thing is `${standard} ${languageName}`
- positivecomment 9y ago"Standard" (the name is very hard to tolerate) not being configurable with questionable defaults (no semicolons!) and being JS-only (no TS or CSS support) makes Prettier[1] a better option. It has a VS Code extension which works great. [1]: https://github.com/prettier/prettier https://github.com/prettier/prettier
- nailer 9y ago> Prettier parses your JavaScript into an AST (Abstract Syntax Tree) and pretty-prints the AST, completely ignoring any of the original formatting*. Say hello to completely consistent syntax! That's excellent. Thanks for the recommendation.
- alangpierce 9y agoCool, I hadn't seen that! bulk-decaffeinate is a wrapper around decaffeinate, jscodeshift, and eslint with a similar goal. And I've certainly thought about incorporating lebab and/or prettier there as well. https://github.com/decaffeinate/bulk-decaffeinate https://github.com/decaffeinate/bulk-decaffeinate
- jlebrech 9y agocoffeescript is best for doing a specific thing on a page. for spa it's different.
- matthewmacleod 9y agoMixed feelings about CoffeeScript, as ever. ES6 obviously deals with some of the issues that CoffeeScript was intended do. That's awesome. Unfortunately, it's still difficult to go back to what seems like the relatively baroque syntax of Javascript afterwards, as someone who has a bit of a vendetta against over-syntax. SO MANY BRACKETS. In particular, there was CJSX - JSX with CoffeeScript. Writing React components using it was an absolute joy in comparison, and helped eliminate a lot of noise – making it much more obvious what a component was doing. But yeah, it's been hard to convince others that it's worth the investment, when honestly it's really just a personal preference at this stage.
- s_kilk 9y ago> SO MANY BRACKETS. }) }) }) }) }) }) }, }) }) }) }) }) }) }, Whatever do you mean?
- chx 9y agoDidn't ES6 promise ;) to solve this?
- matthewmacleod 9y agoThis is true only insofar as libraries use promises, and your code uses promises. They're still pretty annoying in my experience. There are still some other cases where the mess of brackets is overkill, other than callback hell.
- udp 9y ago> This is true only insofar as libraries use promises, and your code uses promises. They're still pretty annoying in my experience. Promisify, or (as I prefer to) just "return new Promise((resolve, reject) => { nonPromisedStuff(...) })"? > There are still some other cases where the mess of brackets is overkill, other than callback hell. Like bad coding style?
- AriaMinaei 9y agoI did an experiment about a year ago when I re-wrote part of LiveScript's code emitter to produce a babel-compatible AST rather than javascript code. It would then pipe the AST to babel's generator and produce the final JavaScript. The benefit was that I could then use any babel-compatible toolset and still write code in LiveScript. ESLint worked with almost no tweaks necessary. Theoretically, you could also use Flow and TypeScript with this approach. Anyway, I didn't have enough time to finish the project, but somebody took the idea and did most of the work [0]. [0] https://github.com/dk00/livescript-next https://github.com/dk00/livescript-next Would love to explain more, but have to board the plain now :) These links might help: https://github.com/gkz/LiveScript/issues/821 https://github.com/gkz/LiveScript/issues/821 https://github.com/facebook/flow/issues/1515 https://github.com/facebook/flow/issues/1515
- bayesian_horse 9y agoCoffeeScript is still relevant to me, mainly because of the sparser syntax. For React, I wrap the components in functions to create syntax that is even a little clearer than JSX, but still valid CoffeeScript. I am still waiting for someone to finish a Python bytecode VM or transpiler for javascript which is actually worth using...
- molszanski 9y ago> waiting for someone to finish a Python bytecode VM or transpiler for javascript which is actually worth using... What is that? Running JS in a python VM?
- bayesian_horse 9y agoNo, by that I mean a VM to run Python bytecode, running in the browser. There is at least one project which tries to do that, but it's not really useable. The point would be to have access to a large part of the standard library, the full Python data model and a good integration with the javascript platform. Only then would there be a reason to use it.
- molszanski 9y agoOh. Now I get your point.
- uranian 9y agoYou have no clue what you are talking about..
- nkohari 9y agoNot sure what the weird hostility is all about, but... I think what they meant is that CoffeeScript doesn't support explicit variable declarations, instead implicitly defining variables when they are first referenced. That makes it hard to add explicit type declarations, because you've got nowhere to declare them.
- koolba 9y agoYes that's exactly the point I was making. Adding types atop something like that would be particularly difficult though not impossible. The hardest part is doing something that maintains the magic of picking the proper scope to define a var at without adding "var" declarations.
- uranian 9y agoSorry, no weird hostility, just an observation. The weirdness comes more from the way how you guys think about creating a typed language. What the heck would a CS compiler with static type checking have to do with var statements apart from generating them in the final JS as it does now already?
- koolba 9y agoIf you don't have var statements then you lose the number one place to specify the type of the variable. It's not about making whatever inferences you can from the code, it's about giving the compiler/typechecker the detail it needs to make more accurate inferences.
- nkohari 9y agoWell, in TypeScript you attach the type declaration to the variable declaration: let foo: number; It's true that you could add the type declaration to the first assignment of the variable, as in: foo: number = 42 ...but that's kind of awkward, because CoffeeScript only has an assignment expression and not a variable declaration statement. You can hack the two together but it's going to make things confusing and complex for the compiler to implement. What happens if you do this: foo = 42 ... 30 lines later ... foo: string = "hello" They're both just assignment expressions, but now they can carry extra metadata about the variable that's being assigned, so there's all sorts of cases you have to consider. Anyways, I was just trying to clarify what the comment you replied to meant. IMO, the real problem is that TypeScript's type system is incredibly powerful, and a huge portion of the compiler is devoted to static checking for it. Even if the CoffeeScript compiler could support types, it makes very little sense to spend the effort when TypeScript already exists. The syntactic difference between the two languages is too small. I could see an option for CoffeeScript to target TypeScript as a transpilation output, but then you'd lose the tooling (tslint) built for TypeScript. And again, why? If you want types, write TypeScript. That's what it's there for.
- andrew_wc_brown 9y agoI love CS and I see myself using it for another 5 years. The aversion developers have had to CS never were legit reasons. If you put all your time in ES6 and CS, I think you'll be more productive in CS. The only issue I foresee is tools being built around the use of ES6 that compel you to abandon it. I've learned that less is better. I don't use JQuery, I don't use Lodash. I don't use React, I don't use ImmutableJs, I don't use Webpack or CommonJS. All of these tools are more a burden that a blessing and you just end up stacking on 100 dependieces asking "Is this really better?" I learned this lesson with Cucumber/RSpec/Caybara and etc.. I started asking why I had to use these over plain old TDD and so I used TDD for a month and I found out everything was totally fine. I don't even really use Arel in ActiveRecord. I just write raw SQL that serves JSON directly back. I made it easier for me to organize SQL in partials just like views and to injects variables and conditions into my SQL. I went to great lengths to evaluate all these tools because as a work-form home contractor I can afford the time, and the "what if" really bothers me. I still working in Rails with Sprockets and CS and I write all my SQL by hand. Less is Better. All these kids want to do a bunch of busy work and for no good reason. It makes the feel productive. I have tried dropping CS but the difference in productive was too great to drop. Its not that I'm married to CS its that it does what it says. It makes your JS concise so you can be more productive. I felt AngularJS dying and so I spent 3 months researching React and building client apps in React. I just didn't get all the work extra work and settled on Mithril. The hardest thing was giving up writing HTML-like templates like I did in AngularJS but I remember that was my first aversion to AngularJS where I swallowed the medicine. I had to swallow more medicine to unlearn that. Mithril paird with CoffeScript makes writing markup in CS a joy. If I had to do that in regular JS I could see why people would be compelled to use ugly JSX.
- vinceguidry 9y agoThanks for the pointer to Mithril. Hadn't heard of it.
- computerex 9y agoI don't think JSX is ugly. React/JSX are incredibly simple and follow the less is more philosophy.
- 9y ago
- thebouv 9y agoRemember when CoffeeScript was "modern JS"? The whole JS stack switches every 2 years or so? I mean, it actually switches faster than that and that's what everyone jokes about (JavaScript fatigue and what not). But a full turnover of the stack is about 2 years?
- fiatjaf 9y agoThis thing made me use React in 2013 (when JSX was still weird): http://blog.vjeux.com/2013/javascript/react-coffeescript.html http://blog.vjeux.com/2013/javascript/react-coffeescript.htm... Now JSX is not weird anymore, it's just horrible.
- baby 9y agoCan you give an example of a CoffeeScript file being transcribed to modern JS :)? I just want to see which syntax I prefer.
- alangpierce 9y agoSure, here's src/main-process/atom-protocol-handler.coffee from the atom codebase (it's a really long URL because it includes the whole source code): http://bit.ly/2rIhFD4 http://bit.ly/2rIhFD4 In this case, the __guardMethod__ usages should probably be rewritten by hand after running decaffeinate. In general, you can paste any code into the left side of http://decaffeinate-project.org/repl http://decaffeinate-project.org/repl to get output on the right side.
- traviswingo 9y agoDoesn't Coffeescript convert Coffeescript to JS? `coffee -c input.coffee`.
- slig 9y agoYes, but it's not "modern JS" and it's not meant to be edited. This tool converts it to modern JS (ES6) that has classes, template strings, etc.
- dyeje 9y agoNever understood the appeal of CS, JavaScript just isn't painful enough to warrant it. Been happy to watch it's slow exit from the mainstream. https://trends.google.com/trends/explore?q=coffeescript https://trends.google.com/trends/explore?q=coffeescript
- scotty79 9y agoMeaningful indentation. I love python and I'm really not sure why other compilers/interpreters ignore indentation since it's the de facto way of how people express structure in any computer language. Also when CS happened, JS didn't even have classes. Half of the ES6 features are CS inspired.
- abritinthebay 9y ago> Also when CS happened, JS didn't even have classes. And it only has class syntax now. Classes in JS are still prototypical inheritance under the hood (and probably always will be). > Half of the ES6 features are CS inspired. This is rewriting history. Most of ES6 was under active development before CS was a thing. It's more accurate to say that the same modern languages features inspired both (with ES6 thankfully being less Ruby-like).
- scotty79 9y agoLast time I tried it did not support cjsx -> jsx, as far as I can tell, so it's useless for migrating React code bases.
- alangpierce 9y agoTake a look at depercolator, it's a wrapper around cjsx-transform, decaffeinate, and some other things: https://github.com/bugsnag/depercolator https://github.com/bugsnag/depercolator There's an open decaffeinate bug for CJSX ( https://github.com/decaffeinate/decaffeinate/issues/1009 https://github.com/decaffeinate/decaffeinate/issues/1009 ) but I suspect it'll be really hard to do anything better than just running cjsx-transform and then running regular decaffeinate. To get JSX on the JS side after decaffeinate, you can use the create-element-to-jsx script from https://github.com/reactjs/react-codemod https://github.com/reactjs/react-codemod .
- rattray 9y agoThe folks behind this have been at it a long time. I first used decaffeinate over 18mo ago and while it was already quite helpful then, it's come a tremendous distance since. Very tricky problem to solve well; bravo! Somewhat surprised nobody has mentioned the upcoming release of CoffeeScript 2.0, which outputs ES6 natively: http://coffeescript.org/v2/ http://coffeescript.org/v2/ It's in beta2 now and ready for trial.
- grogenaut 9y agoIn 3-5 years will we get "FreeRange" to convert typescript to "modern" JavaScript?
- aphextron 9y agoI love this. We've truly come full circle. Does it support a compile to Typescript step?
- alangpierce 9y agobulk-decaffeinate ( https://github.com/decaffeinate/bulk-decaffeinate https://github.com/decaffeinate/bulk-decaffeinate ) supports an outputFileExtension option that can make it so the resulting files end in .ts. But really, the main thing to do when converting JavaScript to TypeScript is adding types, which decaffeinate is much less qualified to do. But if you're going to move from CoffeeScript to TypeScript, JavaScript is probably a pretty important intermediate step.
- YamiOdymel 9y agoPeople might not know but CoffeeScript 2 is out already and supports the ES6 syntaxes. I've been using it for a large Vue.js SPA (with webpack) and some small projects, it really improves the development and saving me a lot of the time. https://github.com/coffeescript6/discuss https://github.com/coffeescript6/discuss
- deleted 9y ago[deleted]