-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Syntax changes #1318
Comments
All Ideas presented here are very reasonable. Particularly I like Static Tags and control flow syntax changes the most. |
Actually, I feel no pain with current, mustache-like, syntax. Maybe because I work with it in Ractive and worked even before Ractive. But I always thought that if Svelte will change its syntax to something new, it will more look like ES6 Template Literals: <h1 class="${myClass}">Hello {name}!</h1> But in this case, we need to decide which syntax will be for blocks: ${if foo}
<p>foo!</p>
{else}
<p>not foo!</p>
{/if} If there are any serious reasons to not use this standard, well, then it's completely up-to-you. Btw, I also personally like Dust-syntax: https://github.com/linkedin/dustjs/wiki/Dust-Tutorial |
I like it, single/double braces sometimes trips when switching between svelte and react. |
Currently you can't use arbitrary JavaScript expressions everywhere you would like to. We could simplify the compiler code by having one expression parsing path instead of each directive and binding using it's own. For example, transitions require an object literal when it could be desirable to use a member, setting the options on data. There are issues to solve, such as methods being pulled from helpers in bindings but pulled from the public component API in events. However, this is a digression from the topic of this issue and should be discussed in more depth elsewhere if it has any merit. My apologies. For the rest:
|
Exciting stuff! 😃 I'm positive on these changes, and excited about decreasing the curlies. The Is there any reason not to use backslashes to escape curlies? Maybe going down the route of any escape characters at all would be confusing, and people would start expecting things like |
|
I wondered about that. But as you mention, the control flow makes it tricky, because it's not really a template literal — it's a DSL. I thought perhaps it's better to have something that's explicitly different, than something a bit 'uncanny valley'.
Am by no means wedded to that second idea — I came up with it more or less as I was typing it. Just want us to have a think about whether there is a better solution than
I had the same question earlier and googled 'react escape curly braces' and landed here: facebook/react#1545. Feels like a slippery slope. Re static tags, I'm not suggesting that they should be part of these initial changes, just that we don't prevent ourselves from doing it in future. Static-ifying stuff at a component level could be done, but it doesn't address this sort of thing: {{#each dynamicList as item}}
<p>[[item.name]]</p>
{{/each}} Tag-level and component-level aren't mutually exclusive though, we could do them independently. |
Things that I miss most from Vue: <!-- Bind expression to attribute with `:` -->
<h1 class="some-static-class">Hello!</h1>
<h1 :class="someClassExpression">Hello!</h1>
<!-- Bind event handler with `@` and pass event as first param. -->
<h1 @click="greet">Hello!</h1>
<!-- Event handler options -->
<button @click.prevent="greet">Hello!</button>
<:Window @keydown.esc="close"></:Window> What bothers me most from Svelte: <!-- I want to bind the value of this custom input just like I would bind to normal input -->
<input bind:value="query" /> <!-- works -->
<search-input bind:value="query" /> <!-- doesn't work :/ --> Proposal for double binding: <search-input ::value="query" /> For templating, I don't mind the handlebars. It's familiar for Vue and Angular users. I have never regretted keeping logic in my templates to a minimum. So I don't agree with the "visceral negative reaction" argument. |
IDK about doubles vs. singles, but |
@Rich-Harris I've an idea, why not use a unified scheme for all things:
For example: <h1 class="{=myClass}">Hello {=name}!</h1> Control flow {#if foo}
<p>foo!</p>
{:else}
<p>not foo!</p>
{/if}
<ul>
{#each cats as cat}
<li><a href="{=cat.video}">{=cat.name}</a></li>
{/each}
</ul>
{#await promise}
<p>wait for it...</p>
{:then answer}
<p>the answer is {answer}!</p>
{:catch error}
<p>well that's odd</p>
{/await} Keyed each blocks <ul>
{#each cats as cat, key}
<li><a target='_blank' href="{=cat.video}">{=cat.name}</a></li>
{/each}
</ul> Triples <div>{&html}</div> Static tags <div>{~text}</div> Escaping Possible
Most likely, the
As I could imagine, the unified scheme should simplify parsing. Correct me if I'm wrong. p/s Sorry for verboseness, you said that you're very interested to hear everyone's ideas. |
single curlies are fine with me. As for the blocks I'd prefer |
I like the single curlies for interpolation. Using them for For static tags, iirc Angular 1.something introduced one-time bindings, where the value inside the As for escaping: For some reason I wasn't thinking about the |
I've used I like @PaulMaly's idea, but I would like it if the "default" sign was |
I just gave @PaulMaly's suggestions a proper re-read, and they are interesting. I like the succinctness but I'm also concerned about this resulting in punctuation salad. (Insert Perl joke here.) Perhaps some middle ground - which I realize is unhelpfully vague. |
@jacwright @Conduitry Thanks,
Agree. I just tried to show the main idea. But, if obligatory using of signs would help with a literal
Yep, it's just a number ideas but seems we already have some of those things like |
I applaud the effort to simplify things for 2.0! The current syntax feels sprawling and ad hoc. The general approach that @PaulMaly suggested looks like a good idea to me. You can remember a simple rule like "everything inside curlies is Svelte specific stuff", and then look up details as needed as you go. The specifics are of course infinitely bikesheddable. To reduce punctuation salad, maybe common interpolation could simply be I think blocks could also be simplified to just use reserved words, like On the general topic of simplifying syntax in a breaking way, I would like to recall #878 and #1069. Remove the poorly motivated special syntax for declaring dependencies of computed properties, so the |
+1 for new control flow +1 for |
Oh man... Please, please, PLEASE keep the normal quotation inline as you mention above regarding tooling: Can we also bikeshed on stuff like
The parser can throw an error if one uses a reserved component namespace. I too like @PaulMaly's notation as well as the recommendation elsewhere to allow |
Oh, also, I agree:
|
I like these ideas. We can also consider this #1322 for V2. |
What happens when a new framework becomes really popular and starts using double curlies? |
👍+1 Btw, we already have one reserved tag: |
For my opinion Mustache syntax, it's ok and makes changes this only by taste reasons it's a bad idea. |
Would it be possible to make the templating engine pluggable, so that the community could write e.g. a svelte-jsx or svelte-lithtml adapter? |
If I remember right too many things locked on the internal handwritten parser. For real good approach, we can use something like Flex/Bison but I don't know about JS in this case. |
Since we already have special "HTML" tags like <:if myVar>
<span>Something</span>
<:else />
<span>Something else</span>
</:if> <ul>
<:each myArray as el>
<li>{el}</li>
</:each>
</ul> That makes a clear distinction between things that control the DOM structure ( |
Oh my, I wasn't expecting so much feedback! Thanks everyone, this is fantastic. @hperrin's idea is pretty cool. You get auto-completion as a nice bonus! The self-closing <:if myArray.length>
<ul>
<:each myArray as el, i>
<li>{el}</li>
</:each>
</ul>
<:else>
Nothing in the array
</:else>
</:if>
<:await promise>
<p>loading...</p>
<:then value>
<p>the value is {value}</p>
</:then>
<:catch error>
<p>oops! {error.message}</p>
</:catch>
</:await> Maybe it's too weird having
I don't totally follow this point — @thgh the Svelte equivalent for those Vue idioms is this — I'm not sure I understand what the drawbacks are? (These are more flexible and explicit IMHO, and barely any extra characters.) <h1 class="some-static-class">Hello!</h1>
<h1 class={{someClassExpression}}>Hello!</h1>
<h1 on:click="greet(event)">Hello!</h1> For the event modifier stuff see #1088. Bindings on custom elements is something we should support, I don't think we currently have an issue for it though. @PaulMaly that's a really strong proposal, thanks. Agree with the other comments the
In theory yes. The compiler really only needs the source string and an AST. If we properly formalised and documented the Svelte AST format, then we could allow anyone to build their own parser. I think the costs of doing so are more human than technical though — having a single canonical template language is better from the point of view of documentation, tutorials, Stack Overflow, shareable components, etc. So, consolidating everyone's input so far, my read is that the current front-runner is something like this...
...with the following possible additions:
But a last minute challenger has entered the race: <:if foo>
<p>foo!</p>
</:if> |
Regarding static tags, we could use another special tag: <:Static>
Hello, {user.name}. Even if you update your name, I'll still call you by the old one!
</:Static> Also, -1 for <{html}>. (It will definitely confuse editors.) |
Regarding @hperrin's suggestion, the simple case works for HTML parsing in browsers. Will more complex expressions hurt that at all? <:if myHelper() !== some.value && foo.bar.length>
Foo is true!
<:else />
Foo is false. :(
</:if> I like it. But I'm leaning to |
I'm personally not a huge fan of
|
Two-way is unchanged — <!-- before -->
<Foo bar={{bar}} />
<Foo :bar /> <!-- shorthand equivalent -->
<!-- after -->
<Foo bar={bar} />
<Foo {bar} /> <!-- shorthand equivalent --> @PaulMaly as soon as humanly possible. Going to do as much work on it this weekend as time allows. |
@Rich-Harris it needs a bit of a cleanup (and decoupling from vscode). I can shove it up on GitHub once I have done this |
What about:
For some consistency? |
The format for directives is bind:expression1=expression2 Conceptually, this is like doing bind:expression1={expression2} ...then it's sort of like saying Probably not articulating myself very well here, but tl;dr is I think |
After looking at the syntax as it stands now, I like it. I think the shorthand example should be updated to the example you provided a few comments up this page @Rich-Harris. It makes it more clear. The one piece that feels confusing to me is they keyed array syntax.
|
@jacwright I was waiting to see if anyone would bring that up... I kind of had the same feeling about {#each cats as cat, i, key={cat.name}} I'll throw a few more options on the table: {#each cats as cat, i @cat.name} {#each cats as cat, i | cat.name} {#each cats as cat, i {cat.name}} {#each cats as (cat, i) {cat.name}} {#each cats as cat, i (cat.name)} {#each cats as cat, i (key = cat.name)} I think I prefer options that don't involve the |
Makes sense |
I like Beyond that, I lean towards |
As long as I can do Multiple cursor selection in various IDEs (cmd + d) can be really cumbersome when trying to select single letters because the letter |
{For each cat in cats where cat is identified by name}
<span>{cat's name}</span>
{.} Personally, I've always been fond of the syntax of the English language. |
My vote is for: {#each cats as cat, i (cat.name)} The parens still imply that it's an expression, and no double curlies. And, it could support a space in that expression, unlike Imagine |
Think I agree with @hperrin. I'll start implementing {#each words as word (word)}
<p>{word}</p>
{/each} — but I suspect that'd be true of whatever we chose. |
Alright, this is implemented in 1.61. You can opt in with |
Personally I find odd the use of {:else} I think it can be a source of bugs for developers. {else} can't be because of new bindings. |
@andreujuanc Why do you think it’ll be a source of bugs? What difference between this syntax change and any other? |
i think its should be candidate for dev mode to catch possible user mistake |
I think it's a change, and people are used to the prev version. I can be wrong, but muscle memory sometimes is hard to beat. Another point against it, it's that the character is relatively smaller and less visible than pound, so eyeballing syntax might be tricky. I do understand the use of it. I get the benefits. But something tells me that it's odd. On the other hand for example I find AMAZING and well thought all the other changes. |
I just think that these problems are common for any syntax changes. Not just for this one. |
I leave this here for an inspiration Marko & NodeJS: STREAMING, ASYNC AND UI COMPONENTS! OH MY! |
@constgen Basically, nothing new. I use all these things even with Ractive. One more bicycle. |
I like declarative conditionals, loops, asyncs, etc. |
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:
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:
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
, andawait
/then
/catch
. We could of course do this......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:
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
withby 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{
, 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!
The text was updated successfully, but these errors were encountered: