-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
/
importUsageCheck.ts
94 lines (84 loc) 路 2.82 KB
/
importUsageCheck.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import type { SFCDescriptor } from '../parse'
import {
type ExpressionNode,
NodeTypes,
type SimpleExpressionNode,
type TemplateChildNode,
parserOptions,
walkIdentifiers,
} from '@vue/compiler-dom'
import { createCache } from '../cache'
import { camelize, capitalize, isBuiltInDirective } from '@vue/shared'
/**
* Check if an import is used in the SFC's template. This is used to determine
* the properties that should be included in the object returned from setup()
* when not using inline mode.
*/
export function isImportUsed(local: string, sfc: SFCDescriptor): boolean {
return resolveTemplateUsedIdentifiers(sfc).has(local)
}
const templateUsageCheckCache = createCache<Set<string>>()
function resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {
const { content, ast } = sfc.template!
const cached = templateUsageCheckCache.get(content)
if (cached) {
return cached
}
const ids = new Set<string>()
ast!.children.forEach(walk)
function walk(node: TemplateChildNode) {
switch (node.type) {
case NodeTypes.ELEMENT:
let tag = node.tag
if (tag.includes('.')) tag = tag.split('.')[0].trim()
if (
!parserOptions.isNativeTag!(tag) &&
!parserOptions.isBuiltInComponent!(tag)
) {
ids.add(camelize(tag))
ids.add(capitalize(camelize(tag)))
}
for (let i = 0; i < node.props.length; i++) {
const prop = node.props[i]
if (prop.type === NodeTypes.DIRECTIVE) {
if (!isBuiltInDirective(prop.name)) {
ids.add(`v${capitalize(camelize(prop.name))}`)
}
// process dynamic directive arguments
if (prop.arg && !(prop.arg as SimpleExpressionNode).isStatic) {
extractIdentifiers(ids, prop.arg)
}
if (prop.name === 'for') {
extractIdentifiers(ids, prop.forParseResult!.source)
} else if (prop.exp) {
extractIdentifiers(ids, prop.exp)
} else if (prop.name === 'bind' && !prop.exp) {
// v-bind shorthand name as identifier
ids.add((prop.arg as SimpleExpressionNode).content)
}
}
if (
prop.type === NodeTypes.ATTRIBUTE &&
prop.name === 'ref' &&
prop.value?.content
) {
ids.add(prop.value.content)
}
}
node.children.forEach(walk)
break
case NodeTypes.INTERPOLATION:
extractIdentifiers(ids, node.content)
break
}
}
templateUsageCheckCache.set(content, ids)
return ids
}
function extractIdentifiers(ids: Set<string>, node: ExpressionNode) {
if (node.ast) {
walkIdentifiers(node.ast, n => ids.add(n.name))
} else if (node.ast === null) {
ids.add((node as SimpleExpressionNode).content)
}
}