Skip to content

Commit e3ad1ac

Browse files
fix: follow spec for customElement option (#13247)
* fix: follow spec for `customElement` option * tweak messages, add link to details that will be included on future docs site --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 501f415 commit e3ad1ac

File tree

11 files changed

+78
-8
lines changed

11 files changed

+78
-8
lines changed

.changeset/stale-rats-check.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+
fix: follow spec for `customElement` option

packages/svelte/messages/compile-errors/template.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,15 @@ HTML restricts where certain elements can appear. In case of a violation the bro
344344
345345
## svelte_options_invalid_tagname
346346

347-
> Tag name must be two or more words joined by the "-" character
347+
> Tag name must be lowercase and hyphenated
348+
349+
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
350+
351+
## svelte_options_reserved_tagname
352+
353+
> Tag name is reserved
354+
355+
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
348356

349357
## svelte_options_unknown_attribute
350358

packages/svelte/src/compiler/errors.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,12 +1352,21 @@ export function svelte_options_invalid_customelement_shadow(node) {
13521352
}
13531353

13541354
/**
1355-
* Tag name must be two or more words joined by the "-" character
1355+
* Tag name must be lowercase and hyphenated
13561356
* @param {null | number | NodeLike} node
13571357
* @returns {never}
13581358
*/
13591359
export function svelte_options_invalid_tagname(node) {
1360-
e(node, "svelte_options_invalid_tagname", "Tag name must be two or more words joined by the \"-\" character");
1360+
e(node, "svelte_options_invalid_tagname", "Tag name must be lowercase and hyphenated");
1361+
}
1362+
1363+
/**
1364+
* Tag name is reserved
1365+
* @param {null | number | NodeLike} node
1366+
* @returns {never}
1367+
*/
1368+
export function svelte_options_reserved_tagname(node) {
1369+
e(node, "svelte_options_reserved_tagname", "Tag name is reserved");
13611370
}
13621371

13631372
/**

packages/svelte/src/compiler/phases/1-parse/read/options.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import { NAMESPACE_MATHML, NAMESPACE_SVG } from '../../../../constants.js';
44
import * as e from '../../../errors.js';
55

6-
const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;
7-
86
/**
97
* @param {AST.SvelteOptionsRaw} node
108
* @returns {AST.Root['options']}
@@ -229,6 +227,21 @@ function get_boolean_value(attribute) {
229227
return value;
230228
}
231229

230+
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
231+
const tag_name_char =
232+
'[a-z0-9_.\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}-]';
233+
const regex_valid_tag_name = new RegExp(`^[a-z]${tag_name_char}*-${tag_name_char}*$`, 'u');
234+
const reserved_tag_names = [
235+
'annotation-xml',
236+
'color-profile',
237+
'font-face',
238+
'font-face-src',
239+
'font-face-uri',
240+
'font-face-format',
241+
'font-face-name',
242+
'missing-glyph'
243+
];
244+
232245
/**
233246
* @param {any} attribute
234247
* @param {string | null} tag
@@ -238,7 +251,11 @@ function validate_tag(attribute, tag) {
238251
if (typeof tag !== 'string') {
239252
e.svelte_options_invalid_tagname(attribute);
240253
}
241-
if (tag && !regex_valid_tag_name.test(tag)) {
242-
e.svelte_options_invalid_tagname(attribute);
254+
if (tag) {
255+
if (!regex_valid_tag_name.test(tag)) {
256+
e.svelte_options_invalid_tagname(attribute);
257+
} else if (reserved_tag_names.includes(tag)) {
258+
e.svelte_options_reserved_tagname(attribute);
259+
}
243260
}
244261
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
compileOptions: {
5+
customElement: true
6+
}
7+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svelte:options customElement="emotion-😍" />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
compileOptions: {
5+
customElement: true
6+
}
7+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svelte:options customElement="custom-" />

packages/svelte/tests/validator/samples/tag-invalid/errors.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"code": "svelte_options_invalid_tagname",
4-
"message": "Tag name must be two or more words joined by the \"-\" character",
4+
"message": "Tag name must be lowercase and hyphenated",
55
"start": {
66
"line": 1,
77
"column": 16
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"code": "svelte_options_reserved_tagname",
4+
"message": "Tag name is reserved",
5+
"start": {
6+
"line": 1,
7+
"column": 16
8+
},
9+
"end": {
10+
"line": 1,
11+
"column": 41
12+
}
13+
}
14+
]

0 commit comments

Comments
 (0)