svelte: Svelte parses HTML all wrong

Describe the bug

I’m a little shaken up. For as long as I’ve been programming, I thought that this…

<div />

…was shorthand for this:

<div></div>

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…

<div />hello!

…is equivalent to this — the hello! is inside the div, not outside it:

<div>hello!</div>

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:

  1. Continue to parse HTML incorrectly
  2. Parse HTML correctly, treating <div /> as <div>, which is also a breaking change but one that would be nightmarish to debug

Ideally 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:

document.body.innerHTML = `<div />hello!`
console.log(document.querySelector('div').textContent);

Then, in a Svelte component, do this:

<script>
  import { onMount } from 'svelte';

  let div;
	
  onMount(() => {
    console.log(div.textContent);
  });
</script>

<div bind:this={div} />hello!

In the first case, ‘hello!’ is logged. In the second case, the empty string is logged.

Logs

No response

System Info

This currently applies to all versions of Svelte

Severity

annoyance

About this issue

  • Original URL
  • State: closed
  • Created 3 months ago
  • Reactions: 248
  • Comments: 83 (35 by maintainers)

Most upvoted comments

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 <div>hello</div> or <div></div>hello depending on which you meant’ categorically does not introduce a new source of confusion. It takes something ambiguous and requires you to make it explicit.

There’s actually a third option which is to just warn when the behavior happens (for now) and then maybe ~do # 2~ error out in the future.

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 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.

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 <div /> into a Svelte component or vice versa, you’ll end up with a completely different element tree. That’s just unacceptable. We’ve been saved by the fact that this situation is somewhat rare, but that doesn’t change the basic fact.

And I’m not suggesting that we start treating <div /> the same way as HTML — that’s clearly confusing and silly behaviour. I’m suggesting that we prevent the ambiguity from arising in the first place.

There’s actually a third option which is to just warn when the behavior happens (for now) and then maybe do # 2 in the future.

This would be an acceptable compromise, if there’s a lot of malformed markup in the wild because of Prettier.

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 <div /> if you wrote it like that). Given how this was not a real issue (some may even prefer it / find the current behavior much more intuitive/consistent with component shorthands), do we really need to change this? We also shouldn’t error on <input />, because who really cares? At the very least this means adjusting prettier-plugin-svelte first, etc etc, so this is a multi-version game for very little gain IMO.

I feel like this is simply a documentation issue … People who read the docs know

‘Fix it with documentation’ is the same sort of mistake as ‘fix it with configuration’. In both cases, you’ve added complexity and pushed the burden onto the user.

How many people do you think have encountered that part of the Vue docs, buried near the bottom of a very long page? And how much shorter and more approachable could open source docs be if documentation wasn’t treated as the solution to design problems? The very fact that an unnecessary distinction exists between ‘in-DOM’ templates and normal ones is itself a self-inflicted problem.

Take it from someone who has been in the open source game a while: people do not read the docs.

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.

Why diverge from HTML there but go for correctness here?

We’re talking about two different forms of ‘divergence’:

  1. disallowing certain things outside a strict subset of HTML (i.e. no string event handlers) to prevent footguns
  2. accepting certain syntactical forms, but interpreting them completely differently 🤡

What I’m proposing here is that we diverge consistently — always 1, never 2.

You should make a poll on Twitter

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.

Why not implement a svelte.config.js option

Because if we did that every time we couldn’t get 100% unanimous consensus on something, your svelte.config.js file would be 700 lines long. Every Svelte project would look and behave completely differently, and you wouldn’t be able to use any library installed from npm that didn’t use the same options as you.

You’re right, like that it wouldn’t. I’m still against it, because for many people it’s much more ergonomic (especially when using web components) to use self-closing in some situations - and they’ve got used to it now. The fact that noone in 5 years (or more?) has opened an issue about this means that the “I copy-paste some HTML code using self-closing tags into a Svelte file and had an hour long debugging session” situations almost certainly never came up.

It’s about eliminating a source of ambiguity.

…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 <div />foo means <div></div>foo and not <div>foo</div>. I agree with others here, I just don’t think this is worth it.

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.

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 array = [1, 2, 3,] created an array of length 4 in Svelte because we historically parsed JavaScript incorrectly.

I’m absolutely flabbergasted at the pushback here.

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. In my opinion what Svelte / JSX does in this matter is a better solution than what HTML offers.

It’s vanishingly rare that adding configuration is the right solution to an API design problem. Configuration is cowardly — it removes the burden of designing something correctly off maintainers’ shoulders and puts it on users instead. It adds technical debt and complexity (for users, in the form of more convoluted documentation and decision fatigue, and for maintainers in implementation terms). And it reduces the incentive to fix the buggy code! It’s drawbacks all round.

It’s true that there’s a possibility of third party libraries triggering warnings that are outside your immediate control. But the same is true of new a11y warnings, for example. Avoiding a warning because of third parties would amount to a policy of never introducing any warnings, and that would clearly be unacceptable. The onwarn option in things like vite-plugin-svelte provides an escape hatch 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 </div> everywhere.

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 svelte-preprocess-self-closing-tags which is just going to be installed in like 90% of all svelte projects. You’re also going to have to deal with years of people wanting this back. I think changing this is great ideologically, but from a practical view it only has downsides.

Vue does both, in a browser context it does it the browser way, in a Single-File-Component (SPA) where you have a build step, it handles it for you

This is a spectacularly awful design, and one that we absolutely do not wish to emulate.

(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)

Taking into account that Svelte 5 already restricts HTML by forbidding “incorrect” DOM structure, e.g. <table><tr></tr></table> and <button><button></button></button>, I think it’s okay also to forbid self-closing for non-void elements. Plus, it is easily fixable by the migrating script, unlike the incorrect DOM structure.

Pros:

  • we follow standards
  • no issues when taking svelte html templates to plain html

Cons:

  • inconsistent with every other frontend framework, including the web component ones
  • breaking changes with existing ecosystem of comments that use this
  • everyone really expects HTML parse like you originally did

IMO the cons far outweigh the benefits, this would become a very common gotcha if we just parse like HTML 5 does on spec

I’m just here for the posterity.

Right now, if you copy-paste some HTML containing <div /> into a Svelte component or vice versa, you’ll end up with a completely different element tree. That’s just unacceptable.

Is the self-closing tag the only thing that makes Svelte output different from HTML?

A few examples

<div>
</div>

<style>
	div {
		width: 20px;
		height: 20px;
		background-color: red;
		&:empty {
			background-color: green;
		}
	}
</style>
  • Svelte 5 will output a green square as the space character is deleted.
  • HTML 5 will output a red square because whitespace will be preserved.
<div>Hello world!
  • Svelte 5 will output Error compiling....
  • HTML 5 will output <div>Hello world!</div> since the unclosed tag is not a problem for it.

If you dive into the error correction inherent in HTML, there are likely other examples.

Why not implement a svelte.config.js option that allows developers to choose whether Svelte should enforce the explicit closing of non-void elements while leaving valid void elements alone, resulting in a compilation error if not adhered to? Then, set the default behaviour in the npm create svelte setup to disallow self-closing tags for non-void elements.

Unless svelte errors out and forces the dev to disambiguate

That’s… exactly what I’m proposing?

or create an inconsistency by allowing self-closing custom tags?

To be clear, this only applies to HTML elements. In other namespaces (such as SVG), self-closing tags are permitted. By extension, Svelte components would continue to have self-closing tags.

I feel like this is simply a documentation issue. This is a feature in Vue, and a documented one: https://vuejs.org/guide/essentials/component-basics.html#self-closing-tags

People who read the docs know that self-closing tags are allowed because it’s Vue, not HTML.

I don’t think the downgrade in DX is worth the “disambiguation”.

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. <div><p>Hello world!</div> with an unclosed p tag works in Svelte 5.

In HTML 5, you can write <div></p>Hello world!</div> (will cause an error in Svelte 5) or <div>Hello world!</p> (which will also cause an error in Svelte 5) and, weird as it sounds, this is normal for HTML 5. At one time, the reason for abandoning XHTML was that HTML 5 just knows how to handle errors, while XHTML does not. Self-closing tags are in fact also an error and the HTML 5 standard describes how to handle it, as well as many other cases. But we use frameworks to make life easier, not the other way around.

Because if we did that every time we couldn’t get 100% unanimous consensus on something, your svelte.config.js file would be 700 lines long. Every Svelte project would look and behave completely differently, and you wouldn’t be able to use any library installed from npm that didn’t use the same options as you.

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.

inconsistent with every other frontend framework, including the web component ones

This is straightforwardly untrue. As shown above, Angular does the right thing here. And if by ‘the web component ones’ you mean things like Lit, I’m afraid you’re mistaken:

image

breaking changes with existing ecosystem of comments that use this

Not if we do a warning instead of a comment. Between that, automated migrations, and fixing the Prettier plugin, this is a non-issue.

everyone really expects HTML parse like you originally did

You’re right, and this is a great opportunity to help correct that widespread misunderstanding, to everyone’s benefit.

This is a rabbit hole where svelte should go with the consensus.

The results here from trying to follow HTML 5 behavior will result in more headaches than potential “problems” it could solve.

IMO and most developers opinion, the current behavior which is adopted by everyone and every framework, is the correct one.

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

The fact that noone in 5 years (or more?) has opened an issue about this means that the “I copy-paste some HTML code using self-closing tags into a Svelte file and had an hour long debugging session” situations almost certainly never came up.

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.

I’m not sure why you think the existence of bug B is some sort of reason to allow bug A to persist.

I could be wrong, but not too long ago there were 2 HTML specifications. One from W3C (I’m not sure if this is the right link, the specs are hard to understand 😬) and one from WHATWG and, oops, they were partially incompatible. And despite the fact that the W3C was considered the benchmark, eventually the WHATWG specification squeezed out the W3C specification because the W3C specification existed in its own fictional world and did not reflect the implementation in browsers, whose vendors trampled their way to their own vision of HTML, which eventually became the current specification. Let’s be private, Svelte, JSx, Vue now occupy quite a large part of the framework market and the fact that they have self-closing tags is well received by a large number of users. It’s just convenient and I don’t consider it a bug provided it’s explicitly documented.

Take it from someone who has been in the open source game a while: people do not read the docs.

Many people don’t even open the HTML specification. Why, when you can just copy the answer from StackOverflow. 😄 And if a person in such a situation writes <input data-id=test-2/>, it means that he shot himself in the foot not at the moment when he wrote it, but long before that.

Personally, I chose Svelte not for being faster than X or consuming less memory, but for its Developer Experience, which, among other things, consists of such a tiny improvement as self-closing tags.

Svelte exists to make our life as developers easier.

For me, this includes closing empty elements in “shorthand” with /> instead of a full closing tag. This isn’t valid HTML, but most will expect the compiler to handle it and extend it to <div></div>. I can’t imagine anyone intentionally writing <div />hello and expecting the output to be <div>hello</div>. Although I admire the desire to adhere to the specs, the Svelte example in the issue is exactly why I love Svelte: it just makes more intuitive sense. Allowing it for SVG and some HTML elements (and Svelte components) but not for other elements is not intuitive, even though it’s the spec. The specs and differing browser implementations are often ambiguous and I believe Svelte, being an opinionated compiler, is in the perfect position to make webdev less enigmatic. Forcing users to adhere to specs does not achieve this goal, and definitely does not warrant a breaking change.

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.

I always thought this was a thought-out Svelte specific feature and I liked it so far. Why not simply keep it?

If someone was using <div /> or <my-thing /> in plain HTML, they arguably already made a mistake. This then being differently broken in Svelte does not feel like a real issue to me.

The results here from trying to follow HTML 5 behavior

I’m not proposing we ‘follow HTML 5 behavior’. Please read the proposal before you disagree with it.

Thinking about this again, honestly this opens such a can of worms considering how browsers are off-spec as well

Browsers just discard invalid sequences of tags, close unclosed tags “somewhere”, ignores slashes at the end of tags, etc

Each one of those is a footgun that was allowed because its in production somewhere and it would cost more to follow spec, so I really dont understand the desire to add this one of all the things, especially considering that iirc this isnt even part of the HTML spec, but a feature of HTML parsers to allow imperfect input (I could be wrong on that one tho), so adding this still would make svelte " a superset of HTML", or considering what @Rich-Harris just said a bit earlier, more like “a superset of a subset of html”

While I think JSX(and others - Vue is fine with <div/> too) is “correct” and more intuitive here than HTML - if the goal is too be as close to HTML is possible, I think giving a warning/error that self-closing is ambiguous is a good compromise.

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 array = [1, 2, 3,] created an array of length 4 in Svelte because we historically parsed JavaScript incorrectly.

I’m absolutely flabbergasted at the pushback here.

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 (<div><section></div></section>), 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 And I guess relates #9477

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.

2. Large group wants to keeps things as is (be jsx compliant).

Sevlte’s syntax isn’t JSX. It handles whitespace differently (like HTML) for a start.

Demo

I think the correct way to do this is to copy Vue’s approach. I’ll mention something no one else has yet about that, keep reading.

  • When using a template compiler, Vue allows users to stylistically write any HTML tags as self-closing and actually close them like you’d expect. This is then enforced across all components with a linting rule. But the default (recommended) linting rule enforces only doing /> on void elements. This is how Vue handles it with the Vue-Template-Compiler and ESLint-Plugin-Vue.
  • HOWEVER! When the Run-time version of Vue is used (via CDN), it just reads in whatever markup is placed in the HTML, and by the time Vue gets to it, it’s already been parsed by the browser and placed in the DOM. So in that scenario <div />Text still becomes <div>Text</div>.

Vue does both, in a browser context it does it the browser way, in a Single-File-Component (SPA) where you have a build step, it handles it for you, but the default linting settings advise you to avoid this all-together.

As always, Vue did it right all along.

Why diverge from HTML there but go for correctness here?

We’re talking about two different forms of ‘divergence’:

  1. disallowing certain things outside a strict subset of HTML (i.e. no string event handlers) to prevent footguns
  2. accepting certain syntactical forms, but interpreting them completely differently 🤡

What I’m proposing here is that we diverge consistently — always 1, never 2.

I get your point, and its mostly valid, but how is letting the developer create an unclosed div by treating the self-closing tag as an opening div, priming a metaphorical mine that blows up at the next self-closing div not a footgun? (Unless svelte errors out and forces the dev to disambiguate)

And what about custom components that accept optional children/slots (with fallbacks or otherwise)? Do you force an empty <Custom></Custom>, or create an inconsistency by allowing self-closing custom tags?

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.

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 <MyHorizontalRule /> into HTML already wouldn’t do anything useful so there’s no problem there.

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 <svelte:... /> tags? The behavior right now is fine because it’s consistent and intuitive. Forcing people to write the closing tag instead of accepting the shorthand /> has a fairly large DX impact, only because there might be a tiny amount of people confused that <div />hello is not the same in their HTML file. It’s also subjectively more elegant and semantic: <div /> implies to me that the div will not have any children, while <div></div> looks unfinished.

My summary from reading:

  1. Broad agreement that being spec compliant on this is not desirable.
  2. Large group wants to keeps things as is (be like jsx on this).
  3. Large group wants to error out (like Angular). And if we error out then make it a warning in Svelte 5 and error in Svelte 6.

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!

At the end of the day, it doesn’t seem like Svelte’s job to “fix” HTML by taking HTML syntax and intentionally treating it differently than browsers—ultimately Svelte’s behavior regarding HTML should match the HTML standards as they exist in the real world. While I can understand the knee-jerk reaction against what is essentially, “let’s reproduce a ‘bug’ we accidentally fixed”, I can’t for the life of me understand who it would ACTUALLY harm. Is anyone here using self-closing, block-level HTML tags in their projects? I mean we can make up hypothetical situations all day about who’s pasting what where or how something is better or worse but at the end of the day the standards are set and implemented and ambiguity IS bad.

@Serator which HTML validator are you actually using to validate this?

@singlyfy I stopped using the validator a long time ago, if that’s what we’re talking about. The browser is the best validator. 😄


To be clear, this only applies to HTML elements. In other namespaces (such as SVG), self-closing tags are permitted. By extension, Svelte components would continue to have self-closing tags.

@Rich-Harris Slashes are still allowed for some html elements and there is an interesting feature here.

A very simple example:

<input data-id=test-1 />
<input data-id=test-2/>
<input data-id="test-3" />
<input data-id="test-4"/>

Try to guess what Svelte will output and what HTML will output.

Output and explanation
  • Svelte 5 (whitespace between tags changed for easier comparison, original output one line):
<input data-id="test-1">
<input data-id="test-2">
<input data-id="test-3">
<input data-id="test-4">
<input data-id="test-1">
<input data-id="test-2/">
<input data-id="test-3">
<input data-id="test-4">

Note the / in the output.

Details are described in the specification:

Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/), which on foreign elements marks the start tag as self-closing. On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.

image

The HTML validator I linked to earlier in this post considers this code to be fully valid and only throws 3 notifications, and <input data-id=test-2/> is normal for it.

Is this really the “beautiful” HTML we want to get?

An ambiguous and generally considered bad practice syntax (albeit spec-compatible because of backward compatibly debt) is usually a linter concern

As Svelte is both a language and a compiler, it would be reasonable to either raise a warning OR an error depending on if it prefers HTML compatibility OR forcing explicit syntax

Maybe default to warning for the Svelte compiler and error for eslint-plugin-svelte ?

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 <div/> while Vue and JSX doesn’t.

@kkarpeev you omitted the ‘or vice versa’ from your quote. That’s the larger problem https://github.com/sveltejs/svelte/issues/11052#issuecomment-2035357540

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.

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 <div /> with <div></div> in the editor on save?

Slashes are still allowed for some html elements

This is a misunderstanding — closing slashes on HTML elements are universally ignored. It’s true that a / immediately following an unquoted attribute value is treated as part of the attribute instead of being ignored, and Svelte gets this wrong. We should treat this case the same as <div /> — as something that causes a warning (or, ultimately, an error) that prompts the user to disambiguate. I’m not sure why you think the existence of bug B is some sort of reason to allow bug A to persist.

As articulated at the top, I would love to apply the same logic to void elements, but that’s not currently possible because of Prettier. Fortunately, Prettier at least inserts a space before a />, so cases like data-id=test-2/ are truly rare.

IMO and most developers opinion, the current behavior which is adopted by everyone and every framework, is the correct one.

by “everyone and every framework”, you actually mean frameworks which use JSX, right?

of course, many frameworks and libraries use HTML as-is and therefore have different behaviour to svelte

its probably worth deciding if svelte templates are JSX or HTML.

similar to the long running prettier discussion on self-closing tags - JSX should be able to self-close any tag, while HTML should allow void tags and ignore self-closing markers.

if the decision is that svelte templates are HTML, Rich is correct and you shouldn’t be able to have a self closing div

Html/original authors right now: https://youtu.be/HMqZ2PPOLik?si=YYSwODD84uDUfOJ2