Skip to content

Syntax changes #1318

@Rich-Harris

Description

@Rich-Harris

Update 12 April

Most of these decisions are fairly settled at this point — you can see a summary here.

Original issue follows:


I've referred to this obliquely in other issues, Gitter, etc, but haven't quite got to the point of starting a proper discussion about it.

Essentially, for version 2 I'd like to move away from the Mustache-esque template syntax to something a bit lighter and more modern, which boils down to using one curly brace instead of two:

<h1 class={myClass}>Hello {name}!</h1>

The success of JSX has proved that the second curly is unnecessary. Moreover, a lot of people — particularly those who have been exposed to React — have a visceral negative reaction to double curlies, many of them assuming that it brings with it all the limitations of crusty old languages like Mustache and Handlebars, where you can't use arbitrary JavaScript in expressions.

We would also put an end to this sort of thing — component properties being typecast — at the same time. (See #657).

Quoted attributes

At present, Svelte allows you to quote attributes and properties for the sake of your syntax highlighter:

<Widget x={{y < z ? }}>this generally breaks highlighting</Widget>
<Widget x="{{y < z ? }}">this generally breaks highlighting</Widget>

I'd suggest that we keep that behaviour, so as not to force people to adopt additional tooling (which doesn't yet exist anyway). The same goes for directive arguments — these would be unchanged.

Control flow

It's less clear what to do about if/else/elseif, each, and await/then/catch. We could of course do this...

{#if foo}
  <p>foo!</p>
{else}
  <p>not foo!</p>
{/if}

...though part of me feels like we're just continuing to accept the premise of Handlebars, and that there's a more natural approach waiting to be discovered. Just for the sake of argument:

#if (foo) {
  <p>foo!</p>
} else if (bar) {
  <p>bar!</p>
} else {
  <p>neither foo nor bar!</p>
}

<ul>
  #each (cats as cat) {
    <li><a target='_blank' href={cat.video}>{cat.name}</a></li>
  }
</ul>

#await (promise) {
  <p>wait for it...</p>
} then (answer) {
  <p>the answer is {answer}!</p>
} catch (error) {
  <p>well that's odd</p>
}

Maybe that makes you want to barf, I don't know. But I'd be very interested to hear everyone's ideas.

Keyed each blocks

I'm in favour of replacing @name with by name, as discussed in #703 — it has some clear advantages.

Triples

Triples could arguably be unchanged — if anything, the increased distinction between {text} and {{{html}}} is a good thing. Or we could go in a totally different direction like <{html}>. Eager to hear thoughts.

Static tags

#364 — briefly discussed, but never acted upon: the idea of adding syntax for declaring tags static, as a way of saying to the compiler 'this will never change after the initial render, don't worry about generating update code'. Would be nice if whatever choices we make preserve that possibility.

Escaping

If you needed a literal { character in your markup, you could always do {'{'}. (This is how it's done in React.) Or you could do &#123;, which is pleasingly easy to remember. Does there need to be some method of escaping beyond that?

Migrating

All this stuff should come with an simple, completely automated way to upgrade an existing template. There could be a CLI tool, and the REPL would detect old templates and show an 'upgrade' button.


Obviously we shouldn't rush into anything. But changes like these are best made earlier on in a project's lifecycle, so I'm eager to hear what people think so that we can start making some progress. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions