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 <rich.harris@vercel.com>
pull/13260/head
wackbyte 5 days ago committed by GitHub
parent 501f415190
commit e3ad1acc90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: follow spec for `customElement` option

@ -344,7 +344,15 @@ HTML restricts where certain elements can appear. In case of a violation the bro
## svelte_options_invalid_tagname
> Tag name must be two or more words joined by the "-" character
> Tag name must be lowercase and hyphenated
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
## svelte_options_reserved_tagname
> Tag name is reserved
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
## svelte_options_unknown_attribute

@ -1352,12 +1352,21 @@ export function svelte_options_invalid_customelement_shadow(node) {
}
/**
* Tag name must be two or more words joined by the "-" character
* Tag name must be lowercase and hyphenated
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function svelte_options_invalid_tagname(node) {
e(node, "svelte_options_invalid_tagname", "Tag name must be two or more words joined by the \"-\" character");
e(node, "svelte_options_invalid_tagname", "Tag name must be lowercase and hyphenated");
}
/**
* Tag name is reserved
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function svelte_options_reserved_tagname(node) {
e(node, "svelte_options_reserved_tagname", "Tag name is reserved");
}
/**

@ -3,8 +3,6 @@
import { NAMESPACE_MATHML, NAMESPACE_SVG } from '../../../../constants.js';
import * as e from '../../../errors.js';
const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;
/**
* @param {AST.SvelteOptionsRaw} node
* @returns {AST.Root['options']}
@ -229,6 +227,21 @@ function get_boolean_value(attribute) {
return value;
}
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
const tag_name_char =
'[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}-]';
const regex_valid_tag_name = new RegExp(`^[a-z]${tag_name_char}*-${tag_name_char}*$`, 'u');
const reserved_tag_names = [
'annotation-xml',
'color-profile',
'font-face',
'font-face-src',
'font-face-uri',
'font-face-format',
'font-face-name',
'missing-glyph'
];
/**
* @param {any} attribute
* @param {string | null} tag
@ -238,7 +251,11 @@ function validate_tag(attribute, tag) {
if (typeof tag !== 'string') {
e.svelte_options_invalid_tagname(attribute);
}
if (tag && !regex_valid_tag_name.test(tag)) {
if (tag) {
if (!regex_valid_tag_name.test(tag)) {
e.svelte_options_invalid_tagname(attribute);
} else if (reserved_tag_names.includes(tag)) {
e.svelte_options_reserved_tagname(attribute);
}
}
}

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
compileOptions: {
customElement: true
}
});

@ -0,0 +1 @@
<svelte:options customElement="emotion-😍" />

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
compileOptions: {
customElement: true
}
});

@ -0,0 +1 @@
<svelte:options customElement="custom-" />

@ -1,7 +1,7 @@
[
{
"code": "svelte_options_invalid_tagname",
"message": "Tag name must be two or more words joined by the \"-\" character",
"message": "Tag name must be lowercase and hyphenated",
"start": {
"line": 1,
"column": 16

@ -0,0 +1,14 @@
[
{
"code": "svelte_options_reserved_tagname",
"message": "Tag name is reserved",
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 41
}
}
]

@ -0,0 +1 @@
<svelte:options customElement="font-face" />
Loading…
Cancel
Save