Skip to content

Commit 42ce8d7

Browse files
authored
breaking: warn on self-closing non-void HTML tags (#11114)
* warn on self-closing non-void HTML tags * fix tests * changeset * account for foreign namespace
1 parent 5665498 commit 42ce8d7

File tree

137 files changed

+1475
-1116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+1475
-1116
lines changed

.changeset/nine-cooks-join.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
breaking: warn on self-closing non-void HTML tags

packages/svelte/src/compiler/phases/2-analyze/validation.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ import {
1515
import { warn } from '../../warnings.js';
1616
import fuzzymatch from '../1-parse/utils/fuzzymatch.js';
1717
import { binding_properties } from '../bindings.js';
18-
import { ContentEditableBindings, EventModifiers, SVGElements } from '../constants.js';
18+
import {
19+
ContentEditableBindings,
20+
EventModifiers,
21+
SVGElements,
22+
VoidElements
23+
} from '../constants.js';
1924
import { is_custom_element_node } from '../nodes.js';
2025
import {
2126
regex_illegal_attribute_character,
@@ -572,6 +577,21 @@ const validation = {
572577
}
573578
}
574579

580+
if (
581+
context.state.analysis.source[node.end - 2] === '/' &&
582+
context.state.options.namespace !== 'foreign' &&
583+
!VoidElements.includes(node.name) &&
584+
!SVGElements.includes(node.name)
585+
) {
586+
warn(
587+
context.state.analysis.warnings,
588+
node,
589+
context.path,
590+
'invalid-self-closing-tag',
591+
node.name
592+
);
593+
}
594+
575595
context.next({
576596
...context.state,
577597
parent_element: node.name

packages/svelte/src/compiler/warnings.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ const options = {
250250
"The 'customElement' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
251251
};
252252

253+
const misc = {
254+
/** @param {string} name */
255+
'invalid-self-closing-tag': (name) =>
256+
`Self-closing HTML tags for non-void elements are ambiguous — use <${name} ...></${name}> rather than <${name} ... />`
257+
};
258+
253259
/** @satisfies {Warnings} */
254260
const warnings = {
255261
...css,
@@ -261,7 +267,8 @@ const warnings = {
261267
...components,
262268
...legacy,
263269
...block,
264-
...options
270+
...options,
271+
...misc
265272
};
266273

267274
/** @typedef {typeof warnings} AllWarnings */

packages/svelte/tests/compiler-errors/samples/component-slot-nested-error-2/main.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Nested>
66
<div slot="slot1">
77
<div>
8-
<div slot="slot2" />
8+
<div slot="slot2"></div>
99
</div>
1010
</div>
1111
</Nested>

packages/svelte/tests/compiler-errors/samples/component-slot-nested-error-3/main.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Nested>
66
<div>
77
<div>
8-
<div slot="slot2" />
8+
<div slot="slot2"></div>
99
</div>
1010
</div>
1111
</Nested>

packages/svelte/tests/compiler-errors/samples/component-slot-nested-error/main.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
<Nested>
66
<div slot="slot1">
7-
<div slot="slot2" />
7+
<div slot="slot2"></div>
88
</div>
99
</Nested>

packages/svelte/tests/css/samples/general-siblings-combinator-await-not-exhaustive/input.svelte

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,24 @@
1818
.c ~ .g { color: green; }
1919
</style>
2020

21-
<div class="a" />
21+
<div class="a"></div>
2222

2323
{#await promise then value}
24-
<div class="b" />
24+
<div class="b"></div>
2525
{:catch error}
26-
<div class="c" />
26+
<div class="c"></div>
2727
{/await}
2828

2929
{#await promise}
30-
<div class="d" />
30+
<div class="d"></div>
3131
{:catch error}
32-
<div class="e" />
32+
<div class="e"></div>
3333
{/await}
3434

3535
{#await promise}
36-
<div class="f" />
36+
<div class="f"></div>
3737
{:then error}
38-
<div class="g" />
38+
<div class="g"></div>
3939
{/await}
4040

41-
<div class="h" />
41+
<div class="h"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-await/input.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
.b ~ .d { color: green; }
1818
</style>
1919

20-
<div class="a" />
20+
<div class="a"></div>
2121

2222
{#await promise}
23-
<div class="b" />
23+
<div class="b"></div>
2424
{:then value}
25-
<div class="c" />
25+
<div class="c"></div>
2626
{:catch error}
27-
<div class="d" />
27+
<div class="d"></div>
2828
{/await}
2929

30-
<div class="e" />
30+
<div class="e"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-each-2/input.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
}
2828
</style>
2929

30-
<div class="a" />
30+
<div class="a"></div>
3131

3232
{#each array as item}
33-
<div class="b" />
34-
<div class="c" />
33+
<div class="b"></div>
34+
<div class="c"></div>
3535
{/each}
3636

37-
<div class="d" />
37+
<div class="d"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-each-else-nested/input.svelte

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,43 +35,43 @@
3535
.e ~ .f { color: green; }
3636
</style>
3737

38-
<div class="a" />
38+
<div class="a"></div>
3939

4040
{#each array as a}
41-
<div class="b" />
41+
<div class="b"></div>
4242
{#each array as b}
43-
<div class="c" />
43+
<div class="c"></div>
4444
{:else}
45-
<div class="d" />
45+
<div class="d"></div>
4646
{/each}
4747
{/each}
4848

4949
{#each array as c}
5050
{#each array as d}
51-
<div class="e" />
51+
<div class="e"></div>
5252
{/each}
5353
{:else}
54-
<div class="f" />
54+
<div class="f"></div>
5555
{/each}
5656

5757
{#each array as x}
58-
<div class="g" />
58+
<div class="g"></div>
5959
{#each array as y}
6060
{#each array as z}
61-
<div class="h" />
61+
<div class="h"></div>
6262
{/each}
6363
{:else}
64-
<div class="i" />
64+
<div class="i"></div>
6565
{/each}
66-
<div class="j" />
66+
<div class="j"></div>
6767
{/each}
6868

69-
<div class="k" />
69+
<div class="k"></div>
7070

7171
{#each array as item}
7272
{#each array as item}
73-
<div class="l" />
73+
<div class="l"></div>
7474
{:else}
75-
<div class="m" />
75+
<div class="m"></div>
7676
{/each}
77-
{/each}
77+
{/each}

packages/svelte/tests/css/samples/general-siblings-combinator-each-else/input.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
.b ~ .c { color: green; }
1414
</style>
1515

16-
<div class="a" />
16+
<div class="a"></div>
1717

1818
{#each array as item}
19-
<div class="b" />
19+
<div class="b"></div>
2020
{:else}
21-
<div class="c" />
21+
<div class="c"></div>
2222
{/each}
2323

24-
<div class="d" />
24+
<div class="d"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-each-nested/input.svelte

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,49 +65,49 @@
6565
.g ~ .i { color: green; }
6666
</style>
6767

68-
<div class="a" />
68+
<div class="a"></div>
6969

7070
{#each array as item}
71-
<div class="b" />
72-
<div class="c" />
71+
<div class="b"></div>
72+
<div class="c"></div>
7373
{/each}
7474

7575
{#each array as item}
7676
{#each array as item}
7777
{#each array as item}
78-
<div class="d" />
78+
<div class="d"></div>
7979
{/each}
80-
<div class="e" />
80+
<div class="e"></div>
8181
{/each}
82-
<div class="f" />
82+
<div class="f"></div>
8383
{/each}
8484

8585
{#each array as item}
86-
<div class="g" />
86+
<div class="g"></div>
8787
{#each array as item}
88-
<div class="h" />
88+
<div class="h"></div>
8989
{#each array as item}
90-
<div class="i" />
90+
<div class="i"></div>
9191
{/each}
9292
{/each}
9393
{/each}
9494

9595
{#each array as item}
96-
<div class="j" />
96+
<div class="j"></div>
9797
{#each array as item}
98-
<div class="k" />
98+
<div class="k"></div>
9999
{#each array as item}
100-
<div class="l" />
100+
<div class="l"></div>
101101
{/each}
102102
{/each}
103103
{/each}
104104

105105
{#each array as item}
106106
{#each array as item}
107107
{#each array as item}
108-
<div class="m" />
108+
<div class="m"></div>
109109
{/each}
110-
<div class="n" />
110+
<div class="n"></div>
111111
{/each}
112-
<div class="o" />
113-
{/each}
112+
<div class="o"></div>
113+
{/each}

packages/svelte/tests/css/samples/general-siblings-combinator-each/input.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
}
99
</style>
1010

11-
<div />
11+
<div></div>
1212

1313
{#each array as item}
14-
<span class="each" />
15-
<div class="each" />
16-
<span class="each" />
17-
<div class="each" />
14+
<span class="each"></span>
15+
<div class="each"></div>
16+
<span class="each"></span>
17+
<div class="each"></div>
1818
{/each}
1919

20-
<span />
20+
<span></span>

packages/svelte/tests/css/samples/general-siblings-combinator-if-not-exhaustive-with-each/input.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
.b ~ .c { color: green; }
1919
</style>
2020

21-
<div class="a" />
21+
<div class="a"></div>
2222

2323
{#if foo}
24-
<div class="b" />
24+
<div class="b"></div>
2525
{:else}
2626
{#each array as item}
27-
<div class="c" />
27+
<div class="c"></div>
2828
{/each}
2929
{/if}
3030

31-
<div class="d" />
31+
<div class="d"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-if-not-exhaustive/input.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
.b ~ .c { color: green; }
1515
</style>
1616

17-
<div class="a" />
17+
<div class="a"></div>
1818

1919
{#if foo}
20-
<div class="b" />
20+
<div class="b"></div>
2121
{:else if bar}
22-
<div class="c" />
22+
<div class="c"></div>
2323
{/if}
2424

25-
<div class="d" />
25+
<div class="d"></div>

packages/svelte/tests/css/samples/general-siblings-combinator-if/input.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
.c ~ .d { color: green; }
1919
</style>
2020

21-
<div class="a" />
21+
<div class="a"></div>
2222

2323
{#if foo}
24-
<div class="b" />
24+
<div class="b"></div>
2525
{:else if bar}
26-
<div class="c" />
26+
<div class="c"></div>
2727
{:else}
28-
<div class="d" />
28+
<div class="d"></div>
2929
{/if}
3030

31-
<div class="e" />
31+
<div class="e"></div>

0 commit comments

Comments
 (0)