diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index 0442a1999a..fe8d124cba 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -225,6 +225,13 @@ const attributes = { 'duplicate-attribute': () => `Attributes need to be unique`, 'invalid-event-attribute-value': () => `Event attribute must be a JavaScript expression, not a string`, + /** @param {'no-each' | 'each-key' | 'child'} type */ + 'invalid-animation': (type) => + type === 'no-each' + ? `An element that uses the animate directive must be the immediate child of a keyed each block` + : type === 'each-key' + ? `An element that uses the animate directive must be used inside a keyed each block. Did you forget to add a key to your each block?` + : `An element that uses the animate directive must be the sole child of a keyed each block`, 'duplicate-animation': () => `An element can only have one 'animate' directive` }; @@ -341,10 +348,6 @@ const errors = { // code: 'invalid-action', // message: 'Actions can only be applied to DOM elements, not components' // }, - // invalid_animation: { - // code: 'invalid-animation', - // message: 'Animations can only be applied to DOM elements, not components' - // }, // invalid_class: { // code: 'invalid-class', // message: 'Classes can only be applied to DOM elements, not components' @@ -446,25 +449,6 @@ const errors = { // code: 'css-invalid-selector', // message: `Invalid selector "${selector}"` // }), - // invalid_animation_immediate: { - // code: 'invalid-animation', - // message: - // 'An element that uses the animate directive must be the immediate child of a keyed each block' - // }, - // invalid_animation_key: { - // code: 'invalid-animation', - // message: - // 'An element that uses the animate directive must be used inside a keyed each block. Did you forget to add a key to your each block?' - // }, - // invalid_animation_sole: { - // code: 'invalid-animation', - // message: - // 'An element that uses the animate directive must be the sole child of a keyed each block' - // }, - // invalid_animation_dynamic_element: { - // code: 'invalid-animation', - // message: ' cannot have a animate directive' - // }, // invalid_directive_value: { // code: 'invalid-directive-value', // message: diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index 603f080a4b..829638fbb7 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -55,6 +55,22 @@ function validate_element(node, context) { validate_slot_attribute(context, attribute); } } else if (attribute.type === 'AnimateDirective') { + const parent = context.path.at(-2); + if (parent?.type !== 'EachBlock') { + error(attribute, 'invalid-animation', 'no-each'); + } else if (!parent.key) { + error(attribute, 'invalid-animation', 'each-key'); + } else if ( + parent.body.nodes.filter( + (n) => + n.type !== 'Comment' && + n.type !== 'ConstTag' && + (n.type !== 'Text' || n.data.trim() !== '') + ).length > 1 + ) { + error(attribute, 'invalid-animation', 'child'); + } + if (has_animate_directive) { error(attribute, 'duplicate-animation'); } else { diff --git a/packages/svelte/tests/validator/samples/animation-not-in-each/_config.js b/packages/svelte/tests/validator/samples/animation-not-in-each/_config.js deleted file mode 100644 index 64fdc120d6..0000000000 --- a/packages/svelte/tests/validator/samples/animation-not-in-each/_config.js +++ /dev/null @@ -1,3 +0,0 @@ -import { test } from '../../test'; - -export default test({ skip: true }); diff --git a/packages/svelte/tests/validator/samples/animation-not-in-keyed-each/_config.js b/packages/svelte/tests/validator/samples/animation-not-in-keyed-each/_config.js deleted file mode 100644 index 64fdc120d6..0000000000 --- a/packages/svelte/tests/validator/samples/animation-not-in-keyed-each/_config.js +++ /dev/null @@ -1,3 +0,0 @@ -import { test } from '../../test'; - -export default test({ skip: true }); diff --git a/packages/svelte/tests/validator/samples/animation-siblings/_config.js b/packages/svelte/tests/validator/samples/animation-siblings/_config.js deleted file mode 100644 index 64fdc120d6..0000000000 --- a/packages/svelte/tests/validator/samples/animation-siblings/_config.js +++ /dev/null @@ -1,3 +0,0 @@ -import { test } from '../../test'; - -export default test({ skip: true });