From b04c5bb398e53cf075f1f91e224ef837850a5a0e Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 16 Jan 2024 13:46:09 +0000 Subject: [PATCH] fix: improve invalid nested interactive element error (#10199) * fix: improve invalid nested interactive element error * add test * revise --- .changeset/giant-moons-own.md | 5 +++++ .../src/compiler/phases/1-parse/utils/html.js | 9 ++++++++- .../src/compiler/phases/2-analyze/validation.js | 14 ++++++++++++++ .../samples/invalid-node-placement/errors.json | 14 ++++++++++++++ .../samples/invalid-node-placement/input.svelte | 7 +++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .changeset/giant-moons-own.md create mode 100644 packages/svelte/tests/validator/samples/invalid-node-placement/errors.json create mode 100644 packages/svelte/tests/validator/samples/invalid-node-placement/input.svelte diff --git a/.changeset/giant-moons-own.md b/.changeset/giant-moons-own.md new file mode 100644 index 0000000000..7568f3868d --- /dev/null +++ b/.changeset/giant-moons-own.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: improve invalid nested interactive element error diff --git a/packages/svelte/src/compiler/phases/1-parse/utils/html.js b/packages/svelte/src/compiler/phases/1-parse/utils/html.js index 309569f4b7..fc74307b3f 100644 --- a/packages/svelte/src/compiler/phases/1-parse/utils/html.js +++ b/packages/svelte/src/compiler/phases/1-parse/utils/html.js @@ -122,7 +122,14 @@ function validate_code(code) { // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission // while `input` is also an interactive element, it is never moved by the browser, so we don't need to check for it -const interactive_elements = new Set(['a', 'button', 'iframe', 'embed', 'select', 'textarea']); +export const interactive_elements = new Set([ + 'a', + 'button', + 'iframe', + 'embed', + 'select', + 'textarea' +]); /** @type {Record>} */ const disallowed_contents = { diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index f64b0268ab..76cfa42717 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -7,6 +7,7 @@ import { } from '../../utils/ast.js'; import { warn } from '../../warnings.js'; import fuzzymatch from '../1-parse/utils/fuzzymatch.js'; +import { interactive_elements } from '../1-parse/utils/html.js'; import { binding_properties } from '../bindings.js'; import { ContentEditableBindings, EventModifiers, SVGElements } from '../constants.js'; import { is_custom_element_node } from '../nodes.js'; @@ -530,6 +531,19 @@ export const validation = { } } + if (interactive_elements.has(node.name)) { + const path = context.path; + for (let parent of path) { + if ( + parent.type === 'RegularElement' && + parent.name === node.name && + interactive_elements.has(parent.name) + ) { + error(node, 'invalid-node-placement', `<${node.name}>`, parent.name); + } + } + } + context.next({ ...context.state, parent_element: node.name diff --git a/packages/svelte/tests/validator/samples/invalid-node-placement/errors.json b/packages/svelte/tests/validator/samples/invalid-node-placement/errors.json new file mode 100644 index 0000000000..259b8f613b --- /dev/null +++ b/packages/svelte/tests/validator/samples/invalid-node-placement/errors.json @@ -0,0 +1,14 @@ +[ + { + "code": "invalid-node-placement", + "message": " is invalid inside ", + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 34 + } + } +] diff --git a/packages/svelte/tests/validator/samples/invalid-node-placement/input.svelte b/packages/svelte/tests/validator/samples/invalid-node-placement/input.svelte new file mode 100644 index 0000000000..a34a019b39 --- /dev/null +++ b/packages/svelte/tests/validator/samples/invalid-node-placement/input.svelte @@ -0,0 +1,7 @@ +
+ +
+

{`hello`}

+
+ +