diff --git a/.changeset/pink-mayflies-tie.md b/.changeset/pink-mayflies-tie.md new file mode 100644 index 0000000000..a98dc0e01a --- /dev/null +++ b/.changeset/pink-mayflies-tie.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: make CSS animation declaration transformation more robust diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/Stylesheet.js b/packages/svelte/src/compiler/phases/2-analyze/css/Stylesheet.js index 9d45692ed5..09440172e4 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/Stylesheet.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/Stylesheet.js @@ -8,7 +8,7 @@ import { push_array } from '../utils/push_array.js'; import { create_attribute } from '../../nodes.js'; const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/; - +const regex_name_boundary = /^[\s,;}]$/; /** * @param {string} name * @returns {string} @@ -213,20 +213,29 @@ class Declaration { transform(code, keyframes) { const property = this.node.property && remove_css_prefix(this.node.property.toLowerCase()); if (property === 'animation' || property === 'animation-name') { - const name = /** @type {string} */ (this.node.value) - .split(' ') - .find((name) => keyframes.has(name)); - - if (name) { - const start = code.original.indexOf( - name, - code.original.indexOf(this.node.property, this.node.start) - ); + let index = this.node.start + this.node.property.length + 1; + let name = ''; - const end = start + name.length; + while (index < code.original.length) { + const character = code.original[index]; - const keyframe = /** @type {string} */ (keyframes.get(name)); - code.update(start, end, keyframe); + if (regex_name_boundary.test(character)) { + const keyframe = keyframes.get(name); + + if (keyframe) { + code.update(index - name.length, index, keyframe); + } + + if (character === ';' || character === '}') { + break; + } + + name = ''; + } else { + name += character; + } + + index++; } } } diff --git a/packages/svelte/tests/css/samples/animations/expected.css b/packages/svelte/tests/css/samples/animations/expected.css new file mode 100644 index 0000000000..137a45843c --- /dev/null +++ b/packages/svelte/tests/css/samples/animations/expected.css @@ -0,0 +1,24 @@ + + @keyframes svelte-xyz-a { + 0% { + transform: scale(1); + } + 100% { + transform: scale(2); + } + } + + @keyframes svelte-xyz-animation { + 0% { + transform: scale(1); + } + 100% { + transform: scale(2); + } + } + + h1.svelte-xyz { + animation: 1s linear infinite svelte-xyz-a; + animation: svelte-xyz-a 1s linear infinite; + animation: 1s linear infinite svelte-xyz-a,svelte-xyz-animation 1s linear infinite; + } diff --git a/packages/svelte/tests/css/samples/animations/input.svelte b/packages/svelte/tests/css/samples/animations/input.svelte new file mode 100644 index 0000000000..2da250f9ab --- /dev/null +++ b/packages/svelte/tests/css/samples/animations/input.svelte @@ -0,0 +1,27 @@ +