2023-04-13 20:49:16 +08:00
|
|
|
import type {
|
|
|
|
CallExpression,
|
|
|
|
Expression,
|
|
|
|
Identifier,
|
|
|
|
ImportDefaultSpecifier,
|
|
|
|
ImportNamespaceSpecifier,
|
|
|
|
ImportSpecifier,
|
|
|
|
Node,
|
|
|
|
StringLiteral,
|
|
|
|
} from '@babel/types'
|
2023-04-17 20:59:03 +08:00
|
|
|
import path from 'path'
|
2023-04-11 13:45:45 +08:00
|
|
|
|
|
|
|
export const UNKNOWN_TYPE = 'Unknown'
|
2023-04-11 13:06:04 +08:00
|
|
|
|
|
|
|
export function resolveObjectKey(node: Node, computed: boolean) {
|
|
|
|
switch (node.type) {
|
|
|
|
case 'StringLiteral':
|
|
|
|
case 'NumericLiteral':
|
2023-04-11 15:20:55 +08:00
|
|
|
return String(node.value)
|
2023-04-11 13:06:04 +08:00
|
|
|
case 'Identifier':
|
|
|
|
if (!computed) return node.name
|
|
|
|
}
|
|
|
|
return undefined
|
|
|
|
}
|
2023-04-11 13:45:45 +08:00
|
|
|
|
|
|
|
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 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' &&
|
|
|
|
(typeof test === 'string'
|
|
|
|
? node.callee.name === test
|
|
|
|
: test(node.callee.name))
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export function toRuntimeTypeString(types: string[]) {
|
|
|
|
return types.length > 1 ? `[${types.join(', ')}]` : types[0]
|
|
|
|
}
|
2023-04-13 20:49:16 +08:00
|
|
|
|
|
|
|
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'
|
2023-11-18 10:33:24 +08:00
|
|
|
? node.value
|
|
|
|
: null
|
2023-04-13 20:49:16 +08:00
|
|
|
}
|
2023-04-14 17:27:50 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2023-04-17 20:59:03 +08:00
|
|
|
|
2023-04-24 11:31:13 +08:00
|
|
|
// in the browser build, the polyfill doesn't expose posix, but defaults to
|
|
|
|
// posix behavior.
|
|
|
|
const normalize = (path.posix || path).normalize
|
2023-04-17 20:59:03 +08:00
|
|
|
const windowsSlashRE = /\\/g
|
|
|
|
export function normalizePath(p: string) {
|
2023-04-24 11:31:13 +08:00
|
|
|
return normalize(p.replace(windowsSlashRE, '/'))
|
2023-04-17 20:59:03 +08:00
|
|
|
}
|
2023-04-24 11:31:13 +08:00
|
|
|
|
|
|
|
export const joinPaths = (path.posix || path).join
|
2023-05-12 18:26:25 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* key may contain symbols
|
|
|
|
* e.g. onUpdate:modelValue -> "onUpdate:modelValue"
|
|
|
|
*/
|
2023-11-10 16:23:47 +08:00
|
|
|
export const propNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~\-]/
|
2023-05-12 18:26:25 +08:00
|
|
|
|
2023-11-10 16:23:47 +08:00
|
|
|
export function getEscapedPropName(key: string) {
|
|
|
|
return propNameEscapeSymbolsRE.test(key) ? JSON.stringify(key) : key
|
|
|
|
}
|
|
|
|
|
|
|
|
export const cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g
|
|
|
|
|
2023-11-30 18:35:20 +08:00
|
|
|
export function getEscapedCssVarName(key: string, doubleEscape: boolean) {
|
|
|
|
return key.replace(cssVarNameEscapeSymbolsRE, s =>
|
|
|
|
doubleEscape ? `\\\\${s}` : `\\${s}`,
|
|
|
|
)
|
2023-05-12 18:26:25 +08:00
|
|
|
}
|