Skip to content

Commit 423c73d

Browse files
committed
feat: (wip) implement a util function to get vue options object
1 parent a5f8464 commit 423c73d

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

src/astUtils.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import type {
2+
ASTNode,
3+
ASTPath,
4+
Collection,
5+
Identifier,
6+
ObjectExpression,
7+
} from 'jscodeshift'
8+
import type { Context } from './wrapAstTransformation'
9+
10+
export function getVueOptionsObject(
11+
context: Context
12+
): Collection<ObjectExpression> {
13+
const paths: ASTPath<ObjectExpression>[] = []
14+
const { j, root, filename } = context
15+
16+
function nodesToPaths<T>(
17+
nodes: T extends ASTNode ? T | T[] : never
18+
): ASTPath<T>[] {
19+
return j(nodes).paths()
20+
}
21+
22+
function getConstDeclarationInit(id: Identifier) {
23+
const declarator = root.findVariableDeclarators(id.name)
24+
const declarationKind = declarator.closest(j.VariableDeclaration).nodes()[0]
25+
.kind
26+
27+
if (declarationKind !== 'const') {
28+
return null
29+
}
30+
31+
return declarator.nodes()[0].init
32+
}
33+
34+
function hasRenderOrTemplateProps(obj: ObjectExpression) {
35+
return obj.properties.some((prop) => {
36+
if (j.SpreadElement.check(prop) || j.SpreadProperty.check(prop)) {
37+
return false
38+
}
39+
40+
if (j.StringLiteral.check(prop.key)) {
41+
return prop.key.value === 'render' || prop.key.value === 'template'
42+
}
43+
44+
if (j.Identifier.check(prop.key)) {
45+
return prop.key.name === 'render' || prop.key.name === 'template'
46+
}
47+
})
48+
}
49+
50+
if (filename.endsWith('.vue')) {
51+
// (.vue) export default {}
52+
const defaultObjectExport = root
53+
.find(j.ExportDefaultDeclaration)
54+
.map((path) => {
55+
const decl = path.node.declaration
56+
57+
if (j.ObjectExpression.check(decl)) {
58+
return nodesToPaths(decl)
59+
}
60+
61+
if (j.Identifier.check(decl)) {
62+
const init = getConstDeclarationInit(decl)
63+
if (init && j.ObjectExpression.check(init)) {
64+
return nodesToPaths(init)
65+
}
66+
}
67+
68+
return null
69+
})
70+
71+
paths.push(...defaultObjectExport.paths())
72+
} else {
73+
// (.js) export default {} with `render` or `template` option
74+
const defaultObjectExport = root
75+
.find(j.ExportDefaultDeclaration)
76+
.map((path) => {
77+
const decl = path.node.declaration
78+
79+
if (j.ObjectExpression.check(decl) && hasRenderOrTemplateProps(decl)) {
80+
return nodesToPaths(decl)
81+
}
82+
83+
if (j.Identifier.check(decl)) {
84+
const init = getConstDeclarationInit(decl)
85+
if (
86+
init &&
87+
j.ObjectExpression.check(init) &&
88+
hasRenderOrTemplateProps(init)
89+
) {
90+
return nodesToPaths(init)
91+
}
92+
}
93+
})
94+
95+
paths.push(...defaultObjectExport.paths())
96+
}
97+
98+
// defineComponent({})
99+
// new Vue({})
100+
// Vue.component('name', {})
101+
102+
return j(paths)
103+
}

0 commit comments

Comments
 (0)