Ver código fonte

A discussion about this issue can be found here: https://github.com/alpinejs/alpine/discussions/1520

Description:
Fix an issue with x-for where parsing the item name out of parenthesis would cause an error if spaces where present around the item name and index was not used.

Example:
-> This fails:
    <template x-for="( item ) in items">
-> This succeeds:
    <template x-for="(item) in items">

Changes:
- Fixed an issue with trimming whitespace around the item name in x-for
- Added unit test
jacobp 3 anos atrás
pai
commit
ba51b41ede

+ 2 - 2
packages/alpinejs/src/directives/x-for.js

@@ -196,7 +196,7 @@ function loop(el, iteratorNames, evaluateItems, evaluateKey) {
 // This was taken from VueJS 2.* core. Thanks Vue!
 function parseForExpression(expression) {
     let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
-    let stripParensRE = /^\(|\)$/g
+    let stripParensRE = /^\s*\(|\)\s*$/g
     let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
     let inMatch = expression.match(forAliasRE)
 
@@ -204,7 +204,7 @@ function parseForExpression(expression) {
 
     let res = {}
     res.items = inMatch[2].trim()
-    let item = inMatch[1].trim().replace(stripParensRE, '')
+    let item = inMatch[1].replace(stripParensRE, '').trim()
     let iteratorMatch = item.match(forIteratorRE)
 
     if (iteratorMatch) {

+ 39 - 0
tests/cypress/integration/directives/x-for.spec.js

@@ -19,6 +19,45 @@ test('renders loops with x-for',
     }
 )
 
+test('renders loops with x-for that have space or newline',
+    html`
+        <div x-data="{ items: ['foo'] }">
+            <button x-on:click="items = ['foo', 'bar']">click me</button>
+
+            <div x-bind:id="1">
+                <template x-for="
+                    (
+                        item
+                    ) in items
+                ">
+                    <span x-text="item"></span>
+                </template>
+            </div>
+
+            <div x-bind:id="2">
+                <template x-for=" (
+                        item,
+                        index
+                    ) in items
+                ">
+                    <span x-text="item"></span>
+                </template>
+            </div>
+        </div>
+    `,
+    ({ get }) => {
+        get('#1 span:nth-of-type(1)').should(haveText('foo'))
+        get('#1 span:nth-of-type(2)').should(notBeVisible())
+        get('#2 span:nth-of-type(1)').should(haveText('foo'))
+        get('#2 span:nth-of-type(2)').should(notBeVisible())
+        get('button').click()
+        get('#1 span:nth-of-type(1)').should(haveText('foo'))
+        get('#1 span:nth-of-type(2)').should(haveText('bar'))
+        get('#2 span:nth-of-type(1)').should(haveText('foo'))
+        get('#2 span:nth-of-type(2)').should(haveText('bar'))
+    }
+)
+
 test('can destructure arrays',
     html`
         <div x-data="{ items: [[1, 'foo'], [2, 'bar']] }">