-
-
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
Svelte parses HTML all wrong #11052
Comments
Further reference: #8923 |
I don't think we can do this for 5.0 - there's probably dozens of apps/libraries that use the self-closing behavior because it was the default in prettier-plugin-svelte for ages (the latest version doesn't care anymore, but will preserve |
There's actually a third option which is to just warn when the behavior happens (for now) and then maybe As a side note, I was around during the transition to HTML5 and never knew this either. Opinionated, but HTML5 browser behavior here is completely non-sensical and I'd be perfectly happy to leave it as is. Put another way, this seems one minor area where modern frameworks have improved on bad browser behavior, with likely no real drawbacks. [I updated my comment above in bold since I originally misunderstood the proposal and agree with erroring out.] |
The issue of self-closing tags has been brought up many times (1 (post), 2, 3...) in the WHATWG and has been continually closed for the reason "it's too late to change anything, as many tools are based on current HTML behavior". Even the WHATWG regulars recognize the problem. |
I actually thought that Svelte 5 intentionally tried to fix this problem with HTML, because it is a major source of bugs that are very difficult to spot (from my experience working in web dev). There are so many things wonky about HTML that I discover, to find some thread from a decade ago as to why it is the way it is, and generally it's because the benefit in fixing it isn't worth breaking the web. I'd probably lean towards keeping the existing behaviour if I was being honest – and maybe back down on how much we set ourselves on being a true superset of HTML. |
This isn't about whether or not Svelte's handling of these tags is preferable or correct or whatever. It's about eliminating a source of ambiguity. Right now, if you copy-paste some HTML containing And I'm not suggesting that we start treating
This would be an acceptable compromise, if there's a lot of malformed markup in the wild because of Prettier. |
(Actually, I just read the 'maybe do # 2 in the future' bit, which I disagree with — I meant that warning now and then erroring in 6+ would be an acceptable compromise) |
...by introducing a new source of confusion, because the average web dev (us all included, as seen by this issue appearing now, and not years before) things that |
Right now, this code... <div />hello will be understood differently by different people. Adding an error or a warning that says 'this is ambiguous, you must either do |
You're right, like that it wouldn't. |
I get that it's more convenient, and in the absence of other considerations convenience is worth optimising for. But I think it's pretty weird that if you take this code from a Svelte component... <div>
<my-thing /> is this inside or outside my-thing?
</div> ...and paste it into an HTML file (or a CodePen or whatever), you get totally different behaviour. We're not doing our community any favours here, and we're not being good citizens of the web. |
@Rich-Harris I mean you can only go so far anyway, you can't exactly copy and paste this: <div>
<button onclick={() => { console.log('clicked me') }} id="1">123</button>
</div> |
Obviously you can't copy-paste Svelte features in the template, any more than you can copy-paste runes and expect them to work. But this is like saying that because you can't use runes outside Svelte, it'd be acceptable if I'm absolutely flabbergasted at the pushback here. |
Or, people have had that experience only to realize their understanding of how these tags work was wrong (in HTML and Svelte), didn't see anyone else confused by it, and felt embarrassed that nobody is apparently struggling with the undocumented discrepancy but them, and didn't open an issue. There are also plenty of situations where this may not manifest in a visible (or overly annoying) way. Maybe people just think their selector is wrong or they style the parent instead of the node they actually want to style because it doesn't work for some reason. This seems like one of those insidious situations where it's obscure and confusing enough to make people think they're wrong. Or they work around it and think their understanding was incorrect. |
If someone was using |
The issue is less that people will paste malformed HTML into Svelte and experience it working differently, it's the reverse — people taking valid Svelte snippets into an HTML context and experience breakage there. This needn't mean literally copying and pasting code — it also means people taking an understanding of how HTML works that came from using Svelte and discovering that things break in odd ways when they try to use other frameworks (or no framework at all). We're literally training people to write broken code. This is very bad. |
Is the self-closing tag the only thing that makes Svelte output different from HTML? A few examples
If you dive into the error correction inherent in HTML, there are likely other examples. |
I would class the first of those as a bug — we should probably preserve whitespace in that situation. The second is fine, because (as with this proposal) we're just eliminating a source of confusion, rather than actively producing the wrong output |
Yep, but that doesn't apply to nested tags. In HTML 5, you can write |
I think we can add a warning for self closing elements that aren’t void. Doing a quick search and they’re used plenty in svelte components for non void elements. I don’t think it should be an error in Svelte 5 though. You’ll cause so much friction in upgrading and people will get frustrated. I’m still personally in the category that feels like Svelte shouldn’t strive for complete HTML compatibility. Being HTML-like, and ironically JSX-like in my eyes, is fine and it has a valid place in the ecosystem. It’s the Svelte way. |
I think the compromise of showing a warning now and then maybe enforcing it down the line is a good move. It would make most codebases more explicit about this behavior and other people that don't like it, can just disable the warning globally, and go about their own codebases at their own discretion. |
Also maybe svelte 5 migration script could have a optional option to basically choose the behavior and apply it to the whole codebase, so people's codebases are not filled with a lot of warnings when upgrading. |
The difference is that with the self-closing tags, the current "incorrect" behavior is the consensus among multiple framework (jsx expands self-closing tags as well), and is the preferred behavior for not only most devs, but the creators of the "correct" behavior as well. As opposed to an example that would be filed as an issue within hours of being a thing At some point correctness becomes less useful. A lot of http servers/clients are "incorrect" according to the spec, and that is by design, even cloudflare had to switch out to "incorrect" http parsers. More than that, the browser itself allows for incorrect HTML like unclosed non-void tags (which your example here actually has. I believe that's invalid HTML according to the spec), "weaved"/incorectly nested tags ( ), etc, depending on the browser. Not only does this support my point about " correctness" sometimes not being thr highest priority, it also leaves ambiguity since different browsers handle different kinds of invalid HTML differently, thus you have to both choose between browser implementations, and between browser behavior and HTML spec.
You can dive into all that hell in the name of correctness, or accept the consensus. And don't forget that one issue where a guy was using an obscure feature of HTML by passing function names as strings to buttons or smth which wasnt a thing in svelte, and iirc was then closed (I'll try finding and linking the issue in a sec). Why diverge from HTML there but go for correctness here? Edit: found the issue I was mentioning: #9437 |
Html/original authors right now: https://youtu.be/HMqZ2PPOLik?si=YYSwODD84uDUfOJ2 |
At most this is a linter issue, making this into a breaking change is genuinely not worth it. You should make a poll on Twitter to gather (albeit not entirely accurate) some numbers on how many developers would rather keep the current behavior. As you said Svelte isn't a framework - it's a language, a difference like this which improves DX is welcomed with open arms. Considering the alternatives, Angular errors on |
We're talking about two different forms of 'divergence':
What I'm proposing here is that we diverge consistently — always 1, never 2.
It will be as useful as if you ask voters whether they want lower taxes or better public services — the answer will be 'yes'. I'm heartened to see Angular doing the right thing here. |
The spec on this is unintuitive and obviously wrong. This is one of the additions that JSX got right. When I started using svelte I was happy that self closing tags were present. I imagine that the vast majority of devs would rather ignore the spec on this one than have to deal with extra It's also not intuitive that you can use self closing tags for SVG and components. You're going to have to document this somewhere anyways. Finally, I imagine that the result of this change would be the immediate creation of something like |
I always thought this was a thought-out Svelte specific feature and I liked it so far. Why not simply keep it? |
I think a warning and a migration script would suffice. As a developer I'd rather stick to HTML spec rather than framework specific specs. Great catch spotting this! |
Why not keep this option inside the svelte components themselves? It would solve this issue, and will help users define how they want this to behave without breaking it when sharing their components around. Example: <script lang="ts">
// behavior of some-component.svelte
// ...
</script>
<svelte:spec-compliant {true} />
<div />hello! If we keep this option tucked in per svelte file, it would make it only relevant when the developer absolutely needs this behavior without applying it to the whole project. |
Svelte exists to make our life as developers easier. For me, this includes closing empty elements in "shorthand" with We're not "training people to write broken code". We're not writing HTML, we're writing Svelte; we're training people to appreciate Svelte. |
What about just permanently making this a warning, while falling back on the XML behaviour when there is an ambiguity between XML and HTML and including a linter that automatically fixes it to be unambiguous regardless of whether it is parsed as HTML or as XML? For reference, Vue SFC templates also use XML, and so does JSX. Warnings would help people not struggle to figure out why the behavious change and the linter would give them a fix. Errors do have the advantage that you can't ignore them of course. Imho the real way to fix this long term would be to have web browsers implement XML as an alternative content type to HTML and have an actual spec that strictly bans the HTML behaviour. Deprecating HTML fully is hard to do of course, but we're in a weird situation where every mainstream javascript framework uses XML to generate markup instead of dealing with HTML, and where the most commonly used linter uses XML semantics. |
My summary from reading:
|
Sevlte's syntax isn't JSX. It handles whitespace differently (like HTML) for a start. |
i always understood that svelte templates were HTML, in which case, self closing markers should be ignored/errored as mentioned above, thats the question we should really answer IMO: is a svelte template HTML? if it is, you already have your answer. though it would be a big change ofc to disallow such syntax |
Another thing to consider is what is most beginner friendly. Beginners get frustrated with errors. But silently doing something different than what was written (like jsx) can catch out beginners too... Would beginners be the least frustrated/surprised if we replaced |
If you look at comments reactions, especially the OP, you'll see a broad agreement that being spec compliant on this is desirable. |
I interpreted that as support for erroring out. |
Right, my interpretation is:
So imho regardless of which path forward is taken in the end there should be a warning raised to prevent a silent ambiguity, but there's a few options for what to do after the warning has been raised. |
Um, just one question. Where can you get some HTML containing |
@kkarpeev you omitted the 'or vice versa' from your quote. That's the larger problem #11052 (comment) |
Funnily enough, I've always written it Just a couple of thoughts.
|
I think the framework should try to
So, by default, the compiler could issue a warning, explaining the issue and also explaining how to turn this warning into an error in future versions the default could be an error instead of a warning, but I would still let users choose to simply ignore it, with no warning or error what so ever |
Void tags will be left alone, at least for now, because otherwise we'd be fighting with Prettier. I think these are fairly harmless anyway, unlike the ambiguous non-void case
The goal here is to make HTML behave the same inside and outside Svelte. In other namespaces (i.e. SVG), self-closing tags are allowed. We can think of Svelte components as being one of those 'other namespaces', and pasting
This is a different way of phrasing 'solve it with configuration', which is addressed in #11052 (comment). It becomes unwieldy as soon as your project has dependencies, who may choose to deal with it in a different fashion |
Hi. I read this discussion and see a waste of time on an extremely insignificant problem. Svelt has many other serious problems, but what is being discussed now is something that is not encountered in normal HTML writing practice. Moreover, the standard validator considers a self-closing tag to be an error. |
There is this article that provides more context (and to clear up some other corner cases). After seeing how JSX handles , I vote for getting rid of HTML whitespace and going the JSX route. |
Why is this the goal? This isn't the case for the majority of Svelte components; loops, render tags, etc. already break this idea. Shouldn't Svelte strive to be as unambiguous as possible? Why should we allow some elements to be self-closing but not others? What about |
Please don't make a breaking change for this. I like being able to write React accepts it. You'd be following in pretty good cowpaths if you continued to accept it. |
Nothingburger bug that'd make life harder. Self closing tags are very useful and prevent duplication. Even an eslint warning would be more annoying than this. |
At the end of the day, does the proposed change mean we can't use It seems to be a small trade-off to align more closely with how HTML functions, whether we like it or not, and to avoid complicating Svelte (even if just a bit) by adding new configurations, documentation, and potential issues. This turned into a discussion on syntactic sugar, and I understand the resistance. Svelte users, myself included, are quite sensitive to syntax changes and reluctant to give up even the smallest bit of convenience. But is it worth the cost of shifting from "it's just HTML" to "it's just HTML, but we treat X differently"? |
As said above, this syntax is used widely probably in no small part because React allows it. If anything I'd say drop the
line. With Signals / Runes Svelte is finally gaining reactivity on par with (or really, better than) React. "It's just html" is honestly the least interesting, least important part of Svelte for the typical user. |
The comments on this thread are getting progressively less useful and more off-topic, and a lot of people are straight-up missing the point (or misunderstanding the proposal), so I'm going to lock it at least for now. As is often the case with these sorts of changes, a vocal minority opposes it, but the emoji reactions tell the true story — most people agree that this is something we should do. The reason this took so long to surface is that self-closing tags are rare. By extension, this change will be a lot less disruptive than some of you seem to imagine. IDEs already tend to do the right thing anyway — it's pretty common that if you write Side-note, but if your markup contains empty |
To update your components en masse, you can use the following command: npx svelte-migrate self-closing-tags This will prevent Svelte 5 warning you to replace |
Describe the bug
I'm a little shaken up. For as long as I've been programming, I thought that this...
...was shorthand for this:
It turns out it's not. Self-closing tags just aren't a thing in HTML — the
/>
is simply ignored by browsers altogether. In other words, this......is equivalent to this — the
hello!
is inside the div, not outside it:Svelte, however, treats
<div />
as<div></div>
. For a framework that prides itself on being a superset of HTML, this is a glaring error.What should we do?
I think the right thing to do is
disallow(edit: warn on) self-closing non-void HTML tags (this only applies to HTML, not other namespaces). This is a breaking change, but the alternatives are:<div />
as<div>
, which is also a breaking change but one that would be nightmarish to debugIdeally we would also disallow self-closing void elements (i.e.
<input>
rather than<input />
), but whether or not this is realistic depends on whether Prettier's current habit of adding an unnecessary/>
to void elements prevents us from doing that.Reproduction
Navigate to
about:blank
, and do this:Then, in a Svelte component, do this:
In the first case, 'hello!' is logged. In the second case, the empty string is logged.
Logs
No response
System Info
Severity
annoyance
The text was updated successfully, but these errors were encountered: