-
-
Notifications
You must be signed in to change notification settings - Fork 8k
/
utils.ts
127 lines (109 loc) 路 3.55 KB
/
utils.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import {
CallExpression,
Expression,
Identifier,
ImportDefaultSpecifier,
ImportNamespaceSpecifier,
ImportSpecifier,
Node,
StringLiteral
} from '@babel/types'
import path from 'path'
import { TS_NODE_TYPES } from '@vue/compiler-dom'
import { isString } from '@vue/shared'
export const UNKNOWN_TYPE = 'Unknown'
export function resolveObjectKey(node: Node, computed: boolean) {
switch (node.type) {
case 'StringLiteral':
case 'NumericLiteral':
return String(node.value)
case 'Identifier':
if (!computed) return node.name
}
return undefined
}
export function concatStrings(strs: Array<string | null | undefined | false>) {
return strs.filter((s): s is string => !!s).join(', ')
}
export function isLiteralNode(node: Node) {
return node.type.endsWith('Literal')
}
export function unwrapTSNode(node: Node): Node {
if (TS_NODE_TYPES.includes(node.type)) {
return unwrapTSNode((node as any).expression)
} else {
return node
}
}
export function isCallOf(
node: Node | null | undefined,
test: string | ((id: string) => boolean) | null | undefined
): node is CallExpression {
return !!(
node &&
test &&
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
(isString(test) ? node.callee.name === test : test(node.callee.name))
)
}
export function toRuntimeTypeString(types: string[]) {
return types.length > 1 ? `[${types.join(', ')}]` : types[0]
}
export function getImportedName(
specifier: ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier
) {
if (specifier.type === 'ImportSpecifier')
return specifier.imported.type === 'Identifier'
? specifier.imported.name
: specifier.imported.value
else if (specifier.type === 'ImportNamespaceSpecifier') return '*'
return 'default'
}
export function getId(node: Identifier | StringLiteral): string
export function getId(node: Expression): string | null
export function getId(node: Expression) {
return node.type === 'Identifier'
? node.name
: node.type === 'StringLiteral'
? node.value
: null
}
const identity = (str: string) => str
const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g
const toLowerCase = (str: string) => str.toLowerCase()
function toFileNameLowerCase(x: string) {
return fileNameLowerCaseRegExp.test(x)
? x.replace(fileNameLowerCaseRegExp, toLowerCase)
: x
}
/**
* We need `getCanonicalFileName` when creating ts module resolution cache,
* but TS does not expose it directly. This implementation is repllicated from
* the TS source code.
*/
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean) {
return useCaseSensitiveFileNames ? identity : toFileNameLowerCase
}
// in the browser build, the polyfill doesn't expose posix, but defaults to
// posix behavior.
const normalize = (path.posix || path).normalize
const windowsSlashRE = /\\/g
export function normalizePath(p: string) {
return normalize(p.replace(windowsSlashRE, '/'))
}
export const joinPaths = (path.posix || path).join
/**
* key may contain symbols
* e.g. onUpdate:modelValue -> "onUpdate:modelValue"
*/
export const propNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~\-]/
export function getEscapedPropName(key: string) {
return propNameEscapeSymbolsRE.test(key) ? JSON.stringify(key) : key
}
export const cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
export function getEscapedCssVarName(key: string, doubleEscape: boolean) {
return key.replace(cssVarNameEscapeSymbolsRE, s =>
doubleEscape ? `\\\\${s}` : `\\${s}`
)
}