Skip to content

fix: error on invalid element name #13057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gentle-needles-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: error on invalid element name
12 changes: 4 additions & 8 deletions packages/svelte/messages/compile-errors/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@

> This type of directive is not valid on components

## component_invalid_name

> Component name must be a valid variable name or dot notation expression

## const_tag_cycle

> Cyclical dependency detected: %cycle%
Expand Down Expand Up @@ -136,10 +132,6 @@

> `</%name%>` attempted to close element that was already automatically closed by `<%reason%>` (cannot nest `<%reason%>` inside `<%name%>`)

## element_invalid_tag_name

> Expected valid tag name

## element_unclosed

> `<%name%>` was left open
Expand Down Expand Up @@ -358,6 +350,10 @@ HTML restricts where certain elements can appear. In case of a violation the bro

> `<svelte:self>` components can only exist inside `{#if}` blocks, `{#each}` blocks, `{#snippet}` blocks or slots passed to components

## tag_invalid_name

> Expected a valid element or component name. Components must have a valid variable name or dot notation expression

## tag_invalid_placement

> {@%name% ...} tag cannot be %location%
Expand Down
27 changes: 9 additions & 18 deletions packages/svelte/src/compiler/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,15 +786,6 @@ export function component_invalid_directive(node) {
e(node, "component_invalid_directive", "This type of directive is not valid on components");
}

/**
* Component name must be a valid variable name or dot notation expression
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function component_invalid_name(node) {
e(node, "component_invalid_name", "Component name must be a valid variable name or dot notation expression");
}

/**
* Cyclical dependency detected: %cycle%
* @param {null | number | NodeLike} node
Expand Down Expand Up @@ -872,15 +863,6 @@ export function element_invalid_closing_tag_autoclosed(node, name, reason) {
e(node, "element_invalid_closing_tag_autoclosed", `\`</${name}>\` attempted to close element that was already automatically closed by \`<${reason}>\` (cannot nest \`<${reason}>\` inside \`<${name}>\`)`);
}

/**
* Expected valid tag name
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function element_invalid_tag_name(node) {
e(node, "element_invalid_tag_name", "Expected valid tag name");
}

/**
* `<%name%>` was left open
* @param {null | number | NodeLike} node
Expand Down Expand Up @@ -1378,6 +1360,15 @@ export function svelte_self_invalid_placement(node) {
e(node, "svelte_self_invalid_placement", "`<svelte:self>` components can only exist inside `{#if}` blocks, `{#each}` blocks, `{#snippet}` blocks or slots passed to components");
}

/**
* Expected a valid element or component name. Components must have a valid variable name or dot notation expression
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function tag_invalid_name(node) {
e(node, "tag_invalid_name", "Expected a valid element or component name. Components must have a valid variable name or dot notation expression");
}

/**
* {@%name% ...} tag cannot be %location%
* @param {null | number | NodeLike} node
Expand Down
18 changes: 7 additions & 11 deletions packages/svelte/src/compiler/phases/1-parse/state/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import { list } from '../../../utils/string.js';
const regex_invalid_unquoted_attribute_value = /^(\/>|[\s"'=<>`])/;
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
const regex_closing_comment = /-->/;
const regex_component_name = /^(?:[A-Z]|[A-Za-z][A-Za-z0-9_$]*\.)/;
const regex_valid_component_name =
/^(?:[A-Z][A-Za-z0-9_$.]*|[a-z][A-Za-z0-9_$]*\.[A-Za-z0-9_$])[A-Za-z0-9_$.]*$/;
const regex_whitespace_or_slash_or_closing_tag = /(\s|\/|>)/;
const regex_token_ending_character = /[\s=/>"']/;
const regex_starts_with_quote_characters = /^["']/;
const regex_attribute_value = /^(?:"([^"]*)"|'([^'])*'|([^>\s]+))/;
const regex_valid_tag_name = /^!?[a-zA-Z]{1,}:?[a-zA-Z0-9-]*/;
const regex_valid_element_name =
/^(?:![a-zA-Z]+|[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|[a-zA-Z][a-zA-Z0-9]*:[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])$/;
const regex_valid_component_name =
/^(?:[A-Z][A-Za-z0-9_$.]*|[a-z][A-Za-z0-9_$]*(?:\.[A-Za-z0-9_$]+)+)$/;

/** @type {Map<string, Compiler.ElementLike['type']>} */
const root_only_meta_tags = new Map([
Expand Down Expand Up @@ -107,9 +107,9 @@ export default function element(parser) {
e.svelte_meta_invalid_tag(bounds, list(Array.from(meta_tags.keys())));
}

if (!regex_valid_tag_name.test(name)) {
if (!regex_valid_element_name.test(name) && !regex_valid_component_name.test(name)) {
const bounds = { start: start + 1, end: start + 1 + name.length };
e.element_invalid_tag_name(bounds);
e.tag_invalid_name(bounds);
}

if (root_only_meta_tags.has(name)) {
Expand All @@ -126,7 +126,7 @@ export default function element(parser) {

const type = meta_tags.has(name)
? meta_tags.get(name)
: regex_component_name.test(name)
: regex_valid_component_name.test(name)
? 'Component'
: name === 'title' && parent_is_head(parser.stack)
? 'TitleElement'
Expand All @@ -135,10 +135,6 @@ export default function element(parser) {
? 'SlotElement'
: 'RegularElement';

if (type === 'Component' && !regex_valid_component_name.test(name)) {
e.component_invalid_name({ start: start + 1, end: start + name.length + 1 });
}

/** @type {Compiler.ElementLike} */
const element =
type === 'RegularElement'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { test } from '../../test';

export default test({
error: {
code: 'component_invalid_name',
message: 'Component name must be a valid variable name or dot notation expression',
code: 'tag_invalid_name',
message:
'Expected a valid element or component name. Components must have a valid variable name or dot notation expression',
position: [1, 14]
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { test } from '../../test';

export default test({
error: {
code: 'tag_invalid_name',
message:
'Expected a valid element or component name. Components must have a valid variable name or dot notation expression',
position: [1, 8]
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<yes[no]></yes[no]>
Loading