Skip to content

Commit b92b2c7

Browse files
committed
feat: implement transition group transformation
1 parent 6925c32 commit b92b2c7

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { runTest } from '../../src/testUtils'
2+
3+
runTest(
4+
'Add tag attribute for default transition-group',
5+
'transition-group-root',
6+
'transition-group-root',
7+
'vue',
8+
'vue'
9+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<div class="hello">
3+
<transition-group tag="ul">
4+
<li v-for="item in items" :key="item">
5+
{{ item }}
6+
</li>
7+
</transition-group>
8+
<transition-group>
9+
<span v-for="item in items" v-bind:key="item" class="list-item">
10+
{{ item }}
11+
</span>
12+
</transition-group>
13+
</div>
14+
</template>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<div class="hello">
3+
<transition-group tag="ul">
4+
<li v-for="item in items" :key="item">
5+
{{ item }}
6+
</li>
7+
</transition-group>
8+
<transition-group tag="span">
9+
<span v-for="item in items" v-bind:key="item" class="list-item">
10+
{{ item }}
11+
</span>
12+
</transition-group>
13+
</div>
14+
</template>

vue-transformations/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const transformationMap: {
99
} = {
1010
'slot-attribute': require('./slot-attribute'),
1111
'slot-default': require('./slot-default'),
12+
'v-for-template-key': require('./v-for-template-key'),
13+
'v-else-if-key': require('./v-else-if-key'),
14+
'transition-group-root': require('./transition-group-root'),
1215
}
1316

1417
export default transformationMap
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import * as OperationUtils from '../src/operationUtils'
2+
import * as parser from 'vue-eslint-parser'
3+
import type { Node } from 'vue-eslint-parser/ast/nodes'
4+
import type { Operation } from '../src/operationUtils'
5+
import type { VueASTTransformation } from '../src/wrapVueTransformation'
6+
import wrap from '../src/wrapVueTransformation'
7+
8+
/**
9+
* 每一个实际的规则,需要做以下几件事:
10+
* 1、findNodes(fileInfo, ast): 寻找匹配规则的节点
11+
* 2、fix(nodes): 完善匹配节点的增删改逻辑
12+
* 3、applyFix(fileInfo, tempFixes): 执行fixer,对源码进行增删改,并返回转换后的代码
13+
* @param context
14+
*/
15+
16+
export const transformAST: VueASTTransformation = (context) => {
17+
let fixOperations: Operation[] = []
18+
const toFixNodes: Node[] = findNodes(context)
19+
toFixNodes.forEach((node) => {
20+
// fix(node) 返回的为 Operation 数组,因此用 concat 合并多个数组
21+
fixOperations = fixOperations.concat(fix(node))
22+
})
23+
return fixOperations
24+
}
25+
26+
export default wrap(transformAST)
27+
/**
28+
* 定位 slot attribute 节点
29+
*
30+
* @param context { file: FileInfo, api: API }
31+
* @param templateBody
32+
* @returns 所有的 slot attribute 节点
33+
*/
34+
function findNodes(context: any): Node[] {
35+
const { file } = context
36+
const source = file.source
37+
const options = { sourceType: 'module' }
38+
const ast = parser.parse(source, options)
39+
let toFixNodes: Node[] = []
40+
let root: Node = <Node>ast.templateBody // 强制类型转换
41+
parser.AST.traverseNodes(root, {
42+
enterNode(node: Node) {
43+
if (node.type === 'VElement' && node.name === 'transition-group') {
44+
toFixNodes.push(node)
45+
}
46+
},
47+
leaveNode(node: Node) {},
48+
})
49+
return toFixNodes
50+
}
51+
/**
52+
* The repair logic for
53+
* @param node The Target Node
54+
*/
55+
function fix(node: any): Operation[] {
56+
let fixOperations: Operation[] = []
57+
58+
// The current node has no attribute that is v-for
59+
let havaTagAttr: boolean = false
60+
node.startTag.attributes
61+
.filter(
62+
(attr: any) =>
63+
attr.type === 'VAttribute' &&
64+
attr.key.type === 'VIdentifier' &&
65+
attr.key.name === 'tag'
66+
)
67+
.forEach((element: any) => {
68+
havaTagAttr = true
69+
})
70+
if (havaTagAttr) {
71+
return fixOperations
72+
}
73+
74+
fixOperations.push(
75+
OperationUtils.insertTextAt(node.startTag.range[1] - 1, ' tag="span"')
76+
)
77+
return fixOperations
78+
}

0 commit comments

Comments
 (0)