Skip to content

Commit 1ca6619

Browse files
committed
fix: follow spec for customElement option
1 parent 501f415 commit 1ca6619

File tree

10 files changed

+70
-4
lines changed

10 files changed

+70
-4
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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ HTML restricts where certain elements can appear. In case of a violation the bro
346346

347347
> Tag name must be two or more words joined by the "-" character
348348
349+
## svelte_options_reserved_tagname
350+
351+
> Tag name is reserved and conflicts with standard element names
352+
349353
## svelte_options_unknown_attribute
350354

351355
> `<svelte:options>` unknown attribute '%name%'

packages/svelte/src/compiler/errors.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,15 @@ export function svelte_options_invalid_tagname(node) {
13601360
e(node, "svelte_options_invalid_tagname", "Tag name must be two or more words joined by the \"-\" character");
13611361
}
13621362

1363+
/**
1364+
* Tag name is reserved and conflicts with standard element names
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 and conflicts with standard element names");
1370+
}
1371+
13631372
/**
13641373
* `<svelte:options>` unknown attribute '%name%'
13651374
* @param {null | number | NodeLike} node

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-" />
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 and conflicts with standard element names",
5+
"start": {
6+
"line": 1,
7+
"column": 16
8+
},
9+
"end": {
10+
"line": 1,
11+
"column": 41
12+
}
13+
}
14+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<svelte:options customElement="font-face" />

0 commit comments

Comments
 (0)