@vureact/compiler-core 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +286 -0
- package/README.md +76 -74
- package/lib/{chunk-CUCUXW56.esm.js → chunk-IGLKQRRZ.esm.js} +1084 -825
- package/lib/{chunk-7LBUUA24.js → chunk-TSGO73AO.js} +1123 -864
- package/lib/cli.esm.js +59 -47
- package/lib/cli.js +62 -50
- package/lib/compiler-core.d.cts +761 -1006
- package/lib/compiler-core.d.ts +761 -1006
- package/lib/compiler-core.esm.js +2 -2
- package/lib/compiler-core.js +3 -3
- package/package.json +13 -5
- package/README.zh.md +0 -284
- package/templates/route-setup-notes.md +0 -192
- package/templates/route-setup-notes.zh.md +0 -192
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vureact/compiler-core v1.
|
|
2
|
+
* @vureact/compiler-core v1.5.0
|
|
3
3
|
* (c) 2025-present Ruihong Zhong (Ryan John)
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -32,6 +32,16 @@ var PACKAGE_NAME = {
|
|
|
32
32
|
runtime: "@vureact/runtime-core",
|
|
33
33
|
router: "@vureact/router"
|
|
34
34
|
};
|
|
35
|
+
var RUNTIME_PACKAGES = {
|
|
36
|
+
router: {
|
|
37
|
+
name: PACKAGE_NAME.router,
|
|
38
|
+
version: "^2.0.1"
|
|
39
|
+
},
|
|
40
|
+
runtime: {
|
|
41
|
+
name: PACKAGE_NAME.runtime,
|
|
42
|
+
version: "^1.0.1"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
35
45
|
var STYLE_MODULE_NAME = "$style";
|
|
36
46
|
var MACRO_API_NAMES = {
|
|
37
47
|
props: "defineProps",
|
|
@@ -418,8 +428,8 @@ function getBabelParseOptions(lang = "js", context = "script", filename) {
|
|
|
418
428
|
function stringToExpr(input, lang, filename = "") {
|
|
419
429
|
return parseExpression(input, getBabelParseOptions(lang, "expression", filename));
|
|
420
430
|
}
|
|
421
|
-
function atComponentOrHookRoot(
|
|
422
|
-
const { parentPath, scope } =
|
|
431
|
+
function atComponentOrHookRoot(path9, rootScope, inScriptFile = false) {
|
|
432
|
+
const { parentPath, scope } = path9;
|
|
423
433
|
const parentBlock = scope.block;
|
|
424
434
|
if (!parentPath) return !inScriptFile;
|
|
425
435
|
if (parentBlock === rootScope) {
|
|
@@ -1650,9 +1660,9 @@ function resolveScriptMeta(result, ctx) {
|
|
|
1650
1660
|
const scriptAST = result.script?.ast;
|
|
1651
1661
|
if (!scriptAST) return;
|
|
1652
1662
|
traverse(scriptAST, {
|
|
1653
|
-
VariableDeclarator(
|
|
1654
|
-
const { node } =
|
|
1655
|
-
if (!atComponentOrHookRoot(
|
|
1663
|
+
VariableDeclarator(path9) {
|
|
1664
|
+
const { node } = path9;
|
|
1665
|
+
if (!atComponentOrHookRoot(path9, scriptAST.program) || !t16.isIdentifier(node.id)) {
|
|
1656
1666
|
return;
|
|
1657
1667
|
}
|
|
1658
1668
|
if (node.init && t16.isCallExpression(node.init) && t16.isIdentifier(node.init.callee)) {
|
|
@@ -1817,12 +1827,6 @@ function resolveStyles(descriptor, ctx, result) {
|
|
|
1817
1827
|
{ file: filename }
|
|
1818
1828
|
);
|
|
1819
1829
|
}
|
|
1820
|
-
if (content.includes("@import")) {
|
|
1821
|
-
logger.warn(
|
|
1822
|
-
"Detected @import in scoped style. Imported styles remain global. Consider inlining them to preserve scoping.",
|
|
1823
|
-
{ file: filename }
|
|
1824
|
-
);
|
|
1825
|
-
}
|
|
1826
1830
|
const { code, fileExt } = resolveLessSass(content, {
|
|
1827
1831
|
lang,
|
|
1828
1832
|
filename,
|
|
@@ -1949,7 +1953,7 @@ function insertCSSImport(ctx) {
|
|
|
1949
1953
|
scriptIR.imports.push(importDecl);
|
|
1950
1954
|
}
|
|
1951
1955
|
|
|
1952
|
-
// src/core/transform/sfc/script/syntax-processor/postprocess/
|
|
1956
|
+
// src/core/transform/sfc/script/syntax-processor/postprocess/resolve-required-imports/index.ts
|
|
1953
1957
|
import * as t18 from "@babel/types";
|
|
1954
1958
|
|
|
1955
1959
|
// src/core/transform/shared.ts
|
|
@@ -1981,79 +1985,161 @@ function replaceVueSuffix(ctx, node) {
|
|
|
1981
1985
|
node.extra = { rawValue: jsxFile, raw: jsxFile };
|
|
1982
1986
|
}
|
|
1983
1987
|
|
|
1984
|
-
// src/core/transform/sfc/script/syntax-processor/postprocess/
|
|
1985
|
-
|
|
1988
|
+
// src/core/transform/sfc/script/syntax-processor/postprocess/resolve-required-imports/import-strategies.ts
|
|
1989
|
+
var VueRouterStrategy = class {
|
|
1990
|
+
matches(moduleName) {
|
|
1991
|
+
return moduleName === "vue-router" || moduleName.startsWith("vue-router/");
|
|
1992
|
+
}
|
|
1993
|
+
process() {
|
|
1994
|
+
return {
|
|
1995
|
+
shouldReplaceSource: true,
|
|
1996
|
+
newSource: PACKAGE_NAME.router,
|
|
1997
|
+
shouldRemove: false,
|
|
1998
|
+
shouldInjectRuntimeImports: false
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
var VueEcosystemStrategy = class {
|
|
2003
|
+
matches(moduleName) {
|
|
2004
|
+
if (moduleName.startsWith(".") || moduleName.startsWith("/") || moduleName.startsWith("file:")) {
|
|
2005
|
+
return false;
|
|
2006
|
+
}
|
|
2007
|
+
if (moduleName === "vue-router" || moduleName.startsWith("vue-router/")) {
|
|
2008
|
+
return false;
|
|
2009
|
+
}
|
|
2010
|
+
if (moduleName.startsWith("@vue/")) {
|
|
2011
|
+
return true;
|
|
2012
|
+
}
|
|
2013
|
+
for (const pkg of VUE_PACKAGES) {
|
|
2014
|
+
if (moduleName === pkg || moduleName.startsWith(`${pkg}/`)) {
|
|
2015
|
+
return true;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
return false;
|
|
2019
|
+
}
|
|
2020
|
+
process() {
|
|
2021
|
+
return {
|
|
2022
|
+
shouldReplaceSource: false,
|
|
2023
|
+
shouldRemove: true,
|
|
2024
|
+
shouldInjectRuntimeImports: true
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
};
|
|
2028
|
+
var StyleFileStrategy = class {
|
|
2029
|
+
regExp = /\.(less|sass|scss)$/i;
|
|
2030
|
+
matches(moduleName) {
|
|
2031
|
+
return this.regExp.test(moduleName);
|
|
2032
|
+
}
|
|
2033
|
+
process(path9, ctx) {
|
|
2034
|
+
if (!ctx.preprocessStyles) {
|
|
2035
|
+
return {};
|
|
2036
|
+
}
|
|
2037
|
+
const importSource = path9.node.source.value;
|
|
2038
|
+
if (typeof importSource !== "string") {
|
|
2039
|
+
return {};
|
|
2040
|
+
}
|
|
2041
|
+
return {
|
|
2042
|
+
shouldReplaceSource: true,
|
|
2043
|
+
newSource: importSource.replace(this.regExp, ".css"),
|
|
2044
|
+
shouldRemove: false,
|
|
2045
|
+
shouldInjectRuntimeImports: false
|
|
2046
|
+
};
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
|
|
2050
|
+
// src/core/transform/sfc/script/syntax-processor/postprocess/resolve-required-imports/import-strategy-manager.ts
|
|
2051
|
+
var ImportStrategyManager = class {
|
|
2052
|
+
strategies = [];
|
|
2053
|
+
constructor() {
|
|
2054
|
+
this.strategies.push(new VueRouterStrategy());
|
|
2055
|
+
this.strategies.push(new VueEcosystemStrategy());
|
|
2056
|
+
this.strategies.push(new StyleFileStrategy());
|
|
2057
|
+
}
|
|
2058
|
+
/** 添加自定义策略 */
|
|
2059
|
+
addStrategy(strategy) {
|
|
2060
|
+
this.strategies.push(strategy);
|
|
2061
|
+
}
|
|
2062
|
+
/** 查找匹配的策略 */
|
|
2063
|
+
findStrategy(moduleName) {
|
|
2064
|
+
for (const strategy of this.strategies) {
|
|
2065
|
+
if (strategy.matches(moduleName)) {
|
|
2066
|
+
return strategy;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
return null;
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
|
|
2073
|
+
// src/core/transform/sfc/script/syntax-processor/postprocess/resolve-required-imports/index.ts
|
|
2074
|
+
function resolveRequiredImports(ctx) {
|
|
1986
2075
|
const processedModules = /* @__PURE__ */ new Set();
|
|
1987
2076
|
let hasProcessedImports = false;
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2077
|
+
const strategyManager = new ImportStrategyManager();
|
|
2078
|
+
if (ctx.inputType === "sfc") {
|
|
2079
|
+
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.memo);
|
|
2080
|
+
}
|
|
2081
|
+
function resolveRequiredImport(path9) {
|
|
2082
|
+
const { node } = path9;
|
|
2083
|
+
const originalModuleName = node.source.value.toLowerCase();
|
|
2084
|
+
const strategy = strategyManager.findStrategy(originalModuleName);
|
|
2085
|
+
if (strategy) {
|
|
2086
|
+
const result = strategy.process(path9, ctx, originalModuleName);
|
|
2087
|
+
if (result.shouldReplaceSource && result.newSource) {
|
|
2088
|
+
node.source.value = result.newSource;
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
const normalizedModuleName = node.source.value.toLowerCase();
|
|
2092
|
+
mergeImports(node, ctx, normalizedModuleName);
|
|
2093
|
+
if (processedModules.has(normalizedModuleName) && !path9.removed) {
|
|
2094
|
+
path9.remove();
|
|
1996
2095
|
return;
|
|
1997
2096
|
}
|
|
1998
|
-
processedModules.add(
|
|
2097
|
+
processedModules.add(normalizedModuleName);
|
|
1999
2098
|
if (!hasProcessedImports) {
|
|
2000
2099
|
const required = createRequiredImports(ctx);
|
|
2001
|
-
if (
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2100
|
+
if (strategy) {
|
|
2101
|
+
const result = strategy.process(path9, ctx, originalModuleName);
|
|
2102
|
+
if (result.shouldRemove) {
|
|
2103
|
+
path9.replaceWithMultiple(required);
|
|
2104
|
+
} else if (normalizedModuleName === PACKAGE_NAME.react) {
|
|
2105
|
+
path9.insertAfter(required);
|
|
2106
|
+
} else {
|
|
2107
|
+
path9.insertBefore(required);
|
|
2108
|
+
}
|
|
2005
2109
|
} else {
|
|
2006
|
-
|
|
2110
|
+
if (normalizedModuleName === PACKAGE_NAME.react) {
|
|
2111
|
+
path9.insertAfter(required);
|
|
2112
|
+
} else {
|
|
2113
|
+
path9.insertBefore(required);
|
|
2114
|
+
}
|
|
2007
2115
|
}
|
|
2008
2116
|
hasProcessedImports = true;
|
|
2009
2117
|
}
|
|
2010
|
-
if (
|
|
2011
|
-
|
|
2012
|
-
|
|
2118
|
+
if (strategy) {
|
|
2119
|
+
const result = strategy.process(path9, ctx, originalModuleName);
|
|
2120
|
+
if (result.shouldRemove && !path9.removed) {
|
|
2121
|
+
path9.remove();
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2013
2124
|
}
|
|
2014
2125
|
replaceVueSuffix(ctx, node.source);
|
|
2015
2126
|
}
|
|
2016
|
-
function resolveStyleFileExt(path8) {
|
|
2017
|
-
if (!ctx.preprocessStyles) return;
|
|
2018
|
-
const { node } = path8;
|
|
2019
|
-
if (!node || !node.source || !node.source.value) return;
|
|
2020
|
-
const importSource = node.source.value;
|
|
2021
|
-
if (typeof importSource !== "string") return;
|
|
2022
|
-
const styleExtRegex = /\.(less|sass|scss)$/i;
|
|
2023
|
-
if (!styleExtRegex.test(importSource)) return;
|
|
2024
|
-
const newSource = importSource.replace(styleExtRegex, ".css");
|
|
2025
|
-
node.source.value = newSource;
|
|
2026
|
-
}
|
|
2027
2127
|
return {
|
|
2028
|
-
//
|
|
2128
|
+
// 兜底:无 ImportDeclaration 的文件也要能注入必需依赖。
|
|
2029
2129
|
Program: {
|
|
2030
|
-
exit(
|
|
2130
|
+
exit(path9) {
|
|
2031
2131
|
if (hasProcessedImports) return;
|
|
2032
2132
|
const required = createRequiredImports(ctx);
|
|
2033
|
-
|
|
2133
|
+
path9.unshiftContainer("body", required);
|
|
2034
2134
|
hasProcessedImports = true;
|
|
2035
2135
|
}
|
|
2036
2136
|
},
|
|
2037
|
-
ImportDeclaration(
|
|
2038
|
-
resolveRequiredImport(
|
|
2039
|
-
resolveStyleFileExt(path8);
|
|
2137
|
+
ImportDeclaration(path9) {
|
|
2138
|
+
resolveRequiredImport(path9);
|
|
2040
2139
|
}
|
|
2041
2140
|
};
|
|
2042
2141
|
}
|
|
2043
|
-
function
|
|
2044
|
-
if (moduleName.startsWith(".") || moduleName.startsWith("/") || moduleName.startsWith("file:")) {
|
|
2045
|
-
return false;
|
|
2046
|
-
}
|
|
2047
|
-
if (moduleName.startsWith("@vue/")) {
|
|
2048
|
-
return true;
|
|
2049
|
-
}
|
|
2050
|
-
if (moduleName === "vue-router" || moduleName.startsWith("vue-router/")) {
|
|
2051
|
-
return true;
|
|
2052
|
-
}
|
|
2053
|
-
return VUE_PACKAGES.some((name) => moduleName === name || moduleName.startsWith(`${name}/`));
|
|
2054
|
-
}
|
|
2055
|
-
function mergeImports(currentNode, ctx) {
|
|
2056
|
-
const moduleName = currentNode.source.value.toLowerCase();
|
|
2142
|
+
function mergeImports(currentNode, ctx, moduleName) {
|
|
2057
2143
|
const ctxImportItems = ctx.imports.get(moduleName);
|
|
2058
2144
|
if (!ctxImportItems?.length) {
|
|
2059
2145
|
return;
|
|
@@ -2068,7 +2154,9 @@ function mergeImports(currentNode, ctx) {
|
|
|
2068
2154
|
}
|
|
2069
2155
|
}
|
|
2070
2156
|
for (const item of ctxImportItems) {
|
|
2071
|
-
if (currentImports.has(item.name))
|
|
2157
|
+
if (currentImports.has(item.name)) {
|
|
2158
|
+
continue;
|
|
2159
|
+
}
|
|
2072
2160
|
const local = t18.identifier(item.name);
|
|
2073
2161
|
const newNode = !item.onDemand ? t18.importDefaultSpecifier(local) : t18.importSpecifier(local, local);
|
|
2074
2162
|
currentNode.specifiers.push(newNode);
|
|
@@ -2107,10 +2195,10 @@ import * as t20 from "@babel/types";
|
|
|
2107
2195
|
|
|
2108
2196
|
// src/core/transform/sfc/script/shared/babel-utils.ts
|
|
2109
2197
|
import * as t19 from "@babel/types";
|
|
2110
|
-
function findRootVariablePath(
|
|
2111
|
-
const rootId = findRootIdentifier(
|
|
2198
|
+
function findRootVariablePath(path9) {
|
|
2199
|
+
const rootId = findRootIdentifier(path9.node);
|
|
2112
2200
|
if (!rootId?.name) return null;
|
|
2113
|
-
const binding =
|
|
2201
|
+
const binding = path9.scope.getBinding(rootId.name);
|
|
2114
2202
|
if (!binding) return null;
|
|
2115
2203
|
const rootPath = getVariableDeclaratorPath(binding.path);
|
|
2116
2204
|
return rootPath;
|
|
@@ -2122,14 +2210,14 @@ function findRootIdentifier(node) {
|
|
|
2122
2210
|
}
|
|
2123
2211
|
return t19.isIdentifier(current) ? current : null;
|
|
2124
2212
|
}
|
|
2125
|
-
function getVariableDeclaratorPath(
|
|
2126
|
-
if (
|
|
2127
|
-
return
|
|
2213
|
+
function getVariableDeclaratorPath(path9) {
|
|
2214
|
+
if (path9.isVariableDeclarator()) {
|
|
2215
|
+
return path9;
|
|
2128
2216
|
}
|
|
2129
|
-
return
|
|
2217
|
+
return path9.findParent((p) => p.isVariableDeclarator());
|
|
2130
2218
|
}
|
|
2131
|
-
function isVariableDeclTopLevel(
|
|
2132
|
-
const variableDeclaratorPath =
|
|
2219
|
+
function isVariableDeclTopLevel(path9) {
|
|
2220
|
+
const variableDeclaratorPath = path9;
|
|
2133
2221
|
const variableDeclarationPath = variableDeclaratorPath.parentPath;
|
|
2134
2222
|
if (!variableDeclarationPath) {
|
|
2135
2223
|
return false;
|
|
@@ -2143,61 +2231,61 @@ function isVariableDeclTopLevel(path8) {
|
|
|
2143
2231
|
}
|
|
2144
2232
|
return false;
|
|
2145
2233
|
}
|
|
2146
|
-
function isRealVariableAccess(
|
|
2147
|
-
return isIdentifierAccess(
|
|
2234
|
+
function isRealVariableAccess(path9) {
|
|
2235
|
+
return isIdentifierAccess(path9) && !isPropertyName(path9);
|
|
2148
2236
|
}
|
|
2149
|
-
function isIdentifierAccess(
|
|
2150
|
-
if (isIdentifierDeclaration(
|
|
2237
|
+
function isIdentifierAccess(path9) {
|
|
2238
|
+
if (isIdentifierDeclaration(path9)) {
|
|
2151
2239
|
return false;
|
|
2152
2240
|
}
|
|
2153
|
-
const binding =
|
|
2241
|
+
const binding = path9.scope.getBinding(path9.node.name);
|
|
2154
2242
|
if (!binding) {
|
|
2155
2243
|
return true;
|
|
2156
2244
|
}
|
|
2157
|
-
return binding.identifier !==
|
|
2245
|
+
return binding.identifier !== path9.node;
|
|
2158
2246
|
}
|
|
2159
|
-
function isIdentifierDeclaration(
|
|
2160
|
-
const parent =
|
|
2247
|
+
function isIdentifierDeclaration(path9) {
|
|
2248
|
+
const parent = path9.parentPath;
|
|
2161
2249
|
if (!parent) return false;
|
|
2162
|
-
if (parent.isVariableDeclarator() && parent.node.id ===
|
|
2250
|
+
if (parent.isVariableDeclarator() && parent.node.id === path9.node) {
|
|
2163
2251
|
return true;
|
|
2164
2252
|
}
|
|
2165
|
-
if (parent.isFunctionDeclaration() && parent.node.id ===
|
|
2253
|
+
if (parent.isFunctionDeclaration() && parent.node.id === path9.node) {
|
|
2166
2254
|
return true;
|
|
2167
2255
|
}
|
|
2168
|
-
if (parent.isFunctionExpression() && parent.node.id ===
|
|
2256
|
+
if (parent.isFunctionExpression() && parent.node.id === path9.node) {
|
|
2169
2257
|
return true;
|
|
2170
2258
|
}
|
|
2171
|
-
if (parent.isClassDeclaration() && parent.node.id ===
|
|
2259
|
+
if (parent.isClassDeclaration() && parent.node.id === path9.node) {
|
|
2172
2260
|
return true;
|
|
2173
2261
|
}
|
|
2174
|
-
if (parent.isImportSpecifier() && parent.node.local ===
|
|
2262
|
+
if (parent.isImportSpecifier() && parent.node.local === path9.node) {
|
|
2175
2263
|
return true;
|
|
2176
2264
|
}
|
|
2177
|
-
if (parent.isImportDefaultSpecifier() && parent.node.local ===
|
|
2265
|
+
if (parent.isImportDefaultSpecifier() && parent.node.local === path9.node) {
|
|
2178
2266
|
return true;
|
|
2179
2267
|
}
|
|
2180
|
-
if (parent.isImportNamespaceSpecifier() && parent.node.local ===
|
|
2268
|
+
if (parent.isImportNamespaceSpecifier() && parent.node.local === path9.node) {
|
|
2181
2269
|
return true;
|
|
2182
2270
|
}
|
|
2183
|
-
if (parent.isFunction() && parent.node.params.includes(
|
|
2271
|
+
if (parent.isFunction() && parent.node.params.includes(path9.node)) {
|
|
2184
2272
|
return true;
|
|
2185
2273
|
}
|
|
2186
|
-
if (parent.isCatchClause() && parent.node.param ===
|
|
2274
|
+
if (parent.isCatchClause() && parent.node.param === path9.node) {
|
|
2187
2275
|
return true;
|
|
2188
2276
|
}
|
|
2189
2277
|
return false;
|
|
2190
2278
|
}
|
|
2191
|
-
function isPropertyName(
|
|
2192
|
-
const parent =
|
|
2279
|
+
function isPropertyName(path9) {
|
|
2280
|
+
const parent = path9.parentPath;
|
|
2193
2281
|
if (!parent) return false;
|
|
2194
|
-
if (parent.isObjectProperty() && parent.node.key ===
|
|
2282
|
+
if (parent.isObjectProperty() && parent.node.key === path9.node) {
|
|
2195
2283
|
return true;
|
|
2196
2284
|
}
|
|
2197
|
-
if (parent.isClassProperty() && parent.node.key ===
|
|
2285
|
+
if (parent.isClassProperty() && parent.node.key === path9.node) {
|
|
2198
2286
|
return true;
|
|
2199
2287
|
}
|
|
2200
|
-
if (parent.isMemberExpression() && parent.node.property ===
|
|
2288
|
+
if (parent.isMemberExpression() && parent.node.property === path9.node) {
|
|
2201
2289
|
return true;
|
|
2202
2290
|
}
|
|
2203
2291
|
return false;
|
|
@@ -2308,26 +2396,26 @@ function resolveStaticHoisting(ctx) {
|
|
|
2308
2396
|
return {};
|
|
2309
2397
|
}
|
|
2310
2398
|
return {
|
|
2311
|
-
"ImportDeclaration|ExportDeclaration"(
|
|
2312
|
-
if (t20.isImportDeclaration(
|
|
2313
|
-
scriptIR.imports.push(
|
|
2314
|
-
} else if (t20.isExportDeclaration(
|
|
2315
|
-
scriptIR.exports.push(
|
|
2399
|
+
"ImportDeclaration|ExportDeclaration"(path9) {
|
|
2400
|
+
if (t20.isImportDeclaration(path9.node)) {
|
|
2401
|
+
scriptIR.imports.push(path9.node);
|
|
2402
|
+
} else if (t20.isExportDeclaration(path9.node)) {
|
|
2403
|
+
scriptIR.exports.push(path9.node);
|
|
2316
2404
|
}
|
|
2317
|
-
|
|
2405
|
+
path9.remove();
|
|
2318
2406
|
},
|
|
2319
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration|TSEnumDeclaration|TSModuleDeclaration|TSModuleDeclaration"(
|
|
2320
|
-
if (t20.isProgram(
|
|
2321
|
-
scriptIR.tsTypes.push(
|
|
2322
|
-
|
|
2407
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration|TSEnumDeclaration|TSModuleDeclaration|TSModuleDeclaration"(path9) {
|
|
2408
|
+
if (t20.isProgram(path9.parent)) {
|
|
2409
|
+
scriptIR.tsTypes.push(path9.node);
|
|
2410
|
+
path9.remove();
|
|
2323
2411
|
}
|
|
2324
2412
|
},
|
|
2325
|
-
VariableDeclarator(
|
|
2326
|
-
const { node } =
|
|
2327
|
-
if (!isVariableDeclTopLevel(
|
|
2413
|
+
VariableDeclarator(path9) {
|
|
2414
|
+
const { node } = path9;
|
|
2415
|
+
if (!isVariableDeclTopLevel(path9) || !isSimpleLiteral(node.init) || getScriptNodeMeta(node)) {
|
|
2328
2416
|
return;
|
|
2329
2417
|
}
|
|
2330
|
-
const declarationPath =
|
|
2418
|
+
const declarationPath = path9.findParent((p) => p.isVariableDeclaration());
|
|
2331
2419
|
if (!declarationPath) return;
|
|
2332
2420
|
scriptIR.statement.global.push(declarationPath.node);
|
|
2333
2421
|
declarationPath.remove();
|
|
@@ -2344,14 +2432,14 @@ function collectLocalStatements(ctx, ast) {
|
|
|
2344
2432
|
import * as t21 from "@babel/types";
|
|
2345
2433
|
function resolveDefineAsyncComponent(ctx) {
|
|
2346
2434
|
return {
|
|
2347
|
-
CallExpression(
|
|
2348
|
-
const { node } =
|
|
2435
|
+
CallExpression(path9) {
|
|
2436
|
+
const { node } = path9;
|
|
2349
2437
|
if (!isCalleeNamed(node, VUE_API_MAP.defineAsyncComponent)) {
|
|
2350
2438
|
return;
|
|
2351
2439
|
}
|
|
2352
2440
|
const [arg] = node.arguments;
|
|
2353
2441
|
checkIsUnsupported(ctx, arg);
|
|
2354
|
-
pushToGlobalScope(
|
|
2442
|
+
pushToGlobalScope(path9, ctx);
|
|
2355
2443
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.lazy);
|
|
2356
2444
|
}
|
|
2357
2445
|
};
|
|
@@ -2414,15 +2502,15 @@ function warnMultipleOptionsUsed(ctx, node) {
|
|
|
2414
2502
|
}
|
|
2415
2503
|
);
|
|
2416
2504
|
}
|
|
2417
|
-
function pushToGlobalScope(
|
|
2418
|
-
const { node } =
|
|
2505
|
+
function pushToGlobalScope(path9, ctx) {
|
|
2506
|
+
const { node } = path9;
|
|
2419
2507
|
const callee = node.callee;
|
|
2420
2508
|
callee.name = REACT_API_MAP.lazy;
|
|
2421
2509
|
callee.loc.identifierName = REACT_API_MAP.lazy;
|
|
2422
2510
|
if (node.typeParameters) {
|
|
2423
2511
|
node.typeParameters = void 0;
|
|
2424
2512
|
}
|
|
2425
|
-
let declarationPath =
|
|
2513
|
+
let declarationPath = path9.parentPath;
|
|
2426
2514
|
while (declarationPath) {
|
|
2427
2515
|
if (declarationPath.isVariableDeclaration()) {
|
|
2428
2516
|
break;
|
|
@@ -2433,12 +2521,12 @@ function pushToGlobalScope(path8, ctx) {
|
|
|
2433
2521
|
if (declarationPath?.isVariableDeclaration()) {
|
|
2434
2522
|
fullNode = declarationPath.node;
|
|
2435
2523
|
declarationPath.remove();
|
|
2436
|
-
} else if (
|
|
2437
|
-
fullNode =
|
|
2438
|
-
|
|
2524
|
+
} else if (path9.parentPath.isVariableDeclarator()) {
|
|
2525
|
+
fullNode = path9.parent;
|
|
2526
|
+
path9.parentPath.remove();
|
|
2439
2527
|
} else {
|
|
2440
|
-
fullNode =
|
|
2441
|
-
|
|
2528
|
+
fullNode = path9.node;
|
|
2529
|
+
path9.remove();
|
|
2442
2530
|
}
|
|
2443
2531
|
const scriptIR = getScriptIR(ctx);
|
|
2444
2532
|
scriptIR.statement.global.push(fullNode);
|
|
@@ -2469,15 +2557,15 @@ function createUseImperativeHandle(refId, init) {
|
|
|
2469
2557
|
function resolveDefineExpose(ctx) {
|
|
2470
2558
|
if (ctx.inputType !== "sfc") return {};
|
|
2471
2559
|
return {
|
|
2472
|
-
CallExpression(
|
|
2473
|
-
const { node } =
|
|
2560
|
+
CallExpression(path9) {
|
|
2561
|
+
const { node } = path9;
|
|
2474
2562
|
const { filename, scriptData } = ctx;
|
|
2475
2563
|
if (!isCalleeNamed(node, MACRO_API_NAMES.expose)) {
|
|
2476
2564
|
return;
|
|
2477
2565
|
}
|
|
2478
2566
|
const [expose] = node.arguments;
|
|
2479
2567
|
if (!expose) {
|
|
2480
|
-
|
|
2568
|
+
path9.remove();
|
|
2481
2569
|
return;
|
|
2482
2570
|
}
|
|
2483
2571
|
const adapter = ADAPTER_RULES.react[MACRO_API_NAMES.expose];
|
|
@@ -2494,7 +2582,7 @@ function resolveDefineExpose(ctx) {
|
|
|
2494
2582
|
const { forwardRef } = scriptData;
|
|
2495
2583
|
const newNode = createUseImperativeHandle(t23.identifier(forwardRef.refField), init);
|
|
2496
2584
|
forwardRef.enabled = true;
|
|
2497
|
-
|
|
2585
|
+
path9.replaceWith(newNode);
|
|
2498
2586
|
}
|
|
2499
2587
|
};
|
|
2500
2588
|
}
|
|
@@ -2503,8 +2591,8 @@ function resolveDefineExpose(ctx) {
|
|
|
2503
2591
|
import * as t24 from "@babel/types";
|
|
2504
2592
|
function resolveDefineOptions(ctx) {
|
|
2505
2593
|
return {
|
|
2506
|
-
CallExpression(
|
|
2507
|
-
const { node } =
|
|
2594
|
+
CallExpression(path9) {
|
|
2595
|
+
const { node } = path9;
|
|
2508
2596
|
if (!isCalleeNamed(node, MACRO_API_NAMES.options)) {
|
|
2509
2597
|
return;
|
|
2510
2598
|
}
|
|
@@ -2516,7 +2604,7 @@ function resolveDefineOptions(ctx) {
|
|
|
2516
2604
|
file: filename,
|
|
2517
2605
|
loc: node?.loc
|
|
2518
2606
|
});
|
|
2519
|
-
|
|
2607
|
+
path9.remove();
|
|
2520
2608
|
return;
|
|
2521
2609
|
}
|
|
2522
2610
|
if (!t24.isObjectExpression(options)) {
|
|
@@ -2533,7 +2621,7 @@ function resolveDefineOptions(ctx) {
|
|
|
2533
2621
|
extractName(prop, ctx);
|
|
2534
2622
|
}
|
|
2535
2623
|
}
|
|
2536
|
-
|
|
2624
|
+
path9.remove();
|
|
2537
2625
|
}
|
|
2538
2626
|
};
|
|
2539
2627
|
}
|
|
@@ -2565,8 +2653,8 @@ function resolveEmitCalls(ctx) {
|
|
|
2565
2653
|
return `on${capitalize(camelCase(normalized))}`;
|
|
2566
2654
|
};
|
|
2567
2655
|
return {
|
|
2568
|
-
CallExpression(
|
|
2569
|
-
const { node } =
|
|
2656
|
+
CallExpression(path9) {
|
|
2657
|
+
const { node } = path9;
|
|
2570
2658
|
const { filename, templateData, scriptData } = ctx;
|
|
2571
2659
|
if (!t25.isIdentifier(node.callee)) return;
|
|
2572
2660
|
const { name } = node.callee;
|
|
@@ -2577,7 +2665,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2577
2665
|
result = meta.source === MACRO_API_NAMES.emits;
|
|
2578
2666
|
}
|
|
2579
2667
|
if (!result) {
|
|
2580
|
-
const binding =
|
|
2668
|
+
const binding = path9.scope.getBinding(name);
|
|
2581
2669
|
if (binding) {
|
|
2582
2670
|
const parent = binding.path.node;
|
|
2583
2671
|
if (t25.isVariableDeclarator(parent) && t25.isCallExpression(parent.init) && t25.isIdentifier(parent.init.callee)) {
|
|
@@ -2596,7 +2684,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2596
2684
|
source: scriptData.source,
|
|
2597
2685
|
loc: callee?.loc
|
|
2598
2686
|
});
|
|
2599
|
-
|
|
2687
|
+
path9.remove();
|
|
2600
2688
|
return;
|
|
2601
2689
|
}
|
|
2602
2690
|
const propCall = t25.optionalCallExpression(
|
|
@@ -2609,7 +2697,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2609
2697
|
args,
|
|
2610
2698
|
true
|
|
2611
2699
|
);
|
|
2612
|
-
|
|
2700
|
+
path9.replaceWith(propCall);
|
|
2613
2701
|
}
|
|
2614
2702
|
};
|
|
2615
2703
|
}
|
|
@@ -2647,9 +2735,9 @@ function cloneCallableParams(params) {
|
|
|
2647
2735
|
// src/core/transform/sfc/script/syntax-processor/preprocess/resolve-props-interface/resolve-emits.ts
|
|
2648
2736
|
function resolveEmitsTopLevelTypes(ctx) {
|
|
2649
2737
|
return {
|
|
2650
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(
|
|
2651
|
-
if (!t27.isProgram(
|
|
2652
|
-
const { node } =
|
|
2738
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(path9) {
|
|
2739
|
+
if (!t27.isProgram(path9.parent)) return;
|
|
2740
|
+
const { node } = path9;
|
|
2653
2741
|
if (t27.isTSInterfaceDeclaration(node)) {
|
|
2654
2742
|
const typeLiteral = t27.tsTypeLiteral(node.body.body);
|
|
2655
2743
|
if (!hasEmitsSignatureInType(typeLiteral)) return;
|
|
@@ -2714,8 +2802,8 @@ function resolveTopLevelEmitType(tsType) {
|
|
|
2714
2802
|
}
|
|
2715
2803
|
return tsType;
|
|
2716
2804
|
}
|
|
2717
|
-
function resolveDefineEmitsIface(
|
|
2718
|
-
const { node } =
|
|
2805
|
+
function resolveDefineEmitsIface(path9, ctx) {
|
|
2806
|
+
const { node } = path9;
|
|
2719
2807
|
const [runtimeArg] = node.arguments;
|
|
2720
2808
|
const tsParams = node.typeParameters?.params;
|
|
2721
2809
|
if (tsParams?.length) {
|
|
@@ -3015,8 +3103,8 @@ function resolveTupleElementParam(element, index) {
|
|
|
3015
3103
|
|
|
3016
3104
|
// src/core/transform/sfc/script/syntax-processor/preprocess/resolve-props-interface/resolve-props.ts
|
|
3017
3105
|
import * as t28 from "@babel/types";
|
|
3018
|
-
function resolveDefinePropsIface(
|
|
3019
|
-
const { node } =
|
|
3106
|
+
function resolveDefinePropsIface(path9, ctx) {
|
|
3107
|
+
const { node } = path9;
|
|
3020
3108
|
const [runtimeArg] = node.arguments;
|
|
3021
3109
|
const tsParams = node.typeParameters?.params;
|
|
3022
3110
|
if (tsParams?.length) {
|
|
@@ -3161,10 +3249,13 @@ var SLOT_DEFAULT_NAME = "default";
|
|
|
3161
3249
|
var SLOT_CHILDREN_NAME = "children";
|
|
3162
3250
|
var SLOT_FN_PARAM_NAME = "props";
|
|
3163
3251
|
function resolveSlotsTopLevelTypes(ctx) {
|
|
3252
|
+
if (ctx.inputType !== "sfc") {
|
|
3253
|
+
return {};
|
|
3254
|
+
}
|
|
3164
3255
|
return {
|
|
3165
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(
|
|
3166
|
-
if (!t29.isProgram(
|
|
3167
|
-
const { node } =
|
|
3256
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(path9) {
|
|
3257
|
+
if (!t29.isProgram(path9.parent)) return;
|
|
3258
|
+
const { node } = path9;
|
|
3168
3259
|
if (t29.isTSInterfaceDeclaration(node)) {
|
|
3169
3260
|
const typeLiteral = t29.tsTypeLiteral(node.body.body);
|
|
3170
3261
|
if (!hasSlotsSignatureInType(typeLiteral)) return;
|
|
@@ -3186,8 +3277,8 @@ function resolveSlotsTopLevelTypes(ctx) {
|
|
|
3186
3277
|
}
|
|
3187
3278
|
};
|
|
3188
3279
|
}
|
|
3189
|
-
function resolveDefineSlotsIface(
|
|
3190
|
-
const { node } =
|
|
3280
|
+
function resolveDefineSlotsIface(path9, ctx) {
|
|
3281
|
+
const { node } = path9;
|
|
3191
3282
|
const tsParams = node.typeParameters?.params;
|
|
3192
3283
|
if (!tsParams?.length) return;
|
|
3193
3284
|
const {
|
|
@@ -3378,8 +3469,8 @@ function resolvePropName2(key) {
|
|
|
3378
3469
|
function resolvePropsIface(ctx) {
|
|
3379
3470
|
const isTS = ctx.scriptData.lang.startsWith("ts");
|
|
3380
3471
|
return {
|
|
3381
|
-
CallExpression(
|
|
3382
|
-
const { node, parentPath } =
|
|
3472
|
+
CallExpression(path9) {
|
|
3473
|
+
const { node, parentPath } = path9;
|
|
3383
3474
|
const name = node.callee.name;
|
|
3384
3475
|
if (!isCalleeNamed(node, MACRO_API_NAMES.props) && !isCalleeNamed(node, MACRO_API_NAMES.emits) && !isCalleeNamed(node, MACRO_API_NAMES.slots)) {
|
|
3385
3476
|
return;
|
|
@@ -3388,7 +3479,7 @@ function resolvePropsIface(ctx) {
|
|
|
3388
3479
|
if (parentPath.isVariableDeclaration() || parentPath.isVariableDeclarator()) {
|
|
3389
3480
|
parentPath.remove();
|
|
3390
3481
|
} else {
|
|
3391
|
-
|
|
3482
|
+
path9.remove();
|
|
3392
3483
|
}
|
|
3393
3484
|
};
|
|
3394
3485
|
if (ctx.inputType !== "sfc") {
|
|
@@ -3402,11 +3493,11 @@ function resolvePropsIface(ctx) {
|
|
|
3402
3493
|
propsTSIface.hasPropsInJsEnv = true;
|
|
3403
3494
|
} else {
|
|
3404
3495
|
if (name === MACRO_API_NAMES.props) {
|
|
3405
|
-
resolveDefinePropsIface(
|
|
3496
|
+
resolveDefinePropsIface(path9, ctx);
|
|
3406
3497
|
} else if (name === MACRO_API_NAMES.emits) {
|
|
3407
|
-
resolveDefineEmitsIface(
|
|
3498
|
+
resolveDefineEmitsIface(path9, ctx);
|
|
3408
3499
|
} else if (name === MACRO_API_NAMES.slots) {
|
|
3409
|
-
resolveDefineSlotsIface(
|
|
3500
|
+
resolveDefineSlotsIface(path9, ctx);
|
|
3410
3501
|
}
|
|
3411
3502
|
}
|
|
3412
3503
|
removePath();
|
|
@@ -3451,15 +3542,27 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3451
3542
|
function addDependency(exp) {
|
|
3452
3543
|
deps.set(getDependencyKey(exp), exp);
|
|
3453
3544
|
}
|
|
3545
|
+
const analyzeTargetPath = parentPath && parentPath.node === analyzeTarget ? parentPath : null;
|
|
3546
|
+
if (analyzeTargetPath) {
|
|
3547
|
+
if (t31.isMemberExpression(analyzeTarget) || t31.isOptionalMemberExpression(analyzeTarget)) {
|
|
3548
|
+
const rootId = findRootIdentifier(analyzeTarget);
|
|
3549
|
+
if (rootId) {
|
|
3550
|
+
tryAddDependency(analyzeTargetPath, rootId.name, analyzeTargetPath.scope);
|
|
3551
|
+
processedIdentifiers.add(rootId);
|
|
3552
|
+
}
|
|
3553
|
+
} else if (t31.isIdentifier(analyzeTarget)) {
|
|
3554
|
+
tryAddDependency(analyzeTargetPath, analyzeTarget.name, analyzeTargetPath.scope);
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3454
3557
|
traverse2(
|
|
3455
3558
|
analyzeTarget,
|
|
3456
3559
|
{
|
|
3457
3560
|
"MemberExpression|OptionalMemberExpression"(memberPath) {
|
|
3458
|
-
const
|
|
3459
|
-
if (isNestedMemberObject(
|
|
3460
|
-
const rootId = findRootIdentifier(
|
|
3561
|
+
const path9 = memberPath;
|
|
3562
|
+
if (isNestedMemberObject(path9)) return;
|
|
3563
|
+
const rootId = findRootIdentifier(path9.node);
|
|
3461
3564
|
if (!rootId) return;
|
|
3462
|
-
tryAddDependency(
|
|
3565
|
+
tryAddDependency(path9, rootId.name, path9.scope);
|
|
3463
3566
|
processedIdentifiers.add(rootId);
|
|
3464
3567
|
},
|
|
3465
3568
|
Identifier(idPath) {
|
|
@@ -3491,16 +3594,19 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3491
3594
|
}
|
|
3492
3595
|
const sourcedExpression = traceBindingSource(binding, /* @__PURE__ */ new Set(), TRACE_MAX_DEPTH);
|
|
3493
3596
|
if (sourcedExpression) {
|
|
3494
|
-
|
|
3597
|
+
const normalizedSource = normalizeSourcedDependency(sourcedExpression);
|
|
3598
|
+
if (normalizedSource) {
|
|
3599
|
+
addDependency(normalizedSource);
|
|
3600
|
+
}
|
|
3495
3601
|
}
|
|
3496
3602
|
}
|
|
3497
|
-
function normalizeDependencyExpr(
|
|
3498
|
-
if (t31.isIdentifier(
|
|
3499
|
-
return t31.identifier(
|
|
3603
|
+
function normalizeDependencyExpr(path9, rootName) {
|
|
3604
|
+
if (t31.isIdentifier(path9.node)) {
|
|
3605
|
+
return t31.identifier(path9.node.name);
|
|
3500
3606
|
}
|
|
3501
|
-
if (t31.isMemberExpression(
|
|
3502
|
-
const normalizedExp = normalizeMemberForCallSite(
|
|
3503
|
-
const safeExp = t31.isMemberExpression(normalizedExp) || t31.isOptionalMemberExpression(normalizedExp) ?
|
|
3607
|
+
if (t31.isMemberExpression(path9.node) || t31.isOptionalMemberExpression(path9.node)) {
|
|
3608
|
+
const normalizedExp = normalizeMemberForCallSite(path9, path9.node);
|
|
3609
|
+
const safeExp = t31.isMemberExpression(normalizedExp) || t31.isOptionalMemberExpression(normalizedExp) ? ensureOptionalForMemberChain(normalizedExp) : normalizedExp;
|
|
3504
3610
|
if (isReactValidDependencyExpr(safeExp)) {
|
|
3505
3611
|
return t31.cloneNode(safeExp, true);
|
|
3506
3612
|
}
|
|
@@ -3508,6 +3614,21 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3508
3614
|
}
|
|
3509
3615
|
return null;
|
|
3510
3616
|
}
|
|
3617
|
+
function normalizeSourcedDependency(exp) {
|
|
3618
|
+
if (t31.isIdentifier(exp)) {
|
|
3619
|
+
return t31.identifier(exp.name);
|
|
3620
|
+
}
|
|
3621
|
+
if (t31.isMemberExpression(exp) || t31.isOptionalMemberExpression(exp)) {
|
|
3622
|
+
const root = findRootIdentifier(exp);
|
|
3623
|
+
if (!root) return null;
|
|
3624
|
+
const safeExp = t31.isMemberExpression(exp) || t31.isOptionalMemberExpression(exp) ? ensureOptionalForMemberChain(exp) : exp;
|
|
3625
|
+
if (isReactValidDependencyExpr(safeExp)) {
|
|
3626
|
+
return t31.cloneNode(safeExp, true);
|
|
3627
|
+
}
|
|
3628
|
+
return t31.identifier(root.name);
|
|
3629
|
+
}
|
|
3630
|
+
return null;
|
|
3631
|
+
}
|
|
3511
3632
|
function isReactValidDependencyExpr(node2) {
|
|
3512
3633
|
if (t31.isIdentifier(node2)) {
|
|
3513
3634
|
return true;
|
|
@@ -3540,8 +3661,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3540
3661
|
}
|
|
3541
3662
|
return false;
|
|
3542
3663
|
}
|
|
3543
|
-
function normalizeMemberForCallSite(
|
|
3544
|
-
const parent =
|
|
3664
|
+
function normalizeMemberForCallSite(path9, node2) {
|
|
3665
|
+
const parent = path9.parentPath;
|
|
3545
3666
|
const isDirectCallee = !!parent && (parent.isCallExpression() && parent.node.callee === node2 || parent.isOptionalCallExpression() && parent.node.callee === node2);
|
|
3546
3667
|
if (!isDirectCallee) {
|
|
3547
3668
|
return node2;
|
|
@@ -3551,8 +3672,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3551
3672
|
}
|
|
3552
3673
|
return node2.object;
|
|
3553
3674
|
}
|
|
3554
|
-
function
|
|
3555
|
-
if (!
|
|
3675
|
+
function ensureOptionalForMemberChain(node2) {
|
|
3676
|
+
if (!hasTrailingMemberAccess(node2)) {
|
|
3556
3677
|
return node2;
|
|
3557
3678
|
}
|
|
3558
3679
|
if (t31.isOptionalMemberExpression(node2) && node2.optional) {
|
|
@@ -3562,19 +3683,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3562
3683
|
const property = t31.cloneNode(node2.property, true);
|
|
3563
3684
|
return t31.optionalMemberExpression(object, property, node2.computed, true);
|
|
3564
3685
|
}
|
|
3565
|
-
function
|
|
3566
|
-
|
|
3567
|
-
while (t31.isMemberExpression(current) || t31.isOptionalMemberExpression(current)) {
|
|
3568
|
-
if (current.computed) {
|
|
3569
|
-
if (t31.isStringLiteral(current.property) && current.property.value === "value") {
|
|
3570
|
-
return true;
|
|
3571
|
-
}
|
|
3572
|
-
} else if (t31.isIdentifier(current.property) && current.property.name === "value") {
|
|
3573
|
-
return true;
|
|
3574
|
-
}
|
|
3575
|
-
current = current.object;
|
|
3576
|
-
}
|
|
3577
|
-
return false;
|
|
3686
|
+
function hasTrailingMemberAccess(node2) {
|
|
3687
|
+
return t31.isMemberExpression(node2.object) || t31.isOptionalMemberExpression(node2.object);
|
|
3578
3688
|
}
|
|
3579
3689
|
function isEligibleBindingSource(binding) {
|
|
3580
3690
|
if (binding.kind === "param") {
|
|
@@ -3582,16 +3692,13 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3582
3692
|
}
|
|
3583
3693
|
const bindingPath = binding.path;
|
|
3584
3694
|
const declaratorPath = getVariableDeclaratorPath(bindingPath);
|
|
3585
|
-
const isImportBinding = bindingPath.isImportSpecifier() || bindingPath.isImportDefaultSpecifier() || bindingPath.isImportNamespaceSpecifier();
|
|
3586
3695
|
const isReactiveVarBinding = !!declaratorPath && isReactiveBinding(declaratorPath.node);
|
|
3587
3696
|
const nodeInit = declaratorPath?.node.init;
|
|
3588
3697
|
const isReactiveApiCallVarBinding = !!declaratorPath && t31.isCallExpression(nodeInit) && t31.isIdentifier(nodeInit.callee) && reactiveStateApis.has(nodeInit.callee.name);
|
|
3589
3698
|
const isHookCallVarBinding = !!declaratorPath && t31.isCallExpression(nodeInit) && isHookLikeCallee(nodeInit.callee);
|
|
3590
3699
|
const isFunctionBinding = bindingPath.isFunctionDeclaration() || !!declaratorPath && !!nodeInit && (t31.isArrowFunctionExpression(nodeInit) || t31.isFunctionExpression(nodeInit));
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
}
|
|
3594
|
-
return isImportBinding || isReactiveVarBinding || isReactiveApiCallVarBinding || isHookCallVarBinding || isFunctionBinding;
|
|
3700
|
+
const isReactiveFunctionBinding = isFunctionBinding && (isReactiveBinding(declaratorPath?.node) || isReactiveBinding(bindingPath.node));
|
|
3701
|
+
return isReactiveVarBinding || isReactiveApiCallVarBinding || isHookCallVarBinding || isReactiveFunctionBinding;
|
|
3595
3702
|
}
|
|
3596
3703
|
function isHookLikeCallee(callee) {
|
|
3597
3704
|
if (t31.isIdentifier(callee)) {
|
|
@@ -3687,11 +3794,11 @@ function getDependencyKey(exp) {
|
|
|
3687
3794
|
}
|
|
3688
3795
|
return exp.type;
|
|
3689
3796
|
}
|
|
3690
|
-
function isNestedMemberObject(
|
|
3691
|
-
const parent =
|
|
3797
|
+
function isNestedMemberObject(path9) {
|
|
3798
|
+
const parent = path9.parentPath;
|
|
3692
3799
|
if (!parent) return false;
|
|
3693
3800
|
if (parent.isMemberExpression() || parent.isOptionalMemberExpression()) {
|
|
3694
|
-
return parent.node.object ===
|
|
3801
|
+
return parent.node.object === path9.node;
|
|
3695
3802
|
}
|
|
3696
3803
|
return false;
|
|
3697
3804
|
}
|
|
@@ -3699,27 +3806,22 @@ function isReactiveBinding(node) {
|
|
|
3699
3806
|
if (!node) return false;
|
|
3700
3807
|
return !!getScriptNodeMeta(node)?.is_reactive;
|
|
3701
3808
|
}
|
|
3702
|
-
function markAsAnalyzed(node, flag = true) {
|
|
3703
|
-
const analyzed = getIsAnalyzed(node);
|
|
3704
|
-
if (analyzed) return;
|
|
3705
|
-
setScriptNodeMeta(node, { is_deps_analyzed: flag });
|
|
3706
|
-
}
|
|
3707
|
-
function getIsAnalyzed(node) {
|
|
3708
|
-
return getScriptNodeMeta(node)?.is_deps_analyzed;
|
|
3709
|
-
}
|
|
3710
3809
|
|
|
3711
3810
|
// src/core/transform/sfc/script/syntax-processor/process/resolve-analysis-only-adapter.ts
|
|
3712
3811
|
function resolveAnalysisOnlyAdapter(ctx) {
|
|
3713
3812
|
return {
|
|
3714
|
-
"CallExpression|Identifier"(
|
|
3715
|
-
const node =
|
|
3813
|
+
"CallExpression|Identifier"(path9) {
|
|
3814
|
+
const node = path9.node;
|
|
3716
3815
|
const apiName = getApiName(node);
|
|
3717
3816
|
const adapter = ADAPTER_RULES.runtime[apiName];
|
|
3718
3817
|
if (!adapter || adapter.type !== "analyzed-deps") {
|
|
3719
3818
|
return;
|
|
3720
3819
|
}
|
|
3820
|
+
if (!isVueApiReference(path9, apiName)) {
|
|
3821
|
+
return;
|
|
3822
|
+
}
|
|
3721
3823
|
if (t32.isCallExpression(node)) {
|
|
3722
|
-
resolveCallNode(
|
|
3824
|
+
resolveCallNode(path9, adapter, ctx);
|
|
3723
3825
|
} else {
|
|
3724
3826
|
replaceIdName(node, adapter.target);
|
|
3725
3827
|
}
|
|
@@ -3737,59 +3839,77 @@ function getApiName(node) {
|
|
|
3737
3839
|
}
|
|
3738
3840
|
return apiName;
|
|
3739
3841
|
}
|
|
3740
|
-
function resolveCallNode(
|
|
3741
|
-
const { node } =
|
|
3842
|
+
function resolveCallNode(path9, adapter, ctx) {
|
|
3843
|
+
const { node } = path9;
|
|
3742
3844
|
const { arguments: args } = node;
|
|
3743
3845
|
if (!args.length) return;
|
|
3744
3846
|
const fn = args[0];
|
|
3745
3847
|
if (!t32.isArrowFunctionExpression(fn) && !t32.isFunctionExpression(fn)) {
|
|
3746
3848
|
return;
|
|
3747
3849
|
}
|
|
3748
|
-
const fnPath =
|
|
3850
|
+
const fnPath = path9.get("arguments")[0];
|
|
3749
3851
|
const deps = analyzeDeps(fn, ctx, fnPath);
|
|
3750
3852
|
args.push(deps);
|
|
3751
3853
|
replaceCallName(node, adapter.target);
|
|
3752
3854
|
recordImport(ctx, adapter.package, adapter.target);
|
|
3753
3855
|
}
|
|
3856
|
+
function isVueApiReference(path9, apiName) {
|
|
3857
|
+
if (path9.isIdentifier()) {
|
|
3858
|
+
if (path9.parentPath.isCallExpression() && path9.parentPath.node.callee === path9.node) {
|
|
3859
|
+
return false;
|
|
3860
|
+
}
|
|
3861
|
+
if (!path9.isReferencedIdentifier()) {
|
|
3862
|
+
return false;
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
if (path9.isCallExpression()) {
|
|
3866
|
+
const callee = path9.get("callee");
|
|
3867
|
+
if (!callee.isIdentifier()) return false;
|
|
3868
|
+
return isVueImportBinding(callee.scope.getBinding(apiName));
|
|
3869
|
+
}
|
|
3870
|
+
return isVueImportBinding(path9.scope.getBinding(apiName));
|
|
3871
|
+
}
|
|
3872
|
+
function isVueImportBinding(binding) {
|
|
3873
|
+
if (!binding) return false;
|
|
3874
|
+
const bindingPath = binding.path;
|
|
3875
|
+
if (!bindingPath.isImportSpecifier() && !bindingPath.isImportDefaultSpecifier() && !bindingPath.isImportNamespaceSpecifier()) {
|
|
3876
|
+
return false;
|
|
3877
|
+
}
|
|
3878
|
+
const parent = bindingPath.parentPath?.node;
|
|
3879
|
+
if (!parent || !t32.isImportDeclaration(parent)) {
|
|
3880
|
+
return false;
|
|
3881
|
+
}
|
|
3882
|
+
const source = parent.source.value.toLowerCase();
|
|
3883
|
+
if (source.startsWith("@vue/")) {
|
|
3884
|
+
return true;
|
|
3885
|
+
}
|
|
3886
|
+
if (source === "vue-router" || source.startsWith("vue-router/")) {
|
|
3887
|
+
return true;
|
|
3888
|
+
}
|
|
3889
|
+
return VUE_PACKAGES.some((name) => source === name || source.startsWith(`${name}/`));
|
|
3890
|
+
}
|
|
3754
3891
|
|
|
3755
3892
|
// src/core/transform/sfc/script/syntax-processor/process/resolve-arrow-deps.ts
|
|
3756
3893
|
function resolveArrowFnDeps(ctx, ast) {
|
|
3757
3894
|
return {
|
|
3758
|
-
ArrowFunctionExpression(
|
|
3759
|
-
const { node, parentPath } =
|
|
3760
|
-
if (isSkip(
|
|
3895
|
+
ArrowFunctionExpression(path9) {
|
|
3896
|
+
const { node, parentPath } = path9;
|
|
3897
|
+
if (isSkip(path9) || !atComponentOrHookRoot(parentPath, ast.program)) {
|
|
3761
3898
|
return;
|
|
3762
3899
|
}
|
|
3763
|
-
const deps = analyzeDeps(node, ctx,
|
|
3900
|
+
const deps = analyzeDeps(node, ctx, path9);
|
|
3764
3901
|
if (!deps.elements.length) return;
|
|
3765
3902
|
const newNode = createUseCallback(node, deps);
|
|
3766
|
-
const declaratorPath = getVariableDeclaratorPath(
|
|
3767
|
-
markAsAnalyzed(newNode.arguments[0]);
|
|
3903
|
+
const declaratorPath = getVariableDeclaratorPath(path9);
|
|
3768
3904
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.useCallback);
|
|
3769
3905
|
setScriptNodeMeta(declaratorPath?.node, { is_reactive: true, reactive_type: "indirect" });
|
|
3770
|
-
|
|
3771
|
-
}
|
|
3772
|
-
};
|
|
3773
|
-
}
|
|
3774
|
-
function resolveUnanalyzedArrow(ctx) {
|
|
3775
|
-
return {
|
|
3776
|
-
ArrowFunctionExpression(path8) {
|
|
3777
|
-
const { node } = path8;
|
|
3778
|
-
const analyzed = getIsAnalyzed(node);
|
|
3779
|
-
if (typeof analyzed === "undefined" || analyzed) return;
|
|
3780
|
-
const newNode = createUseCallback(node);
|
|
3781
|
-
const declaratorPath = getVariableDeclaratorPath(path8);
|
|
3782
|
-
if (declaratorPath?.node) {
|
|
3783
|
-
setScriptNodeMeta(declaratorPath.node, { is_reactive: true, reactive_type: "indirect" });
|
|
3784
|
-
}
|
|
3785
|
-
markAsAnalyzed(newNode.arguments[0]);
|
|
3786
|
-
path8.replaceWith(newNode);
|
|
3906
|
+
path9.replaceWith(newNode);
|
|
3787
3907
|
}
|
|
3788
3908
|
};
|
|
3789
3909
|
}
|
|
3790
|
-
function isSkip(
|
|
3791
|
-
const { parentPath } =
|
|
3792
|
-
const isVariableDecl = () => getVariableDeclaratorPath(
|
|
3910
|
+
function isSkip(path9) {
|
|
3911
|
+
const { parentPath } = path9;
|
|
3912
|
+
const isVariableDecl = () => getVariableDeclaratorPath(path9) !== null;
|
|
3793
3913
|
const isReturnFunc = () => !isVariableDecl() && parentPath.isReturnStatement();
|
|
3794
3914
|
const isCallback = () => {
|
|
3795
3915
|
if (!parentPath) {
|
|
@@ -3798,12 +3918,12 @@ function isSkip(path8) {
|
|
|
3798
3918
|
if (parentPath.isCallExpression()) {
|
|
3799
3919
|
const callExpressionPath = parentPath;
|
|
3800
3920
|
const args = callExpressionPath.node.arguments;
|
|
3801
|
-
return args.some((arg) => arg ===
|
|
3921
|
+
return args.some((arg) => arg === path9.node);
|
|
3802
3922
|
}
|
|
3803
3923
|
if (parentPath.isArrayExpression()) {
|
|
3804
3924
|
const arrayExpressionPath = parentPath;
|
|
3805
3925
|
const elements = arrayExpressionPath.node.elements;
|
|
3806
|
-
return elements.some((element) => element ===
|
|
3926
|
+
return elements.some((element) => element === path9.node);
|
|
3807
3927
|
}
|
|
3808
3928
|
return false;
|
|
3809
3929
|
};
|
|
@@ -3827,13 +3947,13 @@ function isSkip(path8) {
|
|
|
3827
3947
|
import * as t33 from "@babel/types";
|
|
3828
3948
|
function resolveElementRef(ctx) {
|
|
3829
3949
|
return {
|
|
3830
|
-
CallExpression(
|
|
3950
|
+
CallExpression(path9) {
|
|
3831
3951
|
const {
|
|
3832
3952
|
inputType,
|
|
3833
3953
|
templateData: { refBindings }
|
|
3834
3954
|
} = ctx;
|
|
3835
3955
|
if (inputType !== "sfc") return;
|
|
3836
|
-
const { node } =
|
|
3956
|
+
const { node } = path9;
|
|
3837
3957
|
const isUseTemplateRef = isCalleeNamed(node, VUE_API_MAP.useTemplateRef);
|
|
3838
3958
|
const isCompRefBindings = Object.keys(refBindings.componentRefs).length > 0 && isCalleeNamed(node, VUE_API_MAP.ref);
|
|
3839
3959
|
const shouldProcess = isUseTemplateRef || isCompRefBindings;
|
|
@@ -3841,7 +3961,7 @@ function resolveElementRef(ctx) {
|
|
|
3841
3961
|
return;
|
|
3842
3962
|
}
|
|
3843
3963
|
if (isCompRefBindings) {
|
|
3844
|
-
const varDeclaratorPath = getVariableDeclaratorPath(
|
|
3964
|
+
const varDeclaratorPath = getVariableDeclaratorPath(path9)?.node;
|
|
3845
3965
|
if (!t33.isIdentifier(varDeclaratorPath?.id)) {
|
|
3846
3966
|
return;
|
|
3847
3967
|
}
|
|
@@ -3850,22 +3970,22 @@ function resolveElementRef(ctx) {
|
|
|
3850
3970
|
if (!compRef) return;
|
|
3851
3971
|
}
|
|
3852
3972
|
node.arguments[0] = t33.identifier("null");
|
|
3853
|
-
resolveTypeParameters(ctx,
|
|
3973
|
+
resolveTypeParameters(ctx, path9);
|
|
3854
3974
|
replaceCallName(node, REACT_API_MAP.useRef);
|
|
3855
3975
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.useRef);
|
|
3856
3976
|
},
|
|
3857
|
-
MemberExpression(
|
|
3858
|
-
resolveRefValueToCurrent(
|
|
3977
|
+
MemberExpression(path9) {
|
|
3978
|
+
resolveRefValueToCurrent(path9);
|
|
3859
3979
|
}
|
|
3860
3980
|
};
|
|
3861
3981
|
}
|
|
3862
|
-
function resolveTypeParameters(ctx,
|
|
3982
|
+
function resolveTypeParameters(ctx, path9) {
|
|
3863
3983
|
const {
|
|
3864
3984
|
templateData: { refBindings },
|
|
3865
3985
|
scriptData
|
|
3866
3986
|
} = ctx;
|
|
3867
|
-
const { node } =
|
|
3868
|
-
const varDeclaratorNode = getVariableDeclaratorPath(
|
|
3987
|
+
const { node } = path9;
|
|
3988
|
+
const varDeclaratorNode = getVariableDeclaratorPath(path9)?.node;
|
|
3869
3989
|
if (!scriptData.lang.startsWith("ts") || !varDeclaratorNode) {
|
|
3870
3990
|
return;
|
|
3871
3991
|
}
|
|
@@ -3877,12 +3997,12 @@ function resolveTypeParameters(ctx, path8) {
|
|
|
3877
3997
|
node.typeParameters = t33.tsTypeParameterInstantiation([t33.tsTypeReference(t33.identifier(type))]);
|
|
3878
3998
|
}
|
|
3879
3999
|
}
|
|
3880
|
-
function resolveRefValueToCurrent(
|
|
3881
|
-
const { node } =
|
|
4000
|
+
function resolveRefValueToCurrent(path9) {
|
|
4001
|
+
const { node } = path9;
|
|
3882
4002
|
if (node.computed || !t33.isIdentifier(node.property) || node.property.name !== "value") {
|
|
3883
4003
|
return;
|
|
3884
4004
|
}
|
|
3885
|
-
const rootPath = findRootVariablePath(
|
|
4005
|
+
const rootPath = findRootVariablePath(path9);
|
|
3886
4006
|
if (!rootPath?.node || !t33.isCallExpression(rootPath.node.init) || !isCalleeNamed(rootPath.node.init, REACT_API_MAP.useRef)) {
|
|
3887
4007
|
return;
|
|
3888
4008
|
}
|
|
@@ -3898,21 +4018,25 @@ import * as t34 from "@babel/types";
|
|
|
3898
4018
|
function resolveExprMemo(ctx, ast) {
|
|
3899
4019
|
const isScriptFile = ctx.inputType !== "sfc";
|
|
3900
4020
|
return {
|
|
3901
|
-
VariableDeclarator(
|
|
3902
|
-
const { node } =
|
|
4021
|
+
VariableDeclarator(path9) {
|
|
4022
|
+
const { node } = path9;
|
|
3903
4023
|
const { init } = node;
|
|
3904
|
-
if (!init) return;
|
|
3905
4024
|
const shouldMemo = () => {
|
|
3906
|
-
if (!
|
|
4025
|
+
if (!init) return false;
|
|
4026
|
+
if (!atComponentOrHookRoot(path9, ast.program, isScriptFile)) {
|
|
4027
|
+
return false;
|
|
4028
|
+
}
|
|
4029
|
+
if (!t34.isVariableDeclaration(path9.parent) || path9.parent.kind !== "const") {
|
|
3907
4030
|
return false;
|
|
3908
4031
|
}
|
|
4032
|
+
if (t34.isFunction(init)) return false;
|
|
3909
4033
|
if (t34.isCallExpression(init) && t34.isIdentifier(init.callee) && init.callee.name.startsWith("use")) {
|
|
3910
4034
|
return false;
|
|
3911
4035
|
}
|
|
3912
4036
|
return true;
|
|
3913
4037
|
};
|
|
3914
4038
|
if (!shouldMemo()) return;
|
|
3915
|
-
const initPath =
|
|
4039
|
+
const initPath = path9.get("init");
|
|
3916
4040
|
if (!initPath.isExpression()) return;
|
|
3917
4041
|
const deps = analyzeDeps(initPath.node, ctx, initPath);
|
|
3918
4042
|
if (!deps.elements.length) return;
|
|
@@ -3928,8 +4052,8 @@ import * as t35 from "@babel/types";
|
|
|
3928
4052
|
function resolveLintRules(ctx, ast) {
|
|
3929
4053
|
const inScriptFile = ctx.inputType !== "sfc";
|
|
3930
4054
|
return {
|
|
3931
|
-
CallExpression(
|
|
3932
|
-
const { node, parentPath } =
|
|
4055
|
+
CallExpression(path9) {
|
|
4056
|
+
const { node, parentPath } = path9;
|
|
3933
4057
|
if (!t35.isIdentifier(node.callee)) return;
|
|
3934
4058
|
const { name: callName } = node.callee;
|
|
3935
4059
|
const addLog = (t41) => {
|
|
@@ -3948,7 +4072,7 @@ function resolveLintRules(ctx, ast) {
|
|
|
3948
4072
|
);
|
|
3949
4073
|
return;
|
|
3950
4074
|
}
|
|
3951
|
-
if (!atComponentOrHookRoot(
|
|
4075
|
+
if (!atComponentOrHookRoot(path9, ast.program)) {
|
|
3952
4076
|
addLog(
|
|
3953
4077
|
`The ${macro} must be defined at the top level of the component, not inside blocks or functions.`
|
|
3954
4078
|
);
|
|
@@ -3964,7 +4088,7 @@ function resolveLintRules(ctx, ast) {
|
|
|
3964
4088
|
};
|
|
3965
4089
|
const lintHooks = () => {
|
|
3966
4090
|
if (!callName.startsWith("use")) return;
|
|
3967
|
-
if (!atComponentOrHookRoot(
|
|
4091
|
+
if (!atComponentOrHookRoot(path9, ast.program, inScriptFile)) {
|
|
3968
4092
|
addLog(
|
|
3969
4093
|
`The ${callName} hook must be called at the top level, not inside loops, conditions, or nested functions.`
|
|
3970
4094
|
);
|
|
@@ -3982,8 +4106,8 @@ import * as t36 from "@babel/types";
|
|
|
3982
4106
|
function resolveProvide(ctx) {
|
|
3983
4107
|
if (ctx.inputType === "style") return {};
|
|
3984
4108
|
return {
|
|
3985
|
-
CallExpression(
|
|
3986
|
-
const { node } =
|
|
4109
|
+
CallExpression(path9) {
|
|
4110
|
+
const { node } = path9;
|
|
3987
4111
|
const providerTarget = ADAPTER_RULES.runtime[VUE_API_MAP.provide]?.target;
|
|
3988
4112
|
const isProvideCall = isCalleeNamed(node, VUE_API_MAP.provide) || providerTarget && isCalleeNamed(node, providerTarget);
|
|
3989
4113
|
if (!isProvideCall) return;
|
|
@@ -3993,7 +4117,7 @@ function resolveProvide(ctx) {
|
|
|
3993
4117
|
const adapter = ADAPTER_RULES.runtime[VUE_API_MAP.provide];
|
|
3994
4118
|
assignProviderValue(target, key, value);
|
|
3995
4119
|
recordImport(ctx, adapter.package, adapter.target);
|
|
3996
|
-
|
|
4120
|
+
path9.parentPath.remove();
|
|
3997
4121
|
}
|
|
3998
4122
|
};
|
|
3999
4123
|
}
|
|
@@ -4035,8 +4159,8 @@ function assignProviderValue(target, key, value) {
|
|
|
4035
4159
|
import * as t37 from "@babel/types";
|
|
4036
4160
|
function resolveRenameAdapter(ctx) {
|
|
4037
4161
|
return {
|
|
4038
|
-
"CallExpression|Identifier"(
|
|
4039
|
-
const node =
|
|
4162
|
+
"CallExpression|Identifier"(path9) {
|
|
4163
|
+
const node = path9.node;
|
|
4040
4164
|
const isCallNode = t37.isCallExpression(node);
|
|
4041
4165
|
let apiName = "";
|
|
4042
4166
|
if (t37.isIdentifier(node)) {
|
|
@@ -4044,15 +4168,21 @@ function resolveRenameAdapter(ctx) {
|
|
|
4044
4168
|
} else if (isCallNode && t37.isIdentifier(node.callee)) {
|
|
4045
4169
|
apiName = node.callee.name;
|
|
4046
4170
|
}
|
|
4171
|
+
if (!apiName) {
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4047
4174
|
const runtimeAdapter = ADAPTER_RULES.runtime[apiName];
|
|
4048
4175
|
const routerAdapter = ADAPTER_RULES.router[apiName];
|
|
4049
4176
|
const adapter = runtimeAdapter || routerAdapter;
|
|
4050
4177
|
if (!adapter || adapter.type !== "rename") {
|
|
4051
4178
|
return;
|
|
4052
4179
|
}
|
|
4180
|
+
if (!isVueApiReference2(path9, apiName)) {
|
|
4181
|
+
return;
|
|
4182
|
+
}
|
|
4053
4183
|
if (adapter.isTrackable) {
|
|
4054
4184
|
const reactiveType = getReactiveType(apiName);
|
|
4055
|
-
const declaratorPath = getVariableDeclaratorPath(
|
|
4185
|
+
const declaratorPath = getVariableDeclaratorPath(path9);
|
|
4056
4186
|
setScriptNodeMeta(declaratorPath?.node, {
|
|
4057
4187
|
is_reactive: true,
|
|
4058
4188
|
reactive_type: reactiveType
|
|
@@ -4070,6 +4200,41 @@ function resolveRenameAdapter(ctx) {
|
|
|
4070
4200
|
}
|
|
4071
4201
|
};
|
|
4072
4202
|
}
|
|
4203
|
+
function isVueApiReference2(path9, apiName) {
|
|
4204
|
+
if (path9.isIdentifier()) {
|
|
4205
|
+
if (path9.parentPath.isCallExpression() && path9.parentPath.node.callee === path9.node) {
|
|
4206
|
+
return false;
|
|
4207
|
+
}
|
|
4208
|
+
if (!path9.isReferencedIdentifier()) {
|
|
4209
|
+
return false;
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
if (path9.isCallExpression()) {
|
|
4213
|
+
const callee = path9.get("callee");
|
|
4214
|
+
if (!callee.isIdentifier()) return false;
|
|
4215
|
+
return isVueImportBinding2(callee.scope.getBinding(apiName));
|
|
4216
|
+
}
|
|
4217
|
+
return isVueImportBinding2(path9.scope.getBinding(apiName));
|
|
4218
|
+
}
|
|
4219
|
+
function isVueImportBinding2(binding) {
|
|
4220
|
+
if (!binding) return false;
|
|
4221
|
+
const bindingPath = binding.path;
|
|
4222
|
+
if (!bindingPath.isImportSpecifier() && !bindingPath.isImportDefaultSpecifier() && !bindingPath.isImportNamespaceSpecifier()) {
|
|
4223
|
+
return false;
|
|
4224
|
+
}
|
|
4225
|
+
const parent = bindingPath.parentPath?.node;
|
|
4226
|
+
if (!parent || !t37.isImportDeclaration(parent)) {
|
|
4227
|
+
return false;
|
|
4228
|
+
}
|
|
4229
|
+
const source = parent.source.value.toLowerCase();
|
|
4230
|
+
if (source.startsWith("@vue/")) {
|
|
4231
|
+
return true;
|
|
4232
|
+
}
|
|
4233
|
+
if (source === "vue-router" || source.startsWith("vue-router/")) {
|
|
4234
|
+
return true;
|
|
4235
|
+
}
|
|
4236
|
+
return VUE_PACKAGES.some((name) => source === name || source.startsWith(`${name}/`));
|
|
4237
|
+
}
|
|
4073
4238
|
|
|
4074
4239
|
// src/core/transform/sfc/script/syntax-processor/index.ts
|
|
4075
4240
|
function processVueSyntax2(ast, ctx) {
|
|
@@ -4091,16 +4256,17 @@ function processVueSyntax2(ast, ctx) {
|
|
|
4091
4256
|
// provide 需要在 rename 之前收集并移除原始调用,避免被重命名后失配
|
|
4092
4257
|
resolveProvide,
|
|
4093
4258
|
resolveRenameAdapter,
|
|
4259
|
+
// fix:在分析函数前分析可优化为 useMemo 的顶层变量声明,
|
|
4260
|
+
// 使得后续能够被函数依赖分析
|
|
4261
|
+
resolveExprMemo,
|
|
4094
4262
|
resolveArrowFnDeps,
|
|
4095
|
-
resolveUnanalyzedArrow,
|
|
4096
4263
|
resolveAnalysisOnlyAdapter,
|
|
4097
|
-
resolveExprMemo,
|
|
4098
4264
|
resolveLintRules
|
|
4099
4265
|
],
|
|
4100
4266
|
excludeBabel: [resolveTemplateSlotIface, resolveCompIProps]
|
|
4101
4267
|
},
|
|
4102
4268
|
postprocess: {
|
|
4103
|
-
applyBabel: [
|
|
4269
|
+
applyBabel: [resolveRequiredImports, resolveStaticHoisting],
|
|
4104
4270
|
excludeBabel: [insertCSSImport, collectLocalStatements]
|
|
4105
4271
|
}
|
|
4106
4272
|
});
|
|
@@ -4241,7 +4407,7 @@ function isIdentifier20(code) {
|
|
|
4241
4407
|
function isStringLiteral12(code) {
|
|
4242
4408
|
try {
|
|
4243
4409
|
const node = parseExpression3(code);
|
|
4244
|
-
return t38.isStringLiteral(node)
|
|
4410
|
+
return t38.isStringLiteral(node);
|
|
4245
4411
|
} catch {
|
|
4246
4412
|
return false;
|
|
4247
4413
|
}
|
|
@@ -4314,7 +4480,10 @@ function normalizePropName(rawName, name) {
|
|
|
4314
4480
|
case "for":
|
|
4315
4481
|
return "htmlFor";
|
|
4316
4482
|
default:
|
|
4317
|
-
|
|
4483
|
+
if (!isVBind(rawName) && whitelist.test(name)) {
|
|
4484
|
+
return name;
|
|
4485
|
+
}
|
|
4486
|
+
return camelCase(name);
|
|
4318
4487
|
}
|
|
4319
4488
|
}
|
|
4320
4489
|
function isVOn(name) {
|
|
@@ -4330,7 +4499,7 @@ function isVModel(name) {
|
|
|
4330
4499
|
return /^v-model/.test(name ?? "");
|
|
4331
4500
|
}
|
|
4332
4501
|
function isClassAttr(name) {
|
|
4333
|
-
return /^(class|:class|v-bind:class|className)$/.test(name ?? "");
|
|
4502
|
+
return /^(class|:class|v-bind:class|className|class-name)$/.test(name ?? "");
|
|
4334
4503
|
}
|
|
4335
4504
|
function isStyleAttr(name) {
|
|
4336
4505
|
return /^(style|:style|v-bind:style)$/.test(name ?? "");
|
|
@@ -4524,7 +4693,6 @@ function resolveDefaultStyleModuleName(node) {
|
|
|
4524
4693
|
|
|
4525
4694
|
// src/core/transform/sfc/template/syntax-processor/preprocess/resolve-style-scope-attribute.ts
|
|
4526
4695
|
import {
|
|
4527
|
-
ElementTypes,
|
|
4528
4696
|
isSlotOutlet,
|
|
4529
4697
|
isTemplateNode,
|
|
4530
4698
|
NodeTypes as NodeTypes3
|
|
@@ -4548,21 +4716,30 @@ function walkElementNodes2(node, onElement) {
|
|
|
4548
4716
|
}
|
|
4549
4717
|
function injectStyleScopeAttribute(node, ctx) {
|
|
4550
4718
|
const { scopeId } = ctx.styleData;
|
|
4551
|
-
if (!scopeId ||
|
|
4719
|
+
if (!scopeId || isSlotOutlet(node) || isTemplateNode(node)) {
|
|
4552
4720
|
return;
|
|
4553
4721
|
}
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4722
|
+
let hasScopeId = false;
|
|
4723
|
+
let hasClassOrId = false;
|
|
4724
|
+
for (const prop of node.props) {
|
|
4725
|
+
if (prop.type === NodeTypes3.ATTRIBUTE) {
|
|
4726
|
+
if (prop.name === scopeId) {
|
|
4727
|
+
hasScopeId = true;
|
|
4728
|
+
break;
|
|
4729
|
+
}
|
|
4730
|
+
if (getHasClassOrId(prop.name)) {
|
|
4731
|
+
hasClassOrId = true;
|
|
4732
|
+
break;
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
if (prop.type === NodeTypes3.DIRECTIVE && prop.arg?.type === NodeTypes3.SIMPLE_EXPRESSION) {
|
|
4736
|
+
if (getHasClassOrId(prop.arg.content)) {
|
|
4737
|
+
hasClassOrId = true;
|
|
4738
|
+
break;
|
|
4739
|
+
}
|
|
4557
4740
|
}
|
|
4558
|
-
return prop.arg.content === "is";
|
|
4559
|
-
});
|
|
4560
|
-
const hasScopeId = node.props.some(
|
|
4561
|
-
(prop) => prop.type === NodeTypes3.ATTRIBUTE && prop.name === scopeId
|
|
4562
|
-
);
|
|
4563
|
-
if (hasDynamicIs || hasScopeId) {
|
|
4564
|
-
return;
|
|
4565
4741
|
}
|
|
4742
|
+
if (hasScopeId || !hasClassOrId) return;
|
|
4566
4743
|
const attr = {
|
|
4567
4744
|
type: NodeTypes3.ATTRIBUTE,
|
|
4568
4745
|
name: scopeId,
|
|
@@ -4572,11 +4749,8 @@ function injectStyleScopeAttribute(node, ctx) {
|
|
|
4572
4749
|
};
|
|
4573
4750
|
node.props.push(attr);
|
|
4574
4751
|
}
|
|
4575
|
-
function
|
|
4576
|
-
|
|
4577
|
-
return camelCase(node.tag) !== node.tag;
|
|
4578
|
-
}
|
|
4579
|
-
return node.tagType === ElementTypes.COMPONENT;
|
|
4752
|
+
function getHasClassOrId(ns) {
|
|
4753
|
+
return isClassAttr(ns) || ns === "id";
|
|
4580
4754
|
}
|
|
4581
4755
|
|
|
4582
4756
|
// src/core/transform/sfc/template/shared/prop-merge-utils.ts
|
|
@@ -4767,7 +4941,12 @@ function resolvePropertyIR(node, ir, ctx, nodeIR, isDynamic = false) {
|
|
|
4767
4941
|
content = node.value.content = parseStyleString(content);
|
|
4768
4942
|
}
|
|
4769
4943
|
if (isDynamic) {
|
|
4770
|
-
|
|
4944
|
+
const isStringLiteral13 = strCodeTypes.isStringLiteral(content);
|
|
4945
|
+
if (isStringLiteral13) {
|
|
4946
|
+
content = normalizeString(content);
|
|
4947
|
+
node.value.content = content;
|
|
4948
|
+
}
|
|
4949
|
+
node.value.isStringLiteral = isStringLiteral13;
|
|
4771
4950
|
}
|
|
4772
4951
|
const existing = findSameProp(nodeIR.props, node);
|
|
4773
4952
|
if (existing) {
|
|
@@ -4777,6 +4956,12 @@ function resolvePropertyIR(node, ir, ctx, nodeIR, isDynamic = false) {
|
|
|
4777
4956
|
}
|
|
4778
4957
|
resolvePropAsBabelExp(existing ?? node, ctx);
|
|
4779
4958
|
}
|
|
4959
|
+
function normalizeString(s) {
|
|
4960
|
+
if (s.startsWith("'") && s.endsWith("'")) {
|
|
4961
|
+
return s.slice(1, -1);
|
|
4962
|
+
}
|
|
4963
|
+
return s;
|
|
4964
|
+
}
|
|
4780
4965
|
|
|
4781
4966
|
// src/core/transform/sfc/template/syntax-processor/process/props/resolve-attribute-prop.ts
|
|
4782
4967
|
function resolveAttributeProp(node, ir, ctx, nodeIR) {
|
|
@@ -4916,7 +5101,7 @@ function resolveVMemo(node, _ir, ctx, nodeIR) {
|
|
|
4916
5101
|
|
|
4917
5102
|
// src/core/transform/sfc/template/syntax-processor/process/props/resolve-v-model.ts
|
|
4918
5103
|
import {
|
|
4919
|
-
ElementTypes
|
|
5104
|
+
ElementTypes,
|
|
4920
5105
|
NodeTypes as NodeTypes6
|
|
4921
5106
|
} from "@vue/compiler-core";
|
|
4922
5107
|
function resolveVModel(node, _ir, ctx, elementNode, nodeIR) {
|
|
@@ -4924,7 +5109,7 @@ function resolveVModel(node, _ir, ctx, elementNode, nodeIR) {
|
|
|
4924
5109
|
const exp = node.exp;
|
|
4925
5110
|
const modifiers = node.modifiers.map((item) => item.content);
|
|
4926
5111
|
const getterName = exp.content;
|
|
4927
|
-
const isComponent = elementNode.tagType ===
|
|
5112
|
+
const isComponent = elementNode.tagType === ElementTypes.COMPONENT;
|
|
4928
5113
|
const inputType = resolveHtmlInput(elementNode, isComponent);
|
|
4929
5114
|
const propName = arg?.content ?? resolveModelPropName(inputType, isComponent);
|
|
4930
5115
|
let valuePropIR;
|
|
@@ -5001,7 +5186,7 @@ function resolveVOn(node, _ir, ctx, nodeIR) {
|
|
|
5001
5186
|
const exp = node.exp;
|
|
5002
5187
|
const modifiers = node.modifiers.map((item) => item.content);
|
|
5003
5188
|
const captureIndex = modifiers.findIndex((modifier) => modifier === "capture");
|
|
5004
|
-
let eventName =
|
|
5189
|
+
let eventName = normalizeVOnEventName(arg.content);
|
|
5005
5190
|
let handler = resolveSpecialExpressions(exp.content.trim(), ctx);
|
|
5006
5191
|
if (captureIndex > -1) {
|
|
5007
5192
|
eventName = modifiers[captureIndex] ? `${eventName}Capture` : eventName;
|
|
@@ -5012,7 +5197,7 @@ function resolveVOn(node, _ir, ctx, nodeIR) {
|
|
|
5012
5197
|
originalVueEventName = `${arg.content}.${modifiers.join(".")}`;
|
|
5013
5198
|
} else {
|
|
5014
5199
|
const expr = stringToExpr(handler);
|
|
5015
|
-
if (!t40.isFunctionExpression(expr) && !t40.isIdentifier(expr)) {
|
|
5200
|
+
if (!t40.isFunctionExpression(expr) && !t40.isArrowFunctionExpression(expr) && !t40.isIdentifier(expr)) {
|
|
5016
5201
|
handler = `() => {${handler}}`;
|
|
5017
5202
|
}
|
|
5018
5203
|
}
|
|
@@ -5030,6 +5215,11 @@ function resolveVOn(node, _ir, ctx, nodeIR) {
|
|
|
5030
5215
|
}
|
|
5031
5216
|
nodeIR.props.push(eventIR);
|
|
5032
5217
|
}
|
|
5218
|
+
function normalizeVOnEventName(rawEventName) {
|
|
5219
|
+
const segments = rawEventName.split(/[:-]/g).map((segment) => segment.trim()).filter(Boolean);
|
|
5220
|
+
const normalized = segments.map((segment) => capitalize(camelCase(segment))).join("");
|
|
5221
|
+
return `on${normalized}`;
|
|
5222
|
+
}
|
|
5033
5223
|
|
|
5034
5224
|
// src/core/transform/sfc/template/syntax-processor/process/props/resolve-v-show.ts
|
|
5035
5225
|
function resolveVShow(node, _ir, ctx, nodeIR) {
|
|
@@ -5203,7 +5393,7 @@ function resolveCommentNode(node, _ir, ctx, childrenIR) {
|
|
|
5203
5393
|
}
|
|
5204
5394
|
|
|
5205
5395
|
// src/core/transform/sfc/template/syntax-processor/process/resolve-element-node.ts
|
|
5206
|
-
import { ElementTypes as
|
|
5396
|
+
import { ElementTypes as ElementTypes2 } from "@vue/compiler-core";
|
|
5207
5397
|
function resolveElementNode(node, ir, ctx, siblingNodesIR) {
|
|
5208
5398
|
const isComponent = getIsComponent(node);
|
|
5209
5399
|
const tag = isComponent ? capitalize(camelCase(node.tag)) : node.tag;
|
|
@@ -5238,10 +5428,10 @@ function createElementNodeIR(options) {
|
|
|
5238
5428
|
};
|
|
5239
5429
|
}
|
|
5240
5430
|
function getIsComponent(node) {
|
|
5241
|
-
if (node.tagType !==
|
|
5431
|
+
if (node.tagType !== ElementTypes2.COMPONENT) {
|
|
5242
5432
|
return camelCase(node.tag) !== node.tag;
|
|
5243
5433
|
}
|
|
5244
|
-
return node.tagType ===
|
|
5434
|
+
return node.tagType === ElementTypes2.COMPONENT;
|
|
5245
5435
|
}
|
|
5246
5436
|
|
|
5247
5437
|
// src/core/transform/sfc/template/syntax-processor/process/resolve-interpolation-node.ts
|
|
@@ -5460,12 +5650,12 @@ function transform(ast, ctx, options) {
|
|
|
5460
5650
|
}
|
|
5461
5651
|
|
|
5462
5652
|
// package.json
|
|
5463
|
-
var version = "1.
|
|
5653
|
+
var version = "1.5.0";
|
|
5464
5654
|
var bin = {
|
|
5465
5655
|
vureact: "./bin/vureact.js"
|
|
5466
5656
|
};
|
|
5467
5657
|
|
|
5468
|
-
// src/compiler/shared/types.ts
|
|
5658
|
+
// src/compiler/shared/types/cache-types.ts
|
|
5469
5659
|
var CacheKey = /* @__PURE__ */ ((CacheKey2) => {
|
|
5470
5660
|
CacheKey2["SFC"] = "sfc";
|
|
5471
5661
|
CacheKey2["SCRIPT"] = "script";
|
|
@@ -5507,10 +5697,146 @@ function simpleFormat(code) {
|
|
|
5507
5697
|
}
|
|
5508
5698
|
|
|
5509
5699
|
// src/compiler/shared/helper.ts
|
|
5510
|
-
import
|
|
5700
|
+
import fs2 from "fs";
|
|
5701
|
+
import kleur4 from "kleur";
|
|
5702
|
+
import path3 from "path";
|
|
5703
|
+
|
|
5704
|
+
// src/compiler/shared/file-lock-manager.ts
|
|
5511
5705
|
import fs from "fs";
|
|
5512
5706
|
import kleur3 from "kleur";
|
|
5513
5707
|
import path2 from "path";
|
|
5708
|
+
import lockfile from "proper-lockfile";
|
|
5709
|
+
var FileLockManager = class _FileLockManager {
|
|
5710
|
+
static instance;
|
|
5711
|
+
/**
|
|
5712
|
+
* 获取单例实例
|
|
5713
|
+
*/
|
|
5714
|
+
static getInstance() {
|
|
5715
|
+
if (!_FileLockManager.instance) {
|
|
5716
|
+
_FileLockManager.instance = new _FileLockManager();
|
|
5717
|
+
}
|
|
5718
|
+
return _FileLockManager.instance;
|
|
5719
|
+
}
|
|
5720
|
+
/**
|
|
5721
|
+
* 获取文件锁并更新文件内容
|
|
5722
|
+
* @param filePath 文件路径
|
|
5723
|
+
* @param updater 更新函数,接收当前内容,返回更新后的内容
|
|
5724
|
+
* @param options 锁选项
|
|
5725
|
+
*/
|
|
5726
|
+
async updateFile(filePath, updater, options = {}) {
|
|
5727
|
+
return this.withLock(
|
|
5728
|
+
filePath,
|
|
5729
|
+
async () => {
|
|
5730
|
+
let current = null;
|
|
5731
|
+
try {
|
|
5732
|
+
const content = await fs.promises.readFile(filePath, "utf-8");
|
|
5733
|
+
if (content.trim()) {
|
|
5734
|
+
try {
|
|
5735
|
+
current = JSON.parse(content);
|
|
5736
|
+
} catch {
|
|
5737
|
+
current = content;
|
|
5738
|
+
}
|
|
5739
|
+
}
|
|
5740
|
+
} catch (error) {
|
|
5741
|
+
console.error(kleur3.red("\u2716"), `Failed to read file ${filePath}`);
|
|
5742
|
+
console.error(error);
|
|
5743
|
+
}
|
|
5744
|
+
const updated = await updater(current);
|
|
5745
|
+
const contentToWrite = typeof updated === "string" ? updated : JSON.stringify(updated, null, 2);
|
|
5746
|
+
await this.writeFile(filePath, contentToWrite);
|
|
5747
|
+
return updated;
|
|
5748
|
+
},
|
|
5749
|
+
options
|
|
5750
|
+
);
|
|
5751
|
+
}
|
|
5752
|
+
/**
|
|
5753
|
+
* 获取文件锁并执行操作
|
|
5754
|
+
* @param filePath 文件路径
|
|
5755
|
+
* @param operation 要执行的操作函数
|
|
5756
|
+
* @param options 锁选项
|
|
5757
|
+
*/
|
|
5758
|
+
async withLock(filePath, operation, options = {}) {
|
|
5759
|
+
const {
|
|
5760
|
+
stale = 1e4,
|
|
5761
|
+
update = stale / 2,
|
|
5762
|
+
retries = 5,
|
|
5763
|
+
realpath = true,
|
|
5764
|
+
lockfilePath
|
|
5765
|
+
} = options;
|
|
5766
|
+
await fs.promises.mkdir(path2.dirname(filePath), { recursive: true });
|
|
5767
|
+
try {
|
|
5768
|
+
await fs.promises.access(filePath);
|
|
5769
|
+
} catch {
|
|
5770
|
+
await this.writeFile(filePath, "");
|
|
5771
|
+
}
|
|
5772
|
+
const release = await lockfile.lock(filePath, {
|
|
5773
|
+
stale,
|
|
5774
|
+
update,
|
|
5775
|
+
retries,
|
|
5776
|
+
realpath,
|
|
5777
|
+
lockfilePath
|
|
5778
|
+
});
|
|
5779
|
+
try {
|
|
5780
|
+
return await operation();
|
|
5781
|
+
} finally {
|
|
5782
|
+
await release();
|
|
5783
|
+
}
|
|
5784
|
+
}
|
|
5785
|
+
/**
|
|
5786
|
+
* 检查文件是否被锁定
|
|
5787
|
+
* @param filePath 文件路径
|
|
5788
|
+
* @param options 锁选项
|
|
5789
|
+
*/
|
|
5790
|
+
async isLocked(filePath, options = {}) {
|
|
5791
|
+
const { stale = 1e4, realpath = true, lockfilePath } = options;
|
|
5792
|
+
try {
|
|
5793
|
+
return await lockfile.check(filePath, { stale, realpath, lockfilePath });
|
|
5794
|
+
} catch {
|
|
5795
|
+
return false;
|
|
5796
|
+
}
|
|
5797
|
+
}
|
|
5798
|
+
/**
|
|
5799
|
+
* 尝试获取锁(非阻塞)
|
|
5800
|
+
* @param filePath 文件路径
|
|
5801
|
+
* @param options 锁选项
|
|
5802
|
+
* @returns 如果成功获取锁,返回释放函数;否则返回 null
|
|
5803
|
+
*/
|
|
5804
|
+
async tryLock(filePath, options = {}) {
|
|
5805
|
+
const { stale = 1e4, update = stale / 2, realpath = true, lockfilePath } = options;
|
|
5806
|
+
try {
|
|
5807
|
+
const release = await lockfile.lock(filePath, {
|
|
5808
|
+
stale,
|
|
5809
|
+
update,
|
|
5810
|
+
retries: 0,
|
|
5811
|
+
// 不重试
|
|
5812
|
+
realpath,
|
|
5813
|
+
lockfilePath
|
|
5814
|
+
});
|
|
5815
|
+
return release;
|
|
5816
|
+
} catch {
|
|
5817
|
+
return null;
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5820
|
+
/**
|
|
5821
|
+
* 释放文件锁
|
|
5822
|
+
* @param filePath 文件路径
|
|
5823
|
+
* @param options 锁选项
|
|
5824
|
+
*/
|
|
5825
|
+
async unlock(filePath, options = {}) {
|
|
5826
|
+
const { realpath = true, lockfilePath } = options;
|
|
5827
|
+
try {
|
|
5828
|
+
await lockfile.unlock(filePath, { realpath, lockfilePath });
|
|
5829
|
+
} catch {
|
|
5830
|
+
}
|
|
5831
|
+
}
|
|
5832
|
+
async writeFile(filePath, content) {
|
|
5833
|
+
await fs.promises.mkdir(path2.dirname(filePath), { recursive: true });
|
|
5834
|
+
await fs.promises.writeFile(filePath, content, "utf-8");
|
|
5835
|
+
}
|
|
5836
|
+
};
|
|
5837
|
+
var fileLock = FileLockManager.getInstance();
|
|
5838
|
+
|
|
5839
|
+
// src/compiler/shared/helper.ts
|
|
5514
5840
|
var Helper = class {
|
|
5515
5841
|
compilerOpts;
|
|
5516
5842
|
pathFilter;
|
|
@@ -5535,35 +5861,37 @@ var Helper = class {
|
|
|
5535
5861
|
* 获取输入文件的路径
|
|
5536
5862
|
*/
|
|
5537
5863
|
getInputPath() {
|
|
5538
|
-
const { input } = this.compilerOpts;
|
|
5539
|
-
return
|
|
5864
|
+
const { input = "src" } = this.compilerOpts;
|
|
5865
|
+
return path3.resolve(this.getProjectRoot(), input);
|
|
5540
5866
|
}
|
|
5541
5867
|
/**
|
|
5542
5868
|
* 检查 input 路径是否是单个文件
|
|
5543
5869
|
*/
|
|
5544
5870
|
isSingleFile() {
|
|
5545
5871
|
const inputPath = this.getInputPath();
|
|
5546
|
-
return
|
|
5872
|
+
return fs2.existsSync(inputPath) && fs2.statSync(inputPath).isFile();
|
|
5547
5873
|
}
|
|
5548
5874
|
/**
|
|
5549
5875
|
* 获取输出文件的路径。如:'[root]/.vureact/dist/'
|
|
5876
|
+
* @param addInput 会输出如:'[root]/.vureact/dist/[input]/'
|
|
5550
5877
|
*/
|
|
5551
|
-
getOuputPath() {
|
|
5552
|
-
|
|
5878
|
+
getOuputPath(addInput = false) {
|
|
5879
|
+
const { input = "src" } = this.compilerOpts;
|
|
5880
|
+
return path3.resolve(this.getWorkspaceDir(), this.getOutDirName(), addInput ? input : "");
|
|
5553
5881
|
}
|
|
5554
5882
|
getOutDirName() {
|
|
5555
5883
|
const { output } = this.compilerOpts;
|
|
5556
5884
|
return output?.outDir || this.outDir;
|
|
5557
5885
|
}
|
|
5558
5886
|
getWorkspaceDir() {
|
|
5559
|
-
return
|
|
5887
|
+
return path3.resolve(this.getProjectRoot(), this.workspaceDir);
|
|
5560
5888
|
}
|
|
5561
5889
|
/**
|
|
5562
5890
|
* 根据相对输出路径反推源文件路径
|
|
5563
5891
|
*/
|
|
5564
5892
|
getSourcePath(outputPath) {
|
|
5565
|
-
const relativePath2 =
|
|
5566
|
-
return
|
|
5893
|
+
const relativePath2 = path3.relative(this.getOuputPath(), outputPath);
|
|
5894
|
+
return path3.resolve(this.getProjectRoot(), relativePath2);
|
|
5567
5895
|
}
|
|
5568
5896
|
getIgnoreAssets() {
|
|
5569
5897
|
const { output } = this.compilerOpts;
|
|
@@ -5581,7 +5909,9 @@ var Helper = class {
|
|
|
5581
5909
|
"eslint.config.",
|
|
5582
5910
|
"readme.",
|
|
5583
5911
|
"vue.",
|
|
5584
|
-
"
|
|
5912
|
+
".vue",
|
|
5913
|
+
"vureact.config.js",
|
|
5914
|
+
"vureact.config.ts"
|
|
5585
5915
|
]);
|
|
5586
5916
|
}
|
|
5587
5917
|
getIsCache() {
|
|
@@ -5591,19 +5921,19 @@ var Helper = class {
|
|
|
5591
5921
|
* 返回原始目录下的 package.json 路径
|
|
5592
5922
|
*/
|
|
5593
5923
|
getRootPkgPath() {
|
|
5594
|
-
return
|
|
5924
|
+
return path3.join(this.getProjectRoot(), "package.json");
|
|
5595
5925
|
}
|
|
5596
5926
|
/**
|
|
5597
5927
|
* 返回 output 的 package.json 路径
|
|
5598
5928
|
*/
|
|
5599
5929
|
getOutputPkgPath() {
|
|
5600
|
-
return
|
|
5930
|
+
return path3.join(this.getOuputPath(), "package.json");
|
|
5601
5931
|
}
|
|
5602
5932
|
/**
|
|
5603
5933
|
* 返回文件相对工作区的路径
|
|
5604
5934
|
*/
|
|
5605
5935
|
relativePath(filePath) {
|
|
5606
|
-
return
|
|
5936
|
+
return path3.relative(this.getProjectRoot(), filePath);
|
|
5607
5937
|
}
|
|
5608
5938
|
/**
|
|
5609
5939
|
* 替换 .vue 文件名后缀为 .jsx/.tsx
|
|
@@ -5615,8 +5945,8 @@ var Helper = class {
|
|
|
5615
5945
|
const relativePath2 = this.relativePath(filePath);
|
|
5616
5946
|
let newRelativePath = relativePath2.replace(/\.vue$/i, ext);
|
|
5617
5947
|
if (newRelativePath === relativePath2) {
|
|
5618
|
-
const { name, dir } =
|
|
5619
|
-
newRelativePath =
|
|
5948
|
+
const { name, dir } = path3.parse(relativePath2);
|
|
5949
|
+
newRelativePath = path3.join(dir, `${name}${ext}`);
|
|
5620
5950
|
}
|
|
5621
5951
|
return newRelativePath;
|
|
5622
5952
|
}
|
|
@@ -5624,7 +5954,7 @@ var Helper = class {
|
|
|
5624
5954
|
* 判断是否应该跳过不需要进行文件搜索的路径
|
|
5625
5955
|
*/
|
|
5626
5956
|
shouldSkipPath(filePath) {
|
|
5627
|
-
const baseName =
|
|
5957
|
+
const baseName = path3.basename(filePath);
|
|
5628
5958
|
const defaultExcludes = ["node_modules", "dist", "build", ".git", ".DS_Store"];
|
|
5629
5959
|
if (defaultExcludes.includes(baseName)) {
|
|
5630
5960
|
return true;
|
|
@@ -5640,7 +5970,7 @@ var Helper = class {
|
|
|
5640
5970
|
*/
|
|
5641
5971
|
resolveOutputPath(filePath, extname) {
|
|
5642
5972
|
const newRelativePath = extname ? this.replaceVueFileExt(filePath, `.${extname}`) : this.relativePath(filePath);
|
|
5643
|
-
const outputPath =
|
|
5973
|
+
const outputPath = path3.resolve(this.getOuputPath(), newRelativePath);
|
|
5644
5974
|
return outputPath;
|
|
5645
5975
|
}
|
|
5646
5976
|
/**
|
|
@@ -5680,20 +6010,34 @@ var Helper = class {
|
|
|
5680
6010
|
return a.fileSize === b.fileSize && a.mtime === b.mtime;
|
|
5681
6011
|
}
|
|
5682
6012
|
/**
|
|
5683
|
-
*
|
|
6013
|
+
* 统一的写文件方法,包含自动创建目录(带文件互斥锁可选)
|
|
6014
|
+
* @param filePath - 要写入的文件路径
|
|
6015
|
+
* @param content - 要写入的内容
|
|
6016
|
+
* @param options - 可选配置项
|
|
6017
|
+
* @param options.lock - 是否启用文件锁(默认false)
|
|
5684
6018
|
*/
|
|
5685
|
-
async writeFileWithDir(filePath, content) {
|
|
5686
|
-
|
|
5687
|
-
|
|
6019
|
+
async writeFileWithDir(filePath, content, options) {
|
|
6020
|
+
if (options?.lock) {
|
|
6021
|
+
await fileLock.updateFile(filePath, async () => content, options);
|
|
6022
|
+
} else {
|
|
6023
|
+
await fs2.promises.mkdir(path3.dirname(filePath), { recursive: true });
|
|
6024
|
+
await fs2.promises.writeFile(filePath, content, "utf-8");
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
async rmFile(filePath) {
|
|
6028
|
+
try {
|
|
6029
|
+
await fs2.promises.rm(filePath, { recursive: true, force: true });
|
|
6030
|
+
} catch {
|
|
6031
|
+
}
|
|
5688
6032
|
}
|
|
5689
6033
|
async loadCache(key) {
|
|
5690
6034
|
const cacheFile = this.getCachePath();
|
|
5691
6035
|
const defaultData = this.createCacheData(key);
|
|
5692
|
-
if (!
|
|
6036
|
+
if (!fs2.existsSync(cacheFile)) {
|
|
5693
6037
|
return defaultData;
|
|
5694
6038
|
}
|
|
5695
6039
|
try {
|
|
5696
|
-
const content = await
|
|
6040
|
+
const content = await fs2.promises.readFile(cacheFile, "utf-8");
|
|
5697
6041
|
const data = JSON.parse(content);
|
|
5698
6042
|
return {
|
|
5699
6043
|
key,
|
|
@@ -5721,15 +6065,25 @@ var Helper = class {
|
|
|
5721
6065
|
*/
|
|
5722
6066
|
getCachePath() {
|
|
5723
6067
|
const filename = "_metadata";
|
|
5724
|
-
return
|
|
6068
|
+
return path3.resolve(this.getProjectRoot(), this.workspaceDir, "cache", `${filename}.json`);
|
|
5725
6069
|
}
|
|
5726
6070
|
async saveCache(data) {
|
|
5727
6071
|
if (!this.getIsCache() || !data) {
|
|
5728
6072
|
return;
|
|
5729
6073
|
}
|
|
5730
|
-
const
|
|
5731
|
-
|
|
5732
|
-
|
|
6074
|
+
const getDefaultValue = () => ({
|
|
6075
|
+
["sfc" /* SFC */]: [],
|
|
6076
|
+
["script" /* SCRIPT */]: [],
|
|
6077
|
+
["style" /* STYLE */]: [],
|
|
6078
|
+
["copied" /* ASSET */]: []
|
|
6079
|
+
});
|
|
6080
|
+
const cachePath = this.getCachePath();
|
|
6081
|
+
await fileLock.updateFile(cachePath, (currentData) => {
|
|
6082
|
+
const { key, target } = data;
|
|
6083
|
+
const mergedData = currentData || getDefaultValue();
|
|
6084
|
+
mergedData[key] = target;
|
|
6085
|
+
return mergedData;
|
|
6086
|
+
});
|
|
5733
6087
|
}
|
|
5734
6088
|
genHash(content) {
|
|
5735
6089
|
return genHashByXXH(content);
|
|
@@ -5741,18 +6095,18 @@ var Helper = class {
|
|
|
5741
6095
|
*/
|
|
5742
6096
|
scanFiles(dir, filter) {
|
|
5743
6097
|
const results = [];
|
|
5744
|
-
if (!
|
|
6098
|
+
if (!fs2.existsSync(dir)) {
|
|
5745
6099
|
return results;
|
|
5746
6100
|
}
|
|
5747
|
-
const stats =
|
|
6101
|
+
const stats = fs2.statSync(dir);
|
|
5748
6102
|
if (stats.isFile()) {
|
|
5749
6103
|
return filter(dir) ? [dir] : [];
|
|
5750
6104
|
}
|
|
5751
|
-
const list =
|
|
6105
|
+
const list = fs2.readdirSync(dir);
|
|
5752
6106
|
for (const file of list) {
|
|
5753
|
-
const fullPath =
|
|
6107
|
+
const fullPath = path3.resolve(dir, file);
|
|
5754
6108
|
if (this.shouldSkipPath(fullPath)) continue;
|
|
5755
|
-
const stat =
|
|
6109
|
+
const stat = fs2.statSync(fullPath);
|
|
5756
6110
|
if (stat.isDirectory() && this.compilerOpts.recursive !== false) {
|
|
5757
6111
|
results.push(...this.scanFiles(fullPath, filter));
|
|
5758
6112
|
} else if (filter(fullPath)) {
|
|
@@ -5762,19 +6116,19 @@ var Helper = class {
|
|
|
5762
6116
|
return results;
|
|
5763
6117
|
}
|
|
5764
6118
|
getAbsPath(filePath) {
|
|
5765
|
-
return
|
|
6119
|
+
return path3.isAbsolute(filePath) ? filePath : path3.resolve(this.getProjectRoot(), filePath);
|
|
5766
6120
|
}
|
|
5767
6121
|
async getFileMeta(filePath) {
|
|
5768
|
-
const stats = await
|
|
6122
|
+
const stats = await fs2.promises.stat(filePath);
|
|
5769
6123
|
return {
|
|
5770
6124
|
fileSize: stats.size,
|
|
5771
6125
|
mtime: stats.mtimeMs
|
|
5772
6126
|
};
|
|
5773
6127
|
}
|
|
5774
6128
|
async removeOutputFile(filePath, resolveOutputPath) {
|
|
5775
|
-
const
|
|
5776
|
-
if (!
|
|
5777
|
-
await
|
|
6129
|
+
const path9 = resolveOutputPath ? this.resolveOutputPath(filePath) : filePath;
|
|
6130
|
+
if (!fs2.existsSync(path9)) return;
|
|
6131
|
+
await fs2.promises.unlink(path9);
|
|
5778
6132
|
}
|
|
5779
6133
|
updateCache(targetFile, newData, cache) {
|
|
5780
6134
|
const index = cache.target.findIndex((c) => c.file === targetFile);
|
|
@@ -5784,18 +6138,6 @@ var Helper = class {
|
|
|
5784
6138
|
cache.target.push(newData);
|
|
5785
6139
|
}
|
|
5786
6140
|
}
|
|
5787
|
-
resolveViteCreateApp() {
|
|
5788
|
-
const { output } = this.compilerOpts;
|
|
5789
|
-
const config = output?.bootstrapVite;
|
|
5790
|
-
const template = typeof config === "object" ? config.template : "react-ts";
|
|
5791
|
-
const outDirName = this.getOutDirName();
|
|
5792
|
-
const cmd = `npm create vite@latest ${outDirName} -- --template ${template}`;
|
|
5793
|
-
execSync(cmd, {
|
|
5794
|
-
cwd: this.getWorkspaceDir(),
|
|
5795
|
-
stdio: "ignore"
|
|
5796
|
-
// 隐藏 create-vite 内部的输出日志,保持终端整洁
|
|
5797
|
-
});
|
|
5798
|
-
}
|
|
5799
6141
|
/**
|
|
5800
6142
|
* 获取需要排除编译的文件
|
|
5801
6143
|
*/
|
|
@@ -5823,15 +6165,15 @@ var Helper = class {
|
|
|
5823
6165
|
}
|
|
5824
6166
|
printCompileInfo(file, duration) {
|
|
5825
6167
|
this.print(
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
6168
|
+
kleur4.green("Compiled"),
|
|
6169
|
+
kleur4.dim(normalizePath(this.relativePath(file))),
|
|
6170
|
+
kleur4.gray(`(${duration})`)
|
|
5829
6171
|
);
|
|
5830
6172
|
}
|
|
5831
6173
|
print(...message) {
|
|
5832
6174
|
if (this.compilerOpts.watch) {
|
|
5833
6175
|
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
|
|
5834
|
-
console.info(
|
|
6176
|
+
console.info(kleur4.dim(time), kleur4.cyan(kleur4.bold("[vureact]")), ...message);
|
|
5835
6177
|
return;
|
|
5836
6178
|
}
|
|
5837
6179
|
console.info(...message);
|
|
@@ -5839,17 +6181,34 @@ var Helper = class {
|
|
|
5839
6181
|
/**
|
|
5840
6182
|
* 读取 package.json 文件内容,并处理成对象返回
|
|
5841
6183
|
*/
|
|
5842
|
-
async resolvePackageFile(
|
|
6184
|
+
async resolvePackageFile(path9) {
|
|
6185
|
+
if (!fs2.existsSync(path9)) {
|
|
6186
|
+
return {};
|
|
6187
|
+
}
|
|
5843
6188
|
try {
|
|
5844
|
-
|
|
6189
|
+
const content = await fs2.promises.readFile(path9, "utf-8");
|
|
6190
|
+
if (!content.trim()) {
|
|
5845
6191
|
return {};
|
|
5846
6192
|
}
|
|
5847
|
-
return JSON.parse(
|
|
6193
|
+
return JSON.parse(content);
|
|
5848
6194
|
} catch (error) {
|
|
5849
|
-
console.error(
|
|
6195
|
+
console.error(kleur4.red("\u274C"), `Failed to parse JSON file ${path9}:
|
|
6196
|
+
`, error);
|
|
5850
6197
|
return {};
|
|
5851
6198
|
}
|
|
5852
6199
|
}
|
|
6200
|
+
/**
|
|
6201
|
+
* 获取目录到文件的相对路径
|
|
6202
|
+
* @returns 结果路径不包含文件拓展名,并以诸如 ./ 开头
|
|
6203
|
+
*/
|
|
6204
|
+
resolveRelativePath(from, to) {
|
|
6205
|
+
let relativePath2 = path3.relative(from, to);
|
|
6206
|
+
relativePath2 = relativePath2.substring(0, relativePath2.indexOf("."));
|
|
6207
|
+
if (!relativePath2.startsWith(".")) {
|
|
6208
|
+
relativePath2 = `./${relativePath2}`;
|
|
6209
|
+
}
|
|
6210
|
+
return normalizePath(relativePath2);
|
|
6211
|
+
}
|
|
5853
6212
|
};
|
|
5854
6213
|
|
|
5855
6214
|
// src/core/parse/style-only.ts
|
|
@@ -5886,7 +6245,7 @@ function parseOnlyStyle(source, ctx, options) {
|
|
|
5886
6245
|
}
|
|
5887
6246
|
|
|
5888
6247
|
// src/compiler/context/adapter.ts
|
|
5889
|
-
import
|
|
6248
|
+
import path4 from "path";
|
|
5890
6249
|
|
|
5891
6250
|
// src/compiler/context/creator.ts
|
|
5892
6251
|
function createCompilationCtx() {
|
|
@@ -5973,7 +6332,7 @@ var CompilationAdapter = class _CompilationAdapter {
|
|
|
5973
6332
|
return ctx;
|
|
5974
6333
|
}
|
|
5975
6334
|
static detectInputType(filename) {
|
|
5976
|
-
const ext =
|
|
6335
|
+
const ext = path4.extname(filename).toLowerCase();
|
|
5977
6336
|
switch (ext) {
|
|
5978
6337
|
case ".vue":
|
|
5979
6338
|
return "sfc";
|
|
@@ -5997,65 +6356,11 @@ var BaseCompiler = class extends Helper {
|
|
|
5997
6356
|
version = version;
|
|
5998
6357
|
options;
|
|
5999
6358
|
createContext = CompilationAdapter.createContext;
|
|
6000
|
-
/**
|
|
6001
|
-
* 创建基础编译器实例
|
|
6002
|
-
*
|
|
6003
|
-
* @param options - 编译器配置选项,包括缓存设置、插件配置、样式预处理等,
|
|
6004
|
-
* 所有选项都会传递给父类 {@link Helper} 进行初始化
|
|
6005
|
-
*
|
|
6006
|
-
* @see {@link CompilerOptions} 查看完整的配置选项说明
|
|
6007
|
-
*/
|
|
6008
6359
|
constructor(options = {}) {
|
|
6009
6360
|
super(options);
|
|
6010
6361
|
this.options = options;
|
|
6011
6362
|
}
|
|
6012
|
-
/**
|
|
6013
|
-
* 编译 Vue 源代码为 React 代码
|
|
6014
|
-
*
|
|
6015
|
-
* 该方法执行完整的编译流程,包括:
|
|
6016
|
-
* 1. 上下文初始化:创建独立的编译上下文
|
|
6017
|
-
* 2. 解析阶段:将 Vue 源代码解析为抽象语法树(AST)
|
|
6018
|
-
* 3. 转换阶段:将 Vue AST 转换为 React 中间表示(IR)
|
|
6019
|
-
* 4. 生成阶段:将 React IR 生成为目标代码
|
|
6020
|
-
* 5. 插件执行:在各阶段执行注册的插件
|
|
6021
|
-
* 6. 结果处理:整理编译结果并返回
|
|
6022
|
-
*
|
|
6023
|
-
* 编译过程使用 try-finally 确保上下文资源被正确清理,
|
|
6024
|
-
* 即使编译过程中发生错误也不会导致资源泄漏。
|
|
6025
|
-
*
|
|
6026
|
-
* @param source - Vue 源代码字符串
|
|
6027
|
-
* @param filename - 源文件名,用于生成文件ID和输出路径
|
|
6028
|
-
* @returns {CompilationResult} 编译结果,包含生成的代码和文件信息
|
|
6029
|
-
*
|
|
6030
|
-
* @example
|
|
6031
|
-
* ```typescript
|
|
6032
|
-
* const vueCode = `
|
|
6033
|
-
* <template>
|
|
6034
|
-
* <div class="container">{{ message }}</div>
|
|
6035
|
-
* </template>
|
|
6036
|
-
*
|
|
6037
|
-
* <script setup lang="ts">
|
|
6038
|
-
* import { ref } from 'vue;
|
|
6039
|
-
* const message = ref('Hello Vue')
|
|
6040
|
-
* </script>
|
|
6041
|
-
*
|
|
6042
|
-
* <style scoped>
|
|
6043
|
-
* .container {
|
|
6044
|
-
* padding: 20px;
|
|
6045
|
-
* }
|
|
6046
|
-
* </style>
|
|
6047
|
-
* `;
|
|
6048
|
-
*
|
|
6049
|
-
* const result = compiler.compile(vueCode, 'MyComponent.vue');
|
|
6050
|
-
* console.log(result);
|
|
6051
|
-
* ```
|
|
6052
|
-
*
|
|
6053
|
-
* @throws 不会直接抛出异常,错误通过日志系统记录
|
|
6054
|
-
* @see {@link parse} 解析函数
|
|
6055
|
-
* @see {@link transform} 转换函数
|
|
6056
|
-
* @see {@link generate} 生成函数
|
|
6057
|
-
* @see {@link executePlugins} 插件执行函数
|
|
6058
|
-
*/
|
|
6363
|
+
/** 编译 Vue 源代码为 React 代码 */
|
|
6059
6364
|
compile(source, filename) {
|
|
6060
6365
|
const { plugins, preprocessStyles = true } = this.options;
|
|
6061
6366
|
const fileId = this.genHash(filename);
|
|
@@ -6091,61 +6396,12 @@ var BaseCompiler = class extends Helper {
|
|
|
6091
6396
|
ctx.clear();
|
|
6092
6397
|
}
|
|
6093
6398
|
}
|
|
6094
|
-
/**
|
|
6095
|
-
* 初始化 Babel 代码生成选项
|
|
6096
|
-
*
|
|
6097
|
-
* 合并用户自定义的生成选项与默认选项,确保代码生成的一致性和正确性。
|
|
6098
|
-
* 默认配置优化了代码的可读性和性能:
|
|
6099
|
-
* 1. 最小化 Unicode 转义:只转义必要的字符,保持代码可读性
|
|
6100
|
-
* 2. 统一引号风格:使用单引号,符合 JavaScript 社区常见约定
|
|
6101
|
-
* 3. 代码压缩:启用最小化,移除不必要的空白字符
|
|
6102
|
-
*
|
|
6103
|
-
* 如果用户提供了自定义选项,会与默认选项进行深度合并,
|
|
6104
|
-
* 用户选项的优先级高于默认选项。
|
|
6105
|
-
*
|
|
6106
|
-
* @private
|
|
6107
|
-
* @param filename - 可选的文件名,用于源码映射配置
|
|
6108
|
-
* @returns {GeneratorOptions} 合并后的 Babel 生成选项
|
|
6109
|
-
*
|
|
6110
|
-
* @remarks
|
|
6111
|
-
* - 源码映射支持:如果启用了 sourceMaps 且提供了文件名,会自动设置 sourceFileName
|
|
6112
|
-
* - 选项合并策略:用户选项会覆盖默认选项,实现灵活的配置
|
|
6113
|
-
* - 性能优化:默认启用 minified 以减少生成代码的体积
|
|
6114
|
-
* - 编码安全:使用 jsesc 确保特殊字符的正确转义
|
|
6115
|
-
*
|
|
6116
|
-
* @example
|
|
6117
|
-
* ```typescript
|
|
6118
|
-
* // 默认选项
|
|
6119
|
-
* const defaultOptions = {
|
|
6120
|
-
* jsescOption: { minimal: true, quotes: 'single' },
|
|
6121
|
-
* minified: true
|
|
6122
|
-
* };
|
|
6123
|
-
*
|
|
6124
|
-
* // 用户自定义选项
|
|
6125
|
-
* const userOptions = {
|
|
6126
|
-
* minified: false, // 覆盖默认值
|
|
6127
|
-
* sourceMaps: true // 新增选项
|
|
6128
|
-
* };
|
|
6129
|
-
*
|
|
6130
|
-
* // 合并结果
|
|
6131
|
-
* const merged = {
|
|
6132
|
-
* jsescOption: { minimal: true, quotes: 'single' },
|
|
6133
|
-
* minified: false, // 用户值
|
|
6134
|
-
* sourceMaps: true // 用户值
|
|
6135
|
-
* };
|
|
6136
|
-
* ```
|
|
6137
|
-
*
|
|
6138
|
-
* @see {@link GeneratorOptions} Babel 生成选项类型定义
|
|
6139
|
-
*/
|
|
6140
6399
|
prepareGenerateOptions(filename) {
|
|
6141
6400
|
const userOptions = this.options.generate || {};
|
|
6142
6401
|
const mergedOptions = {
|
|
6143
|
-
// 配置 jsesc 避免 Unicode 转义
|
|
6144
6402
|
jsescOption: {
|
|
6145
6403
|
minimal: true,
|
|
6146
|
-
// 只转义必要的字符
|
|
6147
6404
|
quotes: "single"
|
|
6148
|
-
// 使用单引号
|
|
6149
6405
|
},
|
|
6150
6406
|
minified: true,
|
|
6151
6407
|
...userOptions
|
|
@@ -6155,36 +6411,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6155
6411
|
}
|
|
6156
6412
|
return mergedOptions;
|
|
6157
6413
|
}
|
|
6158
|
-
/**
|
|
6159
|
-
* 处理 SFC 和 Script 文件的编译结果
|
|
6160
|
-
*
|
|
6161
|
-
* 根据编译上下文中的输入类型(SFC 或 Script),整理并返回相应的编译结果。
|
|
6162
|
-
* 对于 SFC 文件,返回包含 JSX 和 CSS 信息的完整结果;
|
|
6163
|
-
* 对于 Script 文件,返回仅包含脚本信息的结果。
|
|
6164
|
-
*
|
|
6165
|
-
* 关键处理逻辑:
|
|
6166
|
-
* 1. 构建基础结果:包含文件ID、路由信息和生成的代码
|
|
6167
|
-
* 2. 确定输出路径:根据源文件路径和语言类型生成输出文件路径
|
|
6168
|
-
* 3. 区分文件类型:
|
|
6169
|
-
* - SFC 文件:生成 .tsx 扩展名,包含样式信息
|
|
6170
|
-
* - Script 文件:保持原扩展名,不包含样式信息
|
|
6171
|
-
* 4. 样式处理:提取样式文件路径、作用域ID和样式代码
|
|
6172
|
-
*
|
|
6173
|
-
* @private
|
|
6174
|
-
* @param ir - React 中间表示(IR)描述符,包含转换后的组件信息
|
|
6175
|
-
* @param gen - 代码生成结果,包含生成的代码和源码映射
|
|
6176
|
-
* @param ctxData - 编译上下文数据,包含文件信息和编译状态
|
|
6177
|
-
* @returns {CompilationResult} 整理后的编译结果
|
|
6178
|
-
*
|
|
6179
|
-
* @remarks
|
|
6180
|
-
* - 文件扩展名处理:Vue SFC 文件会转换为 .tsx 或 .jsx 文件
|
|
6181
|
-
* - 样式分离:SFC 中的样式会被提取到独立的 CSS 文件中
|
|
6182
|
-
* - 路由检测:自动检测组件是否使用路由,用于依赖注入
|
|
6183
|
-
* - 作用域样式:为 Scoped CSS 生成唯一的作用域ID
|
|
6184
|
-
*
|
|
6185
|
-
* @see {@link SFCCompilationResult} SFC 编译结果类型
|
|
6186
|
-
* @see {@link ScriptCompilationResult} Script 编译结果类型
|
|
6187
|
-
*/
|
|
6188
6414
|
resolveMainResult(ir, gen, ctxData) {
|
|
6189
6415
|
const { fileId, filename, scriptData, styleData, inputType } = ctxData;
|
|
6190
6416
|
const base = {
|
|
@@ -6199,7 +6425,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6199
6425
|
fileInfo: {
|
|
6200
6426
|
jsx: {
|
|
6201
6427
|
file: `${file}x`,
|
|
6202
|
-
// 'xxx.ts' + 'x' => 'xxx.tsx'
|
|
6203
6428
|
lang
|
|
6204
6429
|
},
|
|
6205
6430
|
css: {
|
|
@@ -6216,11 +6441,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6216
6441
|
...base
|
|
6217
6442
|
};
|
|
6218
6443
|
}
|
|
6219
|
-
/**
|
|
6220
|
-
* 处理 Style 文件的编译结果
|
|
6221
|
-
* @param data style 文件解析结果
|
|
6222
|
-
* @param ctxData 上下文数据
|
|
6223
|
-
*/
|
|
6224
6444
|
resolveStyleResult(data, ctxData) {
|
|
6225
6445
|
const { fileId, filename } = ctxData;
|
|
6226
6446
|
const { lang, content = "" } = data.style.source;
|
|
@@ -6253,13 +6473,12 @@ function formattDuration(n) {
|
|
|
6253
6473
|
}
|
|
6254
6474
|
|
|
6255
6475
|
// src/compiler/shared/file-compiler/index.ts
|
|
6256
|
-
import
|
|
6257
|
-
import kleur6 from "kleur";
|
|
6476
|
+
import kleur8 from "kleur";
|
|
6258
6477
|
import ora2 from "ora";
|
|
6259
6478
|
|
|
6260
6479
|
// src/compiler/shared/file-compiler/asset-manager.ts
|
|
6261
|
-
import
|
|
6262
|
-
import
|
|
6480
|
+
import fs3 from "fs";
|
|
6481
|
+
import path5 from "path";
|
|
6263
6482
|
var AssetManager = class {
|
|
6264
6483
|
constructor(fileCompiler, cleanupManager) {
|
|
6265
6484
|
this.fileCompiler = fileCompiler;
|
|
@@ -6267,19 +6486,21 @@ var AssetManager = class {
|
|
|
6267
6486
|
}
|
|
6268
6487
|
// 需要经过管线编译处理的文件类型
|
|
6269
6488
|
pipelineFiles = [".js", ".ts", ".less", ".scss", ".sass"];
|
|
6489
|
+
skippedCount = 0;
|
|
6270
6490
|
/**
|
|
6271
6491
|
* 运行资源文件处理管线
|
|
6272
6492
|
*/
|
|
6273
6493
|
async runAssetPipeline() {
|
|
6494
|
+
const { options } = this.fileCompiler;
|
|
6274
6495
|
const rootPath = this.fileCompiler.getProjectRoot();
|
|
6275
6496
|
const inputPath = this.fileCompiler.getInputPath();
|
|
6276
6497
|
const exclusions = this.fileCompiler.getIgnoreAssets();
|
|
6277
6498
|
const assetFiles = this.fileCompiler.scanFiles(rootPath, (p) => {
|
|
6278
6499
|
if (this.fileCompiler.shouldSkipPath(p)) return false;
|
|
6279
6500
|
const relativeToRoot = normalizePath(this.fileCompiler.relativePath(p));
|
|
6280
|
-
const filename =
|
|
6281
|
-
const ext =
|
|
6282
|
-
if (!
|
|
6501
|
+
const filename = path5.basename(p).toLowerCase();
|
|
6502
|
+
const ext = path5.extname(p).toLowerCase();
|
|
6503
|
+
if (!options.output?.ignoreAssets) {
|
|
6283
6504
|
const shouldExclude = Array.from(exclusions).some((pattern) => {
|
|
6284
6505
|
if (pattern.endsWith(".")) {
|
|
6285
6506
|
return filename.startsWith(pattern);
|
|
@@ -6289,34 +6510,28 @@ var AssetManager = class {
|
|
|
6289
6510
|
}
|
|
6290
6511
|
return relativeToRoot === pattern || filename === pattern;
|
|
6291
6512
|
});
|
|
6292
|
-
if (shouldExclude)
|
|
6293
|
-
return false;
|
|
6294
|
-
}
|
|
6513
|
+
if (shouldExclude) return false;
|
|
6295
6514
|
} else if (exclusions.has(relativeToRoot) || exclusions.has(filename)) {
|
|
6296
6515
|
return false;
|
|
6297
6516
|
}
|
|
6298
6517
|
if (ext === ".vue") return false;
|
|
6299
|
-
const isInsideSrc = p.startsWith(inputPath +
|
|
6518
|
+
const isInsideSrc = p.startsWith(inputPath + path5.sep);
|
|
6300
6519
|
if (isInsideSrc && this.pipelineFiles.includes(ext)) {
|
|
6301
6520
|
return false;
|
|
6302
6521
|
}
|
|
6303
6522
|
return true;
|
|
6304
6523
|
});
|
|
6305
6524
|
const absFiles = new Set(assetFiles.map((f) => this.fileCompiler.getAbsPath(f)));
|
|
6306
|
-
const cache = await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6307
6525
|
await this.cleanupManager.cleanupOldOutput("copied" /* ASSET */, (u) => !absFiles.has(u.file));
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
for (const file of files) {
|
|
6316
|
-
const meta = await this.processAsset(file, cache);
|
|
6317
|
-
this.updateCache(file, meta, cache);
|
|
6318
|
-
}
|
|
6526
|
+
if (!assetFiles.length) return 0;
|
|
6527
|
+
const cache = await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6528
|
+
const copied = await Promise.all(
|
|
6529
|
+
assetFiles.map((file) => {
|
|
6530
|
+
return this.processAsset(file, cache);
|
|
6531
|
+
})
|
|
6532
|
+
);
|
|
6319
6533
|
await this.fileCompiler.saveCache(cache);
|
|
6534
|
+
return copied.filter(Boolean).length;
|
|
6320
6535
|
}
|
|
6321
6536
|
/**
|
|
6322
6537
|
* Process single asset file, compare with cache and decide whether to copy.
|
|
@@ -6330,11 +6545,16 @@ var AssetManager = class {
|
|
|
6330
6545
|
const cache = (this.fileCompiler.getIsCache() ? existingCache : void 0) || await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6331
6546
|
const record = cache.target.find((f) => f.file === absPath);
|
|
6332
6547
|
if (record && this.fileCompiler.compareFileMeta(record, fileMeta)) {
|
|
6333
|
-
|
|
6548
|
+
this.skippedCount++;
|
|
6549
|
+
return;
|
|
6334
6550
|
}
|
|
6335
6551
|
const outputPath = this.fileCompiler.resolveOutputPath(absPath);
|
|
6336
|
-
await
|
|
6337
|
-
await
|
|
6552
|
+
await fs3.promises.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
6553
|
+
await fs3.promises.copyFile(absPath, outputPath);
|
|
6554
|
+
this.updateCache(absPath, fileMeta, cache);
|
|
6555
|
+
if (this.fileCompiler.getIsCache() && !existingCache) {
|
|
6556
|
+
await this.fileCompiler.saveCache(cache);
|
|
6557
|
+
}
|
|
6338
6558
|
return fileMeta;
|
|
6339
6559
|
}
|
|
6340
6560
|
/**
|
|
@@ -6349,6 +6569,18 @@ var AssetManager = class {
|
|
|
6349
6569
|
cache.target.push(newData);
|
|
6350
6570
|
}
|
|
6351
6571
|
}
|
|
6572
|
+
/**
|
|
6573
|
+
* 获取跳过的文件数量
|
|
6574
|
+
*/
|
|
6575
|
+
getSkippedCount() {
|
|
6576
|
+
return this.skippedCount;
|
|
6577
|
+
}
|
|
6578
|
+
/**
|
|
6579
|
+
* 重置跳过的文件数量
|
|
6580
|
+
*/
|
|
6581
|
+
resetSkippedCount() {
|
|
6582
|
+
this.skippedCount = 0;
|
|
6583
|
+
}
|
|
6352
6584
|
};
|
|
6353
6585
|
|
|
6354
6586
|
// src/compiler/shared/file-compiler/cache-manager.ts
|
|
@@ -6356,12 +6588,12 @@ var CacheManager = class {
|
|
|
6356
6588
|
constructor(fileCompiler) {
|
|
6357
6589
|
this.fileCompiler = fileCompiler;
|
|
6358
6590
|
}
|
|
6591
|
+
pendingUpdates = /* @__PURE__ */ new Map();
|
|
6359
6592
|
/**
|
|
6360
|
-
*
|
|
6593
|
+
* 批量更新缓存记录
|
|
6361
6594
|
*/
|
|
6362
6595
|
async updateCacheIncrementally(unit, key) {
|
|
6363
6596
|
if (!this.fileCompiler.getIsCache()) return;
|
|
6364
|
-
const cache = await this.fileCompiler.loadCache(key);
|
|
6365
6597
|
const meta = { ...unit };
|
|
6366
6598
|
delete meta.source;
|
|
6367
6599
|
if (key === "sfc" /* SFC */) {
|
|
@@ -6372,8 +6604,26 @@ var CacheManager = class {
|
|
|
6372
6604
|
} else if (key === "style" /* STYLE */) {
|
|
6373
6605
|
delete meta.output?.style.code;
|
|
6374
6606
|
}
|
|
6375
|
-
this.
|
|
6607
|
+
if (!this.pendingUpdates.has(key)) {
|
|
6608
|
+
this.pendingUpdates.set(key, []);
|
|
6609
|
+
}
|
|
6610
|
+
this.pendingUpdates.get(key).push({ unit, meta });
|
|
6611
|
+
}
|
|
6612
|
+
/**
|
|
6613
|
+
* 批量保存缓存
|
|
6614
|
+
*/
|
|
6615
|
+
async flushCache(key) {
|
|
6616
|
+
if (!this.fileCompiler.getIsCache() || !this.pendingUpdates.has(key)) {
|
|
6617
|
+
return;
|
|
6618
|
+
}
|
|
6619
|
+
const updates = this.pendingUpdates.get(key);
|
|
6620
|
+
if (updates.length === 0) return;
|
|
6621
|
+
const cache = await this.fileCompiler.loadCache(key);
|
|
6622
|
+
for (const { unit, meta } of updates) {
|
|
6623
|
+
this.updateCache(unit.file, meta, cache);
|
|
6624
|
+
}
|
|
6376
6625
|
await this.fileCompiler.saveCache(cache);
|
|
6626
|
+
this.pendingUpdates.set(key, []);
|
|
6377
6627
|
}
|
|
6378
6628
|
/**
|
|
6379
6629
|
* 更新缓存
|
|
@@ -6389,7 +6639,7 @@ var CacheManager = class {
|
|
|
6389
6639
|
};
|
|
6390
6640
|
|
|
6391
6641
|
// src/compiler/shared/file-compiler/cleanup-manager.ts
|
|
6392
|
-
import
|
|
6642
|
+
import path6 from "path";
|
|
6393
6643
|
var CleanupManager = class {
|
|
6394
6644
|
constructor(fileCompiler) {
|
|
6395
6645
|
this.fileCompiler = fileCompiler;
|
|
@@ -6404,7 +6654,7 @@ var CleanupManager = class {
|
|
|
6404
6654
|
(u) => u.file === absPath || // 加 path.sep 是因为假如删除了 src/components 文件夹,
|
|
6405
6655
|
// 为了防止误删名为 src/components-old 的文件夹,
|
|
6406
6656
|
// 所以必须确保路径后跟着一个分隔符,确保精准匹配子目录内容。
|
|
6407
|
-
u.file.startsWith(absPath +
|
|
6657
|
+
u.file.startsWith(absPath + path6.sep)
|
|
6408
6658
|
);
|
|
6409
6659
|
}
|
|
6410
6660
|
/**
|
|
@@ -6416,25 +6666,43 @@ var CleanupManager = class {
|
|
|
6416
6666
|
const toRemove = cache.target.filter(filter);
|
|
6417
6667
|
if (!toRemove.length) return;
|
|
6418
6668
|
const removeFn = async (m) => {
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6669
|
+
let meta;
|
|
6670
|
+
switch (key) {
|
|
6671
|
+
case "sfc" /* SFC */: {
|
|
6672
|
+
meta = m;
|
|
6673
|
+
const { jsx, css } = meta.output;
|
|
6674
|
+
await this.fileCompiler.removeOutputFile(jsx.file);
|
|
6675
|
+
if (css?.file) {
|
|
6676
|
+
await this.fileCompiler.removeOutputFile(css.file);
|
|
6677
|
+
}
|
|
6678
|
+
break;
|
|
6679
|
+
}
|
|
6680
|
+
case "script" /* SCRIPT */: {
|
|
6681
|
+
meta = m;
|
|
6682
|
+
await this.fileCompiler.removeOutputFile(meta.output.script.file);
|
|
6683
|
+
break;
|
|
6684
|
+
}
|
|
6685
|
+
case "style" /* STYLE */: {
|
|
6686
|
+
meta = m;
|
|
6687
|
+
await this.fileCompiler.removeOutputFile(meta.output.style.file);
|
|
6688
|
+
break;
|
|
6689
|
+
}
|
|
6690
|
+
// 静态资产缓存直接删除对应文件
|
|
6691
|
+
default: {
|
|
6692
|
+
await this.fileCompiler.removeOutputFile(m.file, true);
|
|
6693
|
+
break;
|
|
6426
6694
|
}
|
|
6427
|
-
} else if (key === "script" /* SCRIPT */ || key === "copied" /* ASSET */) {
|
|
6428
|
-
await this.fileCompiler.removeOutputFile(m.file, true);
|
|
6429
6695
|
}
|
|
6430
6696
|
};
|
|
6431
6697
|
await Promise.all(toRemove.map(removeFn));
|
|
6698
|
+
const removedFiles = new Set(toRemove.map((m) => m.file));
|
|
6699
|
+
cache.target = cache.target.filter((m) => !removedFiles.has(m.file));
|
|
6432
6700
|
await this.fileCompiler.saveCache(cache);
|
|
6433
6701
|
}
|
|
6434
6702
|
};
|
|
6435
6703
|
|
|
6436
6704
|
// src/compiler/shared/file-compiler/compilation-unit.ts
|
|
6437
|
-
import
|
|
6705
|
+
import kleur5 from "kleur";
|
|
6438
6706
|
var CompilationUnitProcessor = class {
|
|
6439
6707
|
constructor(fileCompiler) {
|
|
6440
6708
|
this.fileCompiler = fileCompiler;
|
|
@@ -6449,7 +6717,7 @@ var CompilationUnitProcessor = class {
|
|
|
6449
6717
|
this.resolveResult(result, unit, key);
|
|
6450
6718
|
} catch (err) {
|
|
6451
6719
|
console.info(
|
|
6452
|
-
|
|
6720
|
+
kleur5.red(`\u2716`),
|
|
6453
6721
|
`Failed to compile ${this.fileCompiler.relativePath(unit.file)}
|
|
6454
6722
|
`,
|
|
6455
6723
|
err
|
|
@@ -6530,20 +6798,16 @@ var CompilationUnitProcessor = class {
|
|
|
6530
6798
|
};
|
|
6531
6799
|
|
|
6532
6800
|
// src/compiler/shared/file-compiler/file-processor.ts
|
|
6533
|
-
import
|
|
6534
|
-
import
|
|
6801
|
+
import fs4 from "fs";
|
|
6802
|
+
import kleur6 from "kleur";
|
|
6803
|
+
import path7 from "path";
|
|
6535
6804
|
var FileProcessor = class {
|
|
6536
6805
|
constructor(fileCompiler, compilationUnitProcessor, cacheManager) {
|
|
6537
6806
|
this.fileCompiler = fileCompiler;
|
|
6538
6807
|
this.compilationUnitProcessor = compilationUnitProcessor;
|
|
6539
6808
|
this.cacheManager = cacheManager;
|
|
6540
6809
|
}
|
|
6541
|
-
|
|
6542
|
-
router: {
|
|
6543
|
-
name: PACKAGE_NAME.router,
|
|
6544
|
-
version: "^1.0.0"
|
|
6545
|
-
}
|
|
6546
|
-
};
|
|
6810
|
+
skippedCount = 0;
|
|
6547
6811
|
/**
|
|
6548
6812
|
* Process a single Vue file (this method is called directly in CLI Watch mode)
|
|
6549
6813
|
*/
|
|
@@ -6570,10 +6834,13 @@ var FileProcessor = class {
|
|
|
6570
6834
|
const { shouldCompile, hash } = await this.fileCompiler.checkCacheStatus(
|
|
6571
6835
|
fileMeta,
|
|
6572
6836
|
record,
|
|
6573
|
-
() =>
|
|
6837
|
+
() => fs4.promises.readFile(absPath, "utf-8")
|
|
6574
6838
|
);
|
|
6575
|
-
if (!shouldCompile)
|
|
6576
|
-
|
|
6839
|
+
if (!shouldCompile) {
|
|
6840
|
+
this.skippedCount++;
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6843
|
+
const source = await fs4.promises.readFile(absPath, "utf-8");
|
|
6577
6844
|
if (!source.trim()) return;
|
|
6578
6845
|
const initUnit = {
|
|
6579
6846
|
...fileMeta,
|
|
@@ -6589,46 +6856,108 @@ var FileProcessor = class {
|
|
|
6589
6856
|
await this.compilationUnitProcessor.saveCompiledFiles(processed, key);
|
|
6590
6857
|
if (key === "sfc" /* SFC */ || key === "script" /* SCRIPT */) {
|
|
6591
6858
|
if (processed?.hasRoute) {
|
|
6592
|
-
await this.
|
|
6593
|
-
await this.
|
|
6859
|
+
await this.addRouterToPackageJson();
|
|
6860
|
+
await this.updateEntryWithRouterProvider();
|
|
6594
6861
|
}
|
|
6595
6862
|
}
|
|
6596
6863
|
await this.cacheManager.updateCacheIncrementally(processed, key);
|
|
6597
6864
|
}
|
|
6598
6865
|
return processed;
|
|
6599
6866
|
}
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6867
|
+
/**
|
|
6868
|
+
* 对 package.json 注入路由依赖项
|
|
6869
|
+
*/
|
|
6870
|
+
async addRouterToPackageJson() {
|
|
6871
|
+
const { output } = this.fileCompiler.options;
|
|
6872
|
+
if (output?.bootstrapVite === false) {
|
|
6873
|
+
return;
|
|
6606
6874
|
}
|
|
6607
|
-
|
|
6608
|
-
|
|
6875
|
+
const { router } = RUNTIME_PACKAGES;
|
|
6876
|
+
const filePath = this.fileCompiler.getOutputPkgPath();
|
|
6877
|
+
const packageJson = await this.fileCompiler.resolvePackageFile(filePath);
|
|
6878
|
+
if (packageJson?.dependencies?.[router.name]) {
|
|
6879
|
+
return;
|
|
6880
|
+
}
|
|
6881
|
+
if (!packageJson.dependencies) {
|
|
6882
|
+
packageJson.dependencies = {};
|
|
6883
|
+
}
|
|
6884
|
+
packageJson.dependencies[router.name] = router.version;
|
|
6885
|
+
const newData = JSON.stringify(packageJson, null, 2);
|
|
6886
|
+
await this.fileCompiler.writeFileWithDir(filePath, newData, {
|
|
6887
|
+
lock: true
|
|
6888
|
+
});
|
|
6609
6889
|
}
|
|
6610
6890
|
/**
|
|
6611
|
-
*
|
|
6891
|
+
* 注入路由提供器到 React 应用的入口文件(如 main.tsx)
|
|
6612
6892
|
*/
|
|
6613
|
-
async
|
|
6614
|
-
const
|
|
6615
|
-
const
|
|
6616
|
-
const
|
|
6617
|
-
if (!
|
|
6893
|
+
async updateEntryWithRouterProvider() {
|
|
6894
|
+
const { exclude, output, router } = this.fileCompiler.options;
|
|
6895
|
+
const inputPath = this.fileCompiler.getInputPath();
|
|
6896
|
+
const outputPath = this.fileCompiler.getOuputPath(true);
|
|
6897
|
+
if (output?.bootstrapVite === false || router?.autoUpdateEntry === false || !router?.configFile) {
|
|
6618
6898
|
return;
|
|
6619
6899
|
}
|
|
6620
|
-
const
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6900
|
+
const getMainFile = async (filename) => {
|
|
6901
|
+
const filePath = path7.resolve(outputPath, filename);
|
|
6902
|
+
try {
|
|
6903
|
+
return { filePath, content: await fs4.promises.readFile(filePath, "utf-8") };
|
|
6904
|
+
} catch {
|
|
6905
|
+
return;
|
|
6906
|
+
}
|
|
6907
|
+
};
|
|
6908
|
+
const fileData = await getMainFile("main.tsx") || await getMainFile("main.jsx");
|
|
6909
|
+
if (!fileData) {
|
|
6910
|
+
console.warn(
|
|
6911
|
+
`${kleur6.yellow("\u26A0\uFE0F")} React application entry file not found, please confirm the filename is main.tsx or main.jsx?`
|
|
6912
|
+
);
|
|
6913
|
+
return;
|
|
6626
6914
|
}
|
|
6915
|
+
const prepareRouterEntry = () => {
|
|
6916
|
+
const importPath = this.fileCompiler.resolveRelativePath(inputPath, router.configFile);
|
|
6917
|
+
let content = fileData.content;
|
|
6918
|
+
if (exclude?.includes(router.configFile) || exclude?.includes(importPath)) {
|
|
6919
|
+
return content;
|
|
6920
|
+
}
|
|
6921
|
+
const routerModule = "RouterInstance";
|
|
6922
|
+
if (content.includes(routerModule) || content.includes(importPath)) {
|
|
6923
|
+
return content;
|
|
6924
|
+
}
|
|
6925
|
+
const routerImport = `import ${routerModule} from '${importPath}'`;
|
|
6926
|
+
if (content.includes("./App")) {
|
|
6927
|
+
const appImportRegex = /import\s+(?:App|.*)\s+from\s+['"]\.\/App\.(?:tsx|jsx)['"]/;
|
|
6928
|
+
content = content.replace(appImportRegex, routerImport);
|
|
6929
|
+
} else {
|
|
6930
|
+
const lastImportMatch = content.match(/import.*from.*\n/g);
|
|
6931
|
+
if (lastImportMatch) {
|
|
6932
|
+
const lastImport = lastImportMatch.pop();
|
|
6933
|
+
content = content.replace(lastImport, `${lastImport}
|
|
6934
|
+
${routerImport}`);
|
|
6935
|
+
} else {
|
|
6936
|
+
content = `${routerImport}${content}`;
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
const providerTag = `<${routerModule}.RouterProvider />`;
|
|
6940
|
+
fileData.content = content.replace(/<App\s*\/?>/g, providerTag);
|
|
6941
|
+
};
|
|
6942
|
+
prepareRouterEntry();
|
|
6943
|
+
await this.fileCompiler.writeFileWithDir(fileData.filePath, fileData.content);
|
|
6944
|
+
}
|
|
6945
|
+
/**
|
|
6946
|
+
* 获取跳过的文件数量
|
|
6947
|
+
*/
|
|
6948
|
+
getSkippedCount() {
|
|
6949
|
+
return this.skippedCount;
|
|
6950
|
+
}
|
|
6951
|
+
/**
|
|
6952
|
+
* 重置跳过的文件数量
|
|
6953
|
+
*/
|
|
6954
|
+
resetSkippedCount() {
|
|
6955
|
+
this.skippedCount = 0;
|
|
6627
6956
|
}
|
|
6628
6957
|
};
|
|
6629
6958
|
|
|
6630
6959
|
// src/compiler/shared/file-compiler/pipeline-manager.ts
|
|
6631
|
-
import
|
|
6960
|
+
import path8 from "path";
|
|
6632
6961
|
var PipelineManager = class {
|
|
6633
6962
|
constructor(fileCompiler, fileProcessor) {
|
|
6634
6963
|
this.fileCompiler = fileCompiler;
|
|
@@ -6663,7 +6992,7 @@ var PipelineManager = class {
|
|
|
6663
6992
|
const scriptExtRegex = /\.(js|ts)$/i;
|
|
6664
6993
|
const styleExtRegex = /\.(css|less|sass|scss)$/i;
|
|
6665
6994
|
const files = this.fileCompiler.scanFiles(inputPath, (p) => {
|
|
6666
|
-
const ext =
|
|
6995
|
+
const ext = path8.extname(p);
|
|
6667
6996
|
if (key === "sfc" /* SFC */) {
|
|
6668
6997
|
return ext === ".vue";
|
|
6669
6998
|
}
|
|
@@ -6675,28 +7004,21 @@ var PipelineManager = class {
|
|
|
6675
7004
|
}
|
|
6676
7005
|
return false;
|
|
6677
7006
|
});
|
|
6678
|
-
if (!files.length) return 0;
|
|
6679
|
-
const cache = await this.fileCompiler.loadCache(key);
|
|
6680
7007
|
const absFiles = new Set(files.map((f) => this.fileCompiler.getAbsPath(f)));
|
|
6681
7008
|
await this.cleanupManager.cleanupOldOutput(key, (c) => !absFiles.has(c.file));
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
} else {
|
|
6687
|
-
return this.fileProcessor.processFile(key, f, cache);
|
|
6688
|
-
}
|
|
6689
|
-
})
|
|
7009
|
+
if (!files.length) return 0;
|
|
7010
|
+
const cache = await this.fileCompiler.loadCache(key);
|
|
7011
|
+
const compiled = await Promise.all(
|
|
7012
|
+
files.map(async (f) => this.fileProcessor.processFile(key, f, cache))
|
|
6690
7013
|
);
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
return compiledCount;
|
|
7014
|
+
await this.fileCompiler.flushCache(key);
|
|
7015
|
+
return compiled.filter(Boolean).length;
|
|
6694
7016
|
}
|
|
6695
7017
|
/**
|
|
6696
7018
|
* 获取跳过的文件数量
|
|
6697
7019
|
*/
|
|
6698
7020
|
getSkippedCount() {
|
|
6699
|
-
return this.skippedCount;
|
|
7021
|
+
return this.skippedCount += this.fileProcessor.getSkippedCount();
|
|
6700
7022
|
}
|
|
6701
7023
|
/**
|
|
6702
7024
|
* 重置跳过的文件数量
|
|
@@ -6707,9 +7029,9 @@ var PipelineManager = class {
|
|
|
6707
7029
|
};
|
|
6708
7030
|
|
|
6709
7031
|
// src/compiler/shared/file-compiler/vite-bootstrapper.ts
|
|
6710
|
-
import { execSync
|
|
6711
|
-
import
|
|
6712
|
-
import
|
|
7032
|
+
import { execSync } from "child_process";
|
|
7033
|
+
import fs5 from "fs";
|
|
7034
|
+
import kleur7 from "kleur";
|
|
6713
7035
|
import ora from "ora";
|
|
6714
7036
|
var ViteBootstrapper = class {
|
|
6715
7037
|
constructor(fileCompiler, options) {
|
|
@@ -6717,52 +7039,50 @@ var ViteBootstrapper = class {
|
|
|
6717
7039
|
this.options = options;
|
|
6718
7040
|
}
|
|
6719
7041
|
spinner = ora();
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
version: "^1.0.0"
|
|
6724
|
-
}
|
|
7042
|
+
defaultConfig = {
|
|
7043
|
+
template: "react-ts",
|
|
7044
|
+
viteVersion: "@latest"
|
|
6725
7045
|
};
|
|
6726
7046
|
/**
|
|
6727
7047
|
* 检查是否需要初始化 Vite 环境
|
|
6728
7048
|
*/
|
|
6729
7049
|
isSingleFile() {
|
|
6730
7050
|
const inputPath = this.fileCompiler.getInputPath();
|
|
6731
|
-
if (!
|
|
7051
|
+
if (!fs5.existsSync(inputPath)) {
|
|
6732
7052
|
return false;
|
|
6733
7053
|
}
|
|
6734
|
-
const stat =
|
|
7054
|
+
const stat = fs5.statSync(inputPath);
|
|
6735
7055
|
return stat.isFile();
|
|
6736
7056
|
}
|
|
6737
7057
|
/**
|
|
6738
7058
|
* 利用 Vite 官方脚手架创建标准 React 环境
|
|
6739
7059
|
*/
|
|
6740
7060
|
async bootstrapIfNeeded() {
|
|
6741
|
-
const {
|
|
6742
|
-
|
|
7061
|
+
const { output } = this.options;
|
|
7062
|
+
const workspaceDir = this.fileCompiler.getWorkspaceDir();
|
|
7063
|
+
await fs5.promises.mkdir(workspaceDir, { recursive: true });
|
|
7064
|
+
if (output?.bootstrapVite === false) {
|
|
6743
7065
|
return false;
|
|
6744
7066
|
}
|
|
6745
7067
|
if (this.isSingleFile()) {
|
|
6746
|
-
console.info(
|
|
6747
|
-
return
|
|
7068
|
+
console.info("Skipping Vite initialization for single file compilation");
|
|
7069
|
+
return;
|
|
6748
7070
|
}
|
|
6749
|
-
const workspaceDir = this.fileCompiler.getWorkspaceDir();
|
|
6750
7071
|
const outputPkgPath = this.fileCompiler.getOutputPkgPath();
|
|
6751
|
-
if (
|
|
6752
|
-
return
|
|
7072
|
+
if (fs5.existsSync(outputPkgPath)) {
|
|
7073
|
+
return;
|
|
6753
7074
|
}
|
|
6754
|
-
this.spinner.start("Bootstrapping Vite React environment...");
|
|
6755
|
-
await fs4.promises.mkdir(workspaceDir, { recursive: true });
|
|
6756
7075
|
try {
|
|
6757
|
-
this.
|
|
7076
|
+
this.spinner.start("Bootstrapping Vite React environment...");
|
|
7077
|
+
await this.resolveViteCreateApp();
|
|
6758
7078
|
} catch (err) {
|
|
6759
|
-
this.spinner.stop();
|
|
6760
7079
|
console.error(
|
|
6761
|
-
|
|
6762
|
-
"Failed to bootstrap Vite environment. Please check npm/network
|
|
7080
|
+
kleur7.red("\u2716"),
|
|
7081
|
+
"Failed to bootstrap Vite environment. Please check npm/network.\n",
|
|
6763
7082
|
err
|
|
6764
7083
|
);
|
|
6765
|
-
|
|
7084
|
+
this.spinner.stop();
|
|
7085
|
+
return;
|
|
6766
7086
|
}
|
|
6767
7087
|
const removeVuePackages = (deps) => {
|
|
6768
7088
|
for (const name in deps) {
|
|
@@ -6779,103 +7099,134 @@ var ViteBootstrapper = class {
|
|
|
6779
7099
|
...vite
|
|
6780
7100
|
};
|
|
6781
7101
|
if (!isDev) {
|
|
6782
|
-
const { runtime } =
|
|
7102
|
+
const { runtime } = RUNTIME_PACKAGES;
|
|
6783
7103
|
deps[runtime.name] = runtime.version;
|
|
6784
7104
|
}
|
|
6785
7105
|
return deps;
|
|
6786
7106
|
};
|
|
6787
|
-
const
|
|
6788
|
-
const
|
|
6789
|
-
|
|
6790
|
-
const newDeps = resolveDeps(
|
|
6791
|
-
const newDevDeps = resolveDeps(
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
7107
|
+
const sourcePkgPath = this.fileCompiler.getRootPkgPath();
|
|
7108
|
+
const sourcePkg = await this.fileCompiler.resolvePackageFile(sourcePkgPath);
|
|
7109
|
+
let newPkg = await this.fileCompiler.resolvePackageFile(outputPkgPath);
|
|
7110
|
+
const newDeps = resolveDeps(sourcePkg.dependencies, newPkg.dependencies);
|
|
7111
|
+
const newDevDeps = resolveDeps(sourcePkg.devDependencies, newPkg.devDependencies, true);
|
|
7112
|
+
newPkg.dependencies = newDeps;
|
|
7113
|
+
newPkg.devDependencies = newDevDeps;
|
|
7114
|
+
newPkg = output?.packageJson?.(newPkg) || newPkg;
|
|
7115
|
+
await this.fileCompiler.writeFileWithDir(outputPkgPath, JSON.stringify(newPkg, null, 2));
|
|
6795
7116
|
this.spinner.succeed("Standard Vite React environment initialized");
|
|
6796
7117
|
return true;
|
|
6797
7118
|
}
|
|
6798
7119
|
/**
|
|
6799
7120
|
* 执行 vite 创建命令
|
|
6800
7121
|
*/
|
|
6801
|
-
resolveViteCreateApp() {
|
|
7122
|
+
async resolveViteCreateApp() {
|
|
6802
7123
|
const { output } = this.options;
|
|
6803
|
-
const
|
|
6804
|
-
const
|
|
7124
|
+
const { viteVersion, template: tmpl } = this.defaultConfig;
|
|
7125
|
+
const bootstrapVite = output?.bootstrapVite;
|
|
6805
7126
|
const outDirName = this.fileCompiler.getOutDirName();
|
|
6806
|
-
const
|
|
6807
|
-
|
|
7127
|
+
const configObject = typeof bootstrapVite === "object" ? bootstrapVite : null;
|
|
7128
|
+
const viteVer = configObject?.vite || viteVersion;
|
|
7129
|
+
const reactVer = configObject?.react;
|
|
7130
|
+
const template = configObject?.template || tmpl;
|
|
7131
|
+
const cmd = `npm create vite${viteVer} ${outDirName} -- --template ${template}`;
|
|
7132
|
+
execSync(cmd, {
|
|
6808
7133
|
cwd: this.fileCompiler.getWorkspaceDir(),
|
|
6809
7134
|
stdio: "ignore"
|
|
6810
7135
|
// 隐藏 create-vite 内部的输出日志,保持终端整洁
|
|
6811
7136
|
});
|
|
7137
|
+
if (reactVer) {
|
|
7138
|
+
await this.resolveReactVersion(reactVer);
|
|
7139
|
+
}
|
|
6812
7140
|
}
|
|
6813
|
-
};
|
|
6814
|
-
|
|
6815
|
-
// src/compiler/shared/file-compiler/index.ts
|
|
6816
|
-
var FileCompiler = class extends BaseCompiler {
|
|
6817
|
-
skippedCount = 0;
|
|
6818
|
-
spinner = ora2();
|
|
6819
|
-
// 管理器实例
|
|
6820
|
-
viteBootstrapper;
|
|
6821
|
-
pipelineManager;
|
|
6822
|
-
fileProcessor;
|
|
6823
|
-
compilationUnitProcessor;
|
|
6824
|
-
cacheManager;
|
|
6825
|
-
assetManager;
|
|
6826
|
-
cleanupManager;
|
|
6827
7141
|
/**
|
|
6828
|
-
*
|
|
6829
|
-
*
|
|
6830
|
-
* @param options - 编译器配置选项,继承自 BaseCompiler 的选项
|
|
6831
|
-
* 包括输入路径、输出配置、缓存设置、排除模式等
|
|
6832
|
-
* @see {@link CompilerOptions} 查看完整的选项说明
|
|
7142
|
+
* 处理 React 包版本
|
|
7143
|
+
* @param ver 版本号
|
|
6833
7144
|
*/
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
this.
|
|
7145
|
+
async resolveReactVersion(ver) {
|
|
7146
|
+
const outputPkgPath = this.fileCompiler.getOutputPkgPath();
|
|
7147
|
+
const curPkg = await this.fileCompiler.resolvePackageFile(outputPkgPath);
|
|
7148
|
+
const mainVer = Number(ver.split(".")[0]);
|
|
7149
|
+
const typeVer = !isNaN(mainVer) ? `^${mainVer.toString().replace(/@|\^|~|>=|>|/, "")}.0.0` : "^19.0.0";
|
|
7150
|
+
curPkg.dependencies.react = ver;
|
|
7151
|
+
curPkg.dependencies["react-dom"] = ver;
|
|
7152
|
+
curPkg.devDependencies["@types/react"] = typeVer;
|
|
7153
|
+
curPkg.devDependencies["@types/react-dom"] = typeVer;
|
|
7154
|
+
await this.fileCompiler.writeFileWithDir(outputPkgPath, JSON.stringify(curPkg, null, 2));
|
|
7155
|
+
return curPkg;
|
|
7156
|
+
}
|
|
7157
|
+
};
|
|
7158
|
+
|
|
7159
|
+
// src/compiler/shared/file-compiler/setup-manager.ts
|
|
7160
|
+
var SetupManager = class {
|
|
7161
|
+
constructor(getCompiler) {
|
|
7162
|
+
this.getCompiler = getCompiler;
|
|
7163
|
+
this.setup();
|
|
6837
7164
|
}
|
|
6838
7165
|
/**
|
|
6839
7166
|
* 初始化所有管理器实例
|
|
6840
7167
|
*
|
|
6841
|
-
*
|
|
7168
|
+
* !必须按照依赖关系顺序创建各个管理器:
|
|
6842
7169
|
* 1. 基础管理器(无依赖)
|
|
6843
7170
|
* 2. 依赖基础管理器的管理器
|
|
6844
7171
|
* 3. 依赖其他管理器的管理器
|
|
6845
|
-
*
|
|
6846
|
-
* @private
|
|
6847
7172
|
*/
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
this.
|
|
6851
|
-
this.
|
|
6852
|
-
this.
|
|
6853
|
-
this.viteBootstrapper = new ViteBootstrapper(this, this.options);
|
|
6854
|
-
this.pipelineManager = new PipelineManager(this, this.fileProcessor);
|
|
6855
|
-
this.assetManager = new AssetManager(this, this.cleanupManager);
|
|
7173
|
+
setup() {
|
|
7174
|
+
const fileCompiler = this.getCompiler();
|
|
7175
|
+
this.setupBaseManager(fileCompiler);
|
|
7176
|
+
this.setupManagedByBase(fileCompiler);
|
|
7177
|
+
this.setupCompositeManager(fileCompiler);
|
|
6856
7178
|
}
|
|
6857
7179
|
/**
|
|
6858
|
-
*
|
|
6859
|
-
*
|
|
6860
|
-
* 该方法执行以下步骤:
|
|
6861
|
-
* 1. 环境初始化:清理旧输出(如果禁用缓存)并初始化 Vite 项目环境
|
|
6862
|
-
* 2. Vue 文件编译:批量处理所有 .vue 文件
|
|
6863
|
-
* 3. Script 文件编译:批量处理所有 .js/.ts 文件
|
|
6864
|
-
* 4. 资源文件拷贝:处理剩余的非编译文件
|
|
6865
|
-
* 5. 统计输出:显示编译结果和性能统计
|
|
6866
|
-
*
|
|
6867
|
-
* @async
|
|
6868
|
-
* @throws {Error} 当编译过程中发生致命错误时抛出
|
|
6869
|
-
* @returns {Promise<void>}
|
|
7180
|
+
* 创建基础的管理器(无外部依赖)
|
|
6870
7181
|
*/
|
|
7182
|
+
setupBaseManager(fileCompiler) {
|
|
7183
|
+
fileCompiler.manager = {};
|
|
7184
|
+
const manager = fileCompiler.manager;
|
|
7185
|
+
manager.cacheManager = new CacheManager(fileCompiler);
|
|
7186
|
+
manager.cleanupManager = new CleanupManager(fileCompiler);
|
|
7187
|
+
}
|
|
7188
|
+
/**
|
|
7189
|
+
* 创建依赖基础管理器的管理器
|
|
7190
|
+
*/
|
|
7191
|
+
setupManagedByBase(fileCompiler) {
|
|
7192
|
+
const manager = fileCompiler.manager;
|
|
7193
|
+
manager.fileProcessor = new FileProcessor(
|
|
7194
|
+
fileCompiler,
|
|
7195
|
+
new CompilationUnitProcessor(fileCompiler),
|
|
7196
|
+
manager.cacheManager
|
|
7197
|
+
);
|
|
7198
|
+
}
|
|
7199
|
+
/**
|
|
7200
|
+
* 创建依赖其他管理器的管理器
|
|
7201
|
+
*/
|
|
7202
|
+
setupCompositeManager(fileCompiler) {
|
|
7203
|
+
const manager = fileCompiler.manager;
|
|
7204
|
+
manager.viteBootstrapper = new ViteBootstrapper(fileCompiler, fileCompiler.options);
|
|
7205
|
+
manager.pipelineManager = new PipelineManager(fileCompiler, manager.fileProcessor);
|
|
7206
|
+
manager.assetManager = new AssetManager(fileCompiler, manager.cleanupManager);
|
|
7207
|
+
}
|
|
7208
|
+
};
|
|
7209
|
+
|
|
7210
|
+
// src/compiler/shared/file-compiler/index.ts
|
|
7211
|
+
var FileCompiler = class extends BaseCompiler {
|
|
7212
|
+
manager;
|
|
7213
|
+
spinner = ora2();
|
|
7214
|
+
constructor(options = {}) {
|
|
7215
|
+
super(options);
|
|
7216
|
+
new SetupManager(() => this);
|
|
7217
|
+
}
|
|
7218
|
+
/** 执行完整的编译流程 */
|
|
6871
7219
|
async execute() {
|
|
6872
|
-
console.info("\n\n",
|
|
7220
|
+
console.info("\n\n", kleur8.magenta(`${kleur8.bold("VUREACT")} v${this.version}`), "\n");
|
|
6873
7221
|
const startTime = performance.now();
|
|
6874
|
-
|
|
6875
|
-
await
|
|
6876
|
-
}
|
|
6877
|
-
await this.viteBootstrapper.bootstrapIfNeeded();
|
|
7222
|
+
const rmWorkspace = async () => {
|
|
7223
|
+
await this.rmFile(this.getWorkspaceDir());
|
|
7224
|
+
};
|
|
6878
7225
|
try {
|
|
7226
|
+
if (!this.getIsCache()) {
|
|
7227
|
+
await rmWorkspace();
|
|
7228
|
+
}
|
|
7229
|
+
await this.manager.viteBootstrapper.bootstrapIfNeeded();
|
|
6879
7230
|
const sfcCount = await this.runPipelineWithSpinner("sfc" /* SFC */);
|
|
6880
7231
|
const scriptCount = await this.runPipelineWithSpinner("script" /* SCRIPT */);
|
|
6881
7232
|
const styleCount = await this.runPipelineWithSpinner("style" /* STYLE */);
|
|
@@ -6886,35 +7237,73 @@ var FileCompiler = class extends BaseCompiler {
|
|
|
6886
7237
|
this.showCompileStats(endTime, sfcCount, scriptCount, styleCount, assetCount);
|
|
6887
7238
|
} catch (error) {
|
|
6888
7239
|
const endTime = calcElapsedTime(startTime);
|
|
6889
|
-
|
|
7240
|
+
await rmWorkspace();
|
|
7241
|
+
console.error(kleur8.red("\u2716"), `Build failed in ${endTime}`);
|
|
6890
7242
|
console.error(error);
|
|
7243
|
+
process.exit(-1);
|
|
7244
|
+
} finally {
|
|
7245
|
+
this.spinner.stop();
|
|
7246
|
+
this.resetSkippedCount();
|
|
6891
7247
|
}
|
|
6892
7248
|
}
|
|
6893
|
-
/**
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
7249
|
+
/** 处理单个 Vue 单文件组件(SFC) */
|
|
7250
|
+
async processSFC(filePath, existingCache) {
|
|
7251
|
+
return this.manager.fileProcessor.processSFC(filePath, existingCache);
|
|
7252
|
+
}
|
|
7253
|
+
/** 处理单个 JavaScript/TypeScript 脚本文件 */
|
|
7254
|
+
async processScript(filePath, existingCache) {
|
|
7255
|
+
return this.manager.fileProcessor.processScript(filePath, existingCache);
|
|
7256
|
+
}
|
|
7257
|
+
/** 处理单个 CSS/LESS/SCSS 样式文件 */
|
|
7258
|
+
async processStyle(filePath, existingCache) {
|
|
7259
|
+
return this.manager.fileProcessor.processStyle(filePath, existingCache);
|
|
7260
|
+
}
|
|
7261
|
+
/** 处理单个文件(Vue 或 Script) */
|
|
7262
|
+
async processFile(key, filePath, existingCache) {
|
|
7263
|
+
if (key === "sfc" /* SFC */) {
|
|
7264
|
+
return this.manager.fileProcessor.processFile(key, filePath, existingCache);
|
|
7265
|
+
} else if (key === "script" /* SCRIPT */) {
|
|
7266
|
+
return this.manager.fileProcessor.processFile(
|
|
7267
|
+
key,
|
|
7268
|
+
filePath,
|
|
7269
|
+
existingCache
|
|
7270
|
+
);
|
|
7271
|
+
}
|
|
7272
|
+
return this.manager.fileProcessor.processFile(
|
|
7273
|
+
key,
|
|
7274
|
+
filePath,
|
|
7275
|
+
existingCache
|
|
7276
|
+
);
|
|
7277
|
+
}
|
|
7278
|
+
/** 处理单个资源文件 */
|
|
7279
|
+
async processAsset(filePath, existingCache) {
|
|
7280
|
+
return this.manager.assetManager.processAsset(filePath, existingCache);
|
|
7281
|
+
}
|
|
7282
|
+
/** 批量保存缓存 */
|
|
7283
|
+
async flushCache(key) {
|
|
7284
|
+
await this.manager.cacheManager.flushCache(key);
|
|
7285
|
+
}
|
|
7286
|
+
/** 删除指定路径对应的输出文件和缓存 */
|
|
7287
|
+
async removeOutputPath(targetPath, type) {
|
|
7288
|
+
return await this.manager.cleanupManager.removeOutputPath(targetPath, type);
|
|
7289
|
+
}
|
|
6901
7290
|
async runPipelineWithSpinner(name) {
|
|
6902
7291
|
const options = {
|
|
6903
7292
|
["sfc" /* SFC */]: {
|
|
6904
7293
|
text: "Compiling Vue files...",
|
|
6905
|
-
pipeline: () => this.pipelineManager.runSfcPipeline()
|
|
7294
|
+
pipeline: () => this.manager.pipelineManager.runSfcPipeline()
|
|
6906
7295
|
},
|
|
6907
7296
|
["script" /* SCRIPT */]: {
|
|
6908
7297
|
text: "Compiling script files...",
|
|
6909
|
-
pipeline: () => this.pipelineManager.runScriptPipeline()
|
|
7298
|
+
pipeline: () => this.manager.pipelineManager.runScriptPipeline()
|
|
6910
7299
|
},
|
|
6911
7300
|
["style" /* STYLE */]: {
|
|
6912
7301
|
text: "Compiling style files...",
|
|
6913
|
-
pipeline: () => this.pipelineManager.runStylePipeline()
|
|
7302
|
+
pipeline: () => this.manager.pipelineManager.runStylePipeline()
|
|
6914
7303
|
},
|
|
6915
7304
|
["copied" /* ASSET */]: {
|
|
6916
7305
|
text: "Copying assets...",
|
|
6917
|
-
pipeline: () => this.assetManager.runAssetPipeline()
|
|
7306
|
+
pipeline: () => this.manager.assetManager.runAssetPipeline()
|
|
6918
7307
|
}
|
|
6919
7308
|
};
|
|
6920
7309
|
const { text, pipeline } = options[name];
|
|
@@ -6927,166 +7316,36 @@ var FileCompiler = class extends BaseCompiler {
|
|
|
6927
7316
|
this.spinner.stop();
|
|
6928
7317
|
}
|
|
6929
7318
|
}
|
|
6930
|
-
/**
|
|
6931
|
-
* 处理单个 Vue 单文件组件(SFC)
|
|
6932
|
-
*
|
|
6933
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6934
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6935
|
-
*
|
|
6936
|
-
* @async
|
|
6937
|
-
* @param filePath - Vue 文件的绝对路径
|
|
6938
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6939
|
-
* @returns {Promise<SFCUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6940
|
-
* @see {@link FileProcessor.processSFC}
|
|
6941
|
-
*/
|
|
6942
|
-
async processSFC(filePath, existingCache) {
|
|
6943
|
-
return this.fileProcessor.processSFC(filePath, existingCache);
|
|
6944
|
-
}
|
|
6945
|
-
/**
|
|
6946
|
-
* 处理单个 JavaScript/TypeScript 脚本文件
|
|
6947
|
-
*
|
|
6948
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6949
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6950
|
-
*
|
|
6951
|
-
* @async
|
|
6952
|
-
* @param filePath - 脚本文件的绝对路径
|
|
6953
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6954
|
-
* @returns {Promise<ScriptUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6955
|
-
* @see {@link FileProcessor.processScript}
|
|
6956
|
-
*/
|
|
6957
|
-
async processScript(filePath, existingCache) {
|
|
6958
|
-
return this.fileProcessor.processScript(filePath, existingCache);
|
|
6959
|
-
}
|
|
6960
|
-
/**
|
|
6961
|
-
* 处理单个 CSS/LESS/SCSS 样式文件
|
|
6962
|
-
*
|
|
6963
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6964
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6965
|
-
*
|
|
6966
|
-
* @async
|
|
6967
|
-
* @param filePath - style 文件的绝对路径
|
|
6968
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6969
|
-
* @returns {Promise<ScriptUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6970
|
-
* @see {@link FileProcessor.processStyle}
|
|
6971
|
-
*/
|
|
6972
|
-
async processStyle(filePath, existingCache) {
|
|
6973
|
-
return this.fileProcessor.processStyle(filePath, existingCache);
|
|
6974
|
-
}
|
|
6975
|
-
/**
|
|
6976
|
-
* 处理单个文件(Vue 或 Script)
|
|
6977
|
-
*
|
|
6978
|
-
* 通用的文件处理方法,根据 CacheKey 类型自动选择处理逻辑。
|
|
6979
|
-
* 主要用于内部调用和统一的文件处理接口。
|
|
6980
|
-
*
|
|
6981
|
-
* @async
|
|
6982
|
-
* @param key - 文件类型标识(SFC 或 SCRIPT)
|
|
6983
|
-
* @param filePath - 文件的绝对路径
|
|
6984
|
-
* @param existingCache - 可选的预加载缓存对象
|
|
6985
|
-
* @returns {Promise<SFCUnit | ScriptUnit | undefined>} 编译单元对象
|
|
6986
|
-
* @see {@link FileProcessor.processFile}
|
|
6987
|
-
*/
|
|
6988
|
-
async processFile(key, filePath, existingCache) {
|
|
6989
|
-
if (key === "sfc" /* SFC */) {
|
|
6990
|
-
return this.fileProcessor.processFile(key, filePath, existingCache);
|
|
6991
|
-
} else if (key === "script" /* SCRIPT */) {
|
|
6992
|
-
return this.fileProcessor.processFile(key, filePath, existingCache);
|
|
6993
|
-
}
|
|
6994
|
-
return this.fileProcessor.processFile(
|
|
6995
|
-
key,
|
|
6996
|
-
filePath,
|
|
6997
|
-
existingCache
|
|
6998
|
-
);
|
|
6999
|
-
}
|
|
7000
|
-
/**
|
|
7001
|
-
* 处理单个资源文件
|
|
7002
|
-
*
|
|
7003
|
-
* 比较文件与缓存,决定是否需要拷贝。
|
|
7004
|
-
* 资源文件包括图片、字体、样式文件等非编译文件。
|
|
7005
|
-
*
|
|
7006
|
-
* @async
|
|
7007
|
-
* @param filePath - 资源文件的绝对路径
|
|
7008
|
-
* @param existingCache - 可选的预加载缓存对象
|
|
7009
|
-
* @returns {Promise<FileCacheMeta>} 资源文件的缓存元数据
|
|
7010
|
-
* @see {@link AssetManager.processAsset}
|
|
7011
|
-
*/
|
|
7012
|
-
async processAsset(filePath, existingCache) {
|
|
7013
|
-
return this.assetManager.processAsset(filePath, existingCache);
|
|
7014
|
-
}
|
|
7015
|
-
/**
|
|
7016
|
-
* 删除指定路径对应的输出文件和缓存
|
|
7017
|
-
*
|
|
7018
|
-
* 当源文件被删除或重命名时,需要清理对应的输出文件。
|
|
7019
|
-
* 主要用于 watch 模式下的文件删除处理。
|
|
7020
|
-
*
|
|
7021
|
-
* @async
|
|
7022
|
-
* @param targetPath - 源代码的路径(文件或文件夹)
|
|
7023
|
-
* @param type - 清理类型,指定是 SFC、SCRIPT 还是 ASSET
|
|
7024
|
-
* @returns {Promise<void>}
|
|
7025
|
-
* @see {@link CleanupManager.removeOutputPath}
|
|
7026
|
-
*/
|
|
7027
|
-
async removeOutputPath(targetPath, type) {
|
|
7028
|
-
return this.cleanupManager.removeOutputPath(targetPath, type);
|
|
7029
|
-
}
|
|
7030
|
-
/**
|
|
7031
|
-
* 获取跳过的文件数量
|
|
7032
|
-
*
|
|
7033
|
-
* 在增量编译中,未变更的文件会被跳过。
|
|
7034
|
-
* 此方法返回当前编译会话中跳过的文件数量。
|
|
7035
|
-
*
|
|
7036
|
-
* @returns {number} 跳过的文件数量
|
|
7037
|
-
*/
|
|
7038
|
-
getSkippedCount() {
|
|
7039
|
-
return this.skippedCount;
|
|
7040
|
-
}
|
|
7041
|
-
/**
|
|
7042
|
-
* 重置跳过的文件数量
|
|
7043
|
-
*
|
|
7044
|
-
* 在每次新的编译会话开始时调用,重置计数器。
|
|
7045
|
-
*/
|
|
7046
|
-
resetSkippedCount() {
|
|
7047
|
-
this.skippedCount = 0;
|
|
7048
|
-
}
|
|
7049
|
-
/**
|
|
7050
|
-
* 显示编译统计信息
|
|
7051
|
-
*
|
|
7052
|
-
* 在编译完成后调用,显示以下信息:
|
|
7053
|
-
* 1. 编译耗时
|
|
7054
|
-
* 2. 输出目录
|
|
7055
|
-
* 3. 跳过的文件数量
|
|
7056
|
-
* 4. 处理的文件分类统计
|
|
7057
|
-
*
|
|
7058
|
-
* @private
|
|
7059
|
-
* @param endTime - 格式化后的编译耗时字符串
|
|
7060
|
-
* @param sfcCount - 处理的 Vue 文件数量
|
|
7061
|
-
* @param scriptCount - 处理的脚本文件数量
|
|
7062
|
-
* @param assetCount - 处理的资源文件数量
|
|
7063
|
-
*/
|
|
7064
7319
|
showCompileStats(endTime, sfcCount, scriptCount, styleCount, assetCount) {
|
|
7065
|
-
const dir = normalizePath(this.relativePath(this.getOuputPath()));
|
|
7066
7320
|
this.spinner.succeed(`Build completed in ${endTime}`);
|
|
7067
|
-
console.info(` Output directory: ${kleur6.dim(dir)}`);
|
|
7068
7321
|
console.info();
|
|
7069
|
-
this.skippedCount += this.pipelineManager.getSkippedCount();
|
|
7070
|
-
this.pipelineManager.resetSkippedCount();
|
|
7071
|
-
if (this.skippedCount) {
|
|
7072
|
-
console.info(kleur6.dim(`Skipped ${this.skippedCount} unchanged file(s)`));
|
|
7073
|
-
this.resetSkippedCount();
|
|
7074
|
-
}
|
|
7075
7322
|
if (sfcCount || scriptCount || styleCount || assetCount) {
|
|
7076
7323
|
const stats = [];
|
|
7077
7324
|
if (sfcCount) stats.push(`${sfcCount} SFC(s)`);
|
|
7078
7325
|
if (scriptCount) stats.push(`${scriptCount} script(s)`);
|
|
7079
7326
|
if (styleCount) stats.push(`${styleCount} style(s)`);
|
|
7080
7327
|
if (assetCount) stats.push(`${assetCount} asset(s)`);
|
|
7081
|
-
|
|
7328
|
+
this.spinner.succeed(`Processed: ${stats.join(", ")}`);
|
|
7329
|
+
}
|
|
7330
|
+
const skippedCount = this.manager.pipelineManager.getSkippedCount() + this.manager.assetManager.getSkippedCount();
|
|
7331
|
+
if (skippedCount) {
|
|
7332
|
+
console.info(kleur8.gray(`\u21B7 Cached: ${kleur8.white(skippedCount)} unchanged file(s)`));
|
|
7333
|
+
this.resetSkippedCount();
|
|
7082
7334
|
}
|
|
7335
|
+
const dir = normalizePath(this.relativePath(this.getOuputPath()));
|
|
7336
|
+
console.info();
|
|
7337
|
+
console.info(`\u{1F4E6} Output: ${dir}`);
|
|
7083
7338
|
console.info();
|
|
7084
7339
|
}
|
|
7340
|
+
resetSkippedCount() {
|
|
7341
|
+
this.manager.pipelineManager.resetSkippedCount();
|
|
7342
|
+
this.manager.assetManager.resetSkippedCount();
|
|
7343
|
+
}
|
|
7085
7344
|
};
|
|
7086
7345
|
|
|
7087
7346
|
// src/compiler/shared/define-config.ts
|
|
7088
|
-
function defineConfig(
|
|
7089
|
-
return
|
|
7347
|
+
function defineConfig(config) {
|
|
7348
|
+
return typeof config === "function" ? config() : config;
|
|
7090
7349
|
}
|
|
7091
7350
|
|
|
7092
7351
|
// src/compiler/index.ts
|