Skip to content

Commit 1bec693

Browse files
committed
feat: implement v-for and v-if precedence changed transformation
1 parent d261cca commit 1bec693

File tree

7 files changed

+129
-1
lines changed

7 files changed

+129
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { runTest } from '../../src/testUtils'
2+
3+
runTest(
4+
'Fix the precedence problem of v-for and v-if before vue 2.6',
5+
'v-for-v-if-precedence-changed',
6+
'v-for-if-with-key',
7+
'vue',
8+
'vue'
9+
)
10+
11+
runTest(
12+
'Fix the precedence problem of v-for and v-if before vue 2.6',
13+
'v-for-v-if-precedence-changed',
14+
'v-for-if-without-key',
15+
'vue',
16+
'vue'
17+
)
18+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<ul>
3+
<li
4+
v-for='user in users'
5+
v-if='user.isActive'
6+
:key='user.id'
7+
>
8+
{{user.name}}
9+
</li>
10+
</ul>
11+
</template>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<template>
2+
<ul>
3+
<template v-for='user in users' :key='user.id'>
4+
<li
5+
6+
v-if='user.isActive'
7+
8+
>
9+
{{user.name}}
10+
</li>
11+
</template>
12+
</ul>
13+
</template>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<template>
2+
<ul>
3+
<li
4+
v-for='user in users'
5+
v-if='user.isActive'
6+
>
7+
{{user.name}}
8+
</li>
9+
</ul>
10+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<template>
2+
<ul>
3+
<template v-for='user in users'>
4+
<li
5+
6+
v-if='user.isActive'
7+
>
8+
{{user.name}}
9+
</li>
10+
</template>
11+
</ul>
12+
</template>

vue-transformations/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ const transformationMap: {
1212
'v-for-template-key': require('./v-for-template-key'),
1313
'v-else-if-key': require('./v-else-if-key'),
1414
'transition-group-root': require('./transition-group-root'),
15-
'v-bind-order-sensitive': require('./v-bind-order-sensitive.spec')
15+
'v-bind-order-sensitive': require('./v-bind-order-sensitive.spec'),
16+
'v-for-v-if-precedence-changed': require('./v-for-v-if-precedence-changed')
1617
}
1718

1819
export default transformationMap
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Node } from 'vue-eslint-parser/ast/nodes'
2+
import * as OperationUtils from '../src/operationUtils'
3+
import type { Operation } from '../src/operationUtils'
4+
import type { VueASTTransformation } from '../src/wrapVueTransformation'
5+
import * as parser from 'vue-eslint-parser'
6+
import wrap from '../src/wrapVueTransformation'
7+
8+
export const transformAST: VueASTTransformation = (context) => {
9+
let fixOperations: Operation[] = []
10+
const { file } = context
11+
const source = file.source
12+
const toFixNodes: Node[] = findNodes(source)
13+
toFixNodes.forEach((node) => {
14+
fixOperations = fixOperations.concat(fix(node, source))
15+
})
16+
return fixOperations
17+
}
18+
19+
export default wrap(transformAST)
20+
21+
function findNodes(source: string): Node[] {
22+
const options = { sourceType: 'module' };
23+
const ast = parser.parse(source, options);
24+
let toFixNodes: Node[] = [];
25+
let root: Node = <Node>ast.templateBody;
26+
parser.AST.traverseNodes(root, {
27+
enterNode(node: Node) {
28+
if (
29+
node.type === 'VAttribute' &&
30+
node.directive &&
31+
node.key.name.name === 'for' &&
32+
node.parent.attributes.length > 1
33+
) {
34+
for (let ifNode of node.parent.attributes) {
35+
// @ts-ignore
36+
if (ifNode?.key?.name?.name === 'if') toFixNodes.push(node);
37+
}
38+
}
39+
},
40+
leaveNode(node: Node) {},
41+
})
42+
return toFixNodes
43+
}
44+
45+
function fix(node: Node, source: string): Operation[] {
46+
let fixOperations: Operation[] = [];
47+
const target: any = node!.parent;
48+
let forValue: string = source.slice(node.range[0], node.range[1]);
49+
let keyNode: any = false;
50+
for (let findKeyNode of target?.attributes) {
51+
// @ts-ignore
52+
if (findKeyNode?.key?.argument?.name === 'key') keyNode = findKeyNode;
53+
}
54+
if (keyNode) {
55+
let keyValue: string = source.slice(keyNode.range[0],keyNode.range[1]);
56+
forValue += ' ' + keyValue;
57+
fixOperations.push (OperationUtils.remove(keyNode));
58+
}
59+
fixOperations.push(OperationUtils.remove(node));
60+
fixOperations.push(OperationUtils.insertTextBefore(target!.parent, `<template ${forValue}>\n`));
61+
fixOperations.push(OperationUtils.insertTextAfter(target!.parent, `\n</template>`))
62+
return fixOperations
63+
}

0 commit comments

Comments
 (0)