Repository: sveltejs/svelte (JavaScript)
Date: 2020-09-30 13:27:20+00:00
Task type: Bug Fix

Issue:
Error when using animate flip if there is no space in front of each block
**Describe the bug**
I got an error message `An element that use the animate directive must be the sole child of a keyed each block` when using animate flip if there is no space in front of each block.

**To Reproduce**
https://svelte.dev/repl/1661180017a5479caf0b6451c6279a7a?version=3.25.1

**Additional context**
I use inline blocks on my project, excess spaces must be removed to make the layout accurate.
So I use preprocessor like this ( https://github.com/sveltejs/svelte/issues/189#issuecomment-586142198 ) to remove all excess spaces between tags, but it will then cause the above error.


Issue discussion:
Here's a more minimalistic reproduction. The following does not parse:

```
<div>{#each [] as n (n)} <div animate:flip /> {/each}</div>
```

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Svelte changelog
 
+## Unreleased
+
+* Ignore whitespace in `{#each}` blocks when containing elements with `animate:` ([#5477](https://github.com/sveltejs/svelte/pull/5477))
+
 ## 3.46.2
 
 * Export `FlipParams` interface from `svelte/animate` ([#7103](https://github.com/sveltejs/svelte/issues/7103))
diff --git a/src/compiler/compile/nodes/EachBlock.ts b/src/compiler/compile/nodes/EachBlock.ts
--- a/src/compiler/compile/nodes/EachBlock.ts
+++ b/src/compiler/compile/nodes/EachBlock.ts
@@ -9,6 +9,7 @@ import { Node } from 'estree';
 import Component from '../Component';
 import { TemplateNode } from '../../interfaces';
 import compiler_errors from '../compiler_errors';
+import { INode } from './interfaces';
 import get_const_tags from './shared/get_const_tags';
 
 export default class EachBlock extends AbstractBlock {
@@ -62,6 +63,8 @@ export default class EachBlock extends AbstractBlock {
 		([this.const_tags, this.children] = get_const_tags(info.children, component, this, this));
 
 		if (this.has_animation) {
+			this.children = this.children.filter(child => !isEmptyNode(child));
+
 			if (this.children.length !== 1) {
 				const child = this.children.find(child => !!(child as Element).animation);
 				component.error((child as Element).animation, compiler_errors.invalid_animation_sole);
@@ -76,3 +79,7 @@ export default class EachBlock extends AbstractBlock {
 			: null;
 	}
 }
+
+function isEmptyNode(node: INode) {
+	return node.type === 'Text' && node.data.trim() === '';
+}


Test patch:
diff --git a/test/validator/samples/animation-each-with-const/errors.json b/test/validator/samples/animation-each-with-const/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/animation-each-with-const/errors.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/test/validator/samples/animation-each-with-const/input.svelte b/test/validator/samples/animation-each-with-const/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/animation-each-with-const/input.svelte
@@ -0,0 +1,10 @@
+<script>
+  function flip(){}
+</script>
+
+<div>
+  {#each [] as n (n)}
+    {@const a = n}
+    <div animate:flip={a} />
+  {/each}
+</div>
diff --git a/test/validator/samples/animation-each-with-whitespace/errors.json b/test/validator/samples/animation-each-with-whitespace/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/animation-each-with-whitespace/errors.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/test/validator/samples/animation-each-with-whitespace/input.svelte b/test/validator/samples/animation-each-with-whitespace/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/animation-each-with-whitespace/input.svelte
@@ -0,0 +1,7 @@
+<script>
+	function flip() {}
+</script>
+
+<div>
+	{#each [] as n (n)} <div animate:flip /> {/each}
+</div>