Skip to content

Meta: Support JSX similar to Literate CoffeeScript? #4529

Closed
@GeoffreyBooth

Description

@GeoffreyBooth

I’ve been thinking about JSX, and a way that CoffeeScript could perhaps support it. In particular, I’ve been thinking about how it’s actually somewhat similar to Literate CoffeeScript:

  • Literate CoffeeScript is essentially a Markdown file that uses indentation to define CoffeeScript code blocks.
  • JSX is JavaScript that uses XML open and closing tags to define HTML blocks (that themselves can contain JavaScript, within braces).

I haven’t used JSX in a project, so if I’m oversimplifying here, please correct me.

What if the CoffeeScript compiler detected XML open and closing tags and treated them the same as backticks? In other words, everything from the first < of the first opening tag through to the last > of the last closing tag would be passed through unmodified, similar to embedded JavaScript. The compiler would therefore be outputting JSX, and then the next step in the build chain would be Babel with the JSX transform.

This wouldn’t even be a breaking change. Currently <div> throws unexpected <, and </div> throws missing / (unclosed regex).

We also wouldn’t be favoring one framework over another, because we’re just outputting the straight HTML, not converting it into code like React.createElement. Vue has added support for JSX, and the Babel transform is now generic to allow future frameworks to adopt it, so it’s not a React-specific thing anymore.

How is this different from coffee-react or coffee-react-transform or CJSX, you might ask?

  • That project is deprecated, for starters, and is pinned to version 1.9.1 of the compiler.
  • It didn’t rely on Babel, compiling straight to the final JavaScript React.createElement output, and therefore was dependant on React; the last version supports “React >= 0.14.x”.
  • It aimed to compile CoffeeScript within the XML blocks.

That last point is important. In my proposal, within an XML block you would need to use this.foo, not @foo. You couldn’t write code like coffee-react‘s example {<p key={n}>This line has been printed {n} times</p> for n in [1..5]}—you would need to write the JavaScript equivalent. But I don’t think this is so terrible. In my experience, most of the JavaScript inside a template is very minimal, generally just references to objects or basic constructs like if statements or loops. (Again, please correct me if I’m wrong.) It would be a formidable challenge to parse CoffeeScript within XML tags, which is probably why coffee-react was deprecated; but I don’t think we need to take on that task.

I can certainly see people objecting to this proposal on the grounds that people shouldn’t be forced to use JavaScript, or even snippets of it, within a CoffeeScript file. Fair enough. Another perfectly valid objection is that JSX isn’t hard to achieve right now using plain backticks:

getGreeting = (user) ->
  if user
    `<h1>Hello, {formatName(user)}!</h1>`
  else
    `<h1>Hello, Stranger.</h1>`

var getGreeting;

getGreeting = function(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  } else {
    return <h1>Hello, Stranger.</h1>;
  }
};

See CoffeeScript and Babel conversions. If we don’t implement this proposal, at the very least we should perhaps at this example to the docs, either in the backticks section or in a new section discussing JSX.

But anyway, now that JSX is growing into a framework-independent standard, and we can support it in a minimal, framework-independent way, should we? And if we should, does this seem like the way to add support for it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions