@tarojs/cli-convertor 3.6.18 → 3.6.19
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/bin/taro-convert +1 -1
- package/dist/index.js +533 -114
- package/dist/index.js.map +1 -1
- package/dist/util/astConvert.js +66 -3
- package/dist/util/astConvert.js.map +1 -1
- package/dist/util/global.js +7 -0
- package/dist/util/global.js.map +1 -0
- package/dist/util/index.js +311 -11
- package/dist/util/index.js.map +1 -1
- package/package.json +35 -9
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
// import { ProjectType } from './../../taro-plugin-mini-ci/src/BaseCi';
|
|
12
13
|
const template_1 = require("@babel/template");
|
|
13
14
|
const traverse_1 = require("@babel/traverse");
|
|
14
15
|
const t = require("@babel/types");
|
|
@@ -22,10 +23,11 @@ const unitTransform = require("postcss-taro-unit-transform");
|
|
|
22
23
|
const prettier = require("prettier");
|
|
23
24
|
const util_1 = require("./util");
|
|
24
25
|
const astConvert_1 = require("./util/astConvert");
|
|
26
|
+
const global_1 = require("./util/global");
|
|
25
27
|
const prettierJSConfig = {
|
|
26
28
|
semi: false,
|
|
27
29
|
singleQuote: true,
|
|
28
|
-
parser: 'babel'
|
|
30
|
+
parser: 'babel',
|
|
29
31
|
};
|
|
30
32
|
const babylonConfig = {
|
|
31
33
|
sourceType: 'module',
|
|
@@ -36,19 +38,18 @@ const babylonConfig = {
|
|
|
36
38
|
'asyncGenerators',
|
|
37
39
|
'objectRestSpread',
|
|
38
40
|
'decorators',
|
|
39
|
-
'dynamicImport'
|
|
40
|
-
]
|
|
41
|
+
'dynamicImport',
|
|
42
|
+
],
|
|
41
43
|
};
|
|
42
44
|
const OUTPUT_STYLE_EXTNAME = '.scss';
|
|
43
45
|
const WX_GLOBAL_FN = new Set(['getApp', 'getCurrentPages', 'requirePlugin', 'Behavior']);
|
|
44
46
|
function processStyleImports(content, processFn) {
|
|
45
|
-
|
|
46
|
-
const imports =
|
|
47
|
+
// 获取css中的引用样式文件路径集合
|
|
48
|
+
const imports = (0, util_1.getWxssImports)(content);
|
|
49
|
+
// 将引用的样式文件路径转换为相对路径,后缀名转换为.scss
|
|
47
50
|
const styleReg = new RegExp('.wxss');
|
|
48
51
|
content = content.replace(helper_1.CSS_IMPORT_REG, (m, _$1, $2) => {
|
|
49
52
|
if (styleReg.test($2)) {
|
|
50
|
-
style.push(m);
|
|
51
|
-
imports.push($2);
|
|
52
53
|
if (processFn) {
|
|
53
54
|
return processFn(m, $2);
|
|
54
55
|
}
|
|
@@ -61,33 +62,38 @@ function processStyleImports(content, processFn) {
|
|
|
61
62
|
});
|
|
62
63
|
return {
|
|
63
64
|
content,
|
|
64
|
-
|
|
65
|
-
imports
|
|
65
|
+
imports,
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
class Convertor {
|
|
69
|
-
constructor(root) {
|
|
69
|
+
constructor(root, isTsProject) {
|
|
70
70
|
this.wxsIncrementId = (0, util_1.incrementId)();
|
|
71
71
|
this.root = root;
|
|
72
72
|
this.convertRoot = path.join(this.root, 'taroConvert');
|
|
73
73
|
this.convertDir = path.join(this.convertRoot, 'src');
|
|
74
74
|
this.importsDir = path.join(this.convertDir, 'imports');
|
|
75
|
+
this.isTsProject = isTsProject;
|
|
76
|
+
if (isTsProject) {
|
|
77
|
+
this.miniprogramRoot = path.join(this.root, 'miniprogram');
|
|
78
|
+
}
|
|
75
79
|
this.fileTypes = {
|
|
76
80
|
TEMPL: '.wxml',
|
|
77
81
|
STYLE: '.wxss',
|
|
78
82
|
CONFIG: '.json',
|
|
79
|
-
SCRIPT: '.js'
|
|
83
|
+
SCRIPT: isTsProject ? '.ts' : '.js',
|
|
80
84
|
};
|
|
81
85
|
this.pages = new Set();
|
|
82
86
|
this.components = new Set();
|
|
83
87
|
this.hadBeenCopyedFiles = new Set();
|
|
84
88
|
this.hadBeenBuiltComponents = new Set();
|
|
85
89
|
this.hadBeenBuiltImports = new Set();
|
|
90
|
+
this.reportErroMsg = [];
|
|
86
91
|
this.init();
|
|
87
92
|
}
|
|
88
93
|
init() {
|
|
89
94
|
console.log(helper_1.chalk.green('开始代码转换...'));
|
|
90
95
|
this.initConvert();
|
|
96
|
+
this.getConvertConfig();
|
|
91
97
|
this.getApp();
|
|
92
98
|
this.getPages();
|
|
93
99
|
this.getSitemapLocation();
|
|
@@ -100,13 +106,22 @@ class Convertor {
|
|
|
100
106
|
else {
|
|
101
107
|
helper_1.fs.ensureDirSync(this.convertRoot);
|
|
102
108
|
}
|
|
109
|
+
this.convertSelfDefinedConfig();
|
|
110
|
+
// 创建.convert目录,存放转换中间数据
|
|
111
|
+
(0, util_1.generateDir)(path.join(this.convertRoot, '.convert'));
|
|
112
|
+
global_1.globals.logFilePath = path.join(this.convertRoot, '.convert', 'convert.log');
|
|
103
113
|
}
|
|
104
114
|
parseAst({ ast, sourceFilePath, outputFilePath, importStylePath, depComponents, imports = [] }) {
|
|
105
115
|
const scriptFiles = new Set();
|
|
106
116
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
107
117
|
const self = this;
|
|
118
|
+
// 转换后js页面的所有自定义标签
|
|
119
|
+
const scriptComponents = [];
|
|
108
120
|
let componentClassName;
|
|
109
121
|
let needInsertImportTaro = false;
|
|
122
|
+
let hasCacheOptionsRequired = false;
|
|
123
|
+
let hasDatasetRequired = false;
|
|
124
|
+
const set = new Set();
|
|
110
125
|
(0, traverse_1.default)(ast, {
|
|
111
126
|
Program: {
|
|
112
127
|
enter(astPath) {
|
|
@@ -121,10 +136,10 @@ class Convertor {
|
|
|
121
136
|
astPath.traverse({
|
|
122
137
|
JSXElement() {
|
|
123
138
|
isTaroComponent = true;
|
|
124
|
-
}
|
|
139
|
+
},
|
|
125
140
|
});
|
|
126
141
|
}
|
|
127
|
-
}
|
|
142
|
+
},
|
|
128
143
|
});
|
|
129
144
|
if (isTaroComponent) {
|
|
130
145
|
componentClassName = node.id.name;
|
|
@@ -141,10 +156,10 @@ class Convertor {
|
|
|
141
156
|
astPath.traverse({
|
|
142
157
|
JSXElement() {
|
|
143
158
|
isTaroComponent = true;
|
|
144
|
-
}
|
|
159
|
+
},
|
|
145
160
|
});
|
|
146
161
|
}
|
|
147
|
-
}
|
|
162
|
+
},
|
|
148
163
|
});
|
|
149
164
|
if (isTaroComponent) {
|
|
150
165
|
if (node.id === null) {
|
|
@@ -172,10 +187,10 @@ class Convertor {
|
|
|
172
187
|
astPath.traverse({
|
|
173
188
|
JSXElement() {
|
|
174
189
|
isTaroComponent = true;
|
|
175
|
-
}
|
|
190
|
+
},
|
|
176
191
|
});
|
|
177
192
|
}
|
|
178
|
-
}
|
|
193
|
+
},
|
|
179
194
|
});
|
|
180
195
|
if (isTaroComponent) {
|
|
181
196
|
componentClassName = declaration.id.name;
|
|
@@ -187,40 +202,211 @@ class Convertor {
|
|
|
187
202
|
const node = astPath.node;
|
|
188
203
|
const source = node.source;
|
|
189
204
|
const value = source.value;
|
|
190
|
-
(0, util_1.analyzeImportUrl)(self.root, sourceFilePath, scriptFiles, source, value);
|
|
205
|
+
(0, util_1.analyzeImportUrl)(self.root, sourceFilePath, scriptFiles, source, value, self.isTsProject);
|
|
191
206
|
},
|
|
192
207
|
CallExpression(astPath) {
|
|
208
|
+
(0, util_1.printToLogFile)(`解析CallExpression: ${astPath} ${(0, util_1.getLineBreak)()}`);
|
|
193
209
|
const node = astPath.node;
|
|
194
210
|
const calleePath = astPath.get('callee');
|
|
195
211
|
const callee = calleePath.node;
|
|
196
212
|
if (callee.type === 'Identifier') {
|
|
197
213
|
if (callee.name === 'require') {
|
|
198
214
|
const args = node.arguments;
|
|
215
|
+
if (args.length === 0) {
|
|
216
|
+
// require()
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!t.isStringLiteral(args[0])) {
|
|
220
|
+
// require 暂不支持动态导入,如require('aa' + aa),后续收录到报告中
|
|
221
|
+
throw new Error(`require暂不支持动态导入, filePath: ${sourceFilePath}, context: ${astPath}`);
|
|
222
|
+
}
|
|
199
223
|
const value = args[0].value;
|
|
200
|
-
(0, util_1.analyzeImportUrl)(self.root, sourceFilePath, scriptFiles, args[0], value);
|
|
224
|
+
(0, util_1.analyzeImportUrl)(self.root, sourceFilePath, scriptFiles, args[0], value, self.isTsProject);
|
|
201
225
|
}
|
|
202
226
|
else if (WX_GLOBAL_FN.has(callee.name)) {
|
|
203
227
|
calleePath.replaceWith(t.memberExpression(t.identifier('Taro'), callee));
|
|
204
228
|
needInsertImportTaro = true;
|
|
205
229
|
}
|
|
230
|
+
else if (callee.name === 'Page' || callee.name === 'Component' || callee.name === 'App') {
|
|
231
|
+
// 将 App() Page() Component() 改为 cacheOptions.setOptionsToCache() 的形式去初始化页面数据
|
|
232
|
+
const arg = astPath.get('arguments')[0];
|
|
233
|
+
const cacheOptionsAstNode = t.callExpression(t.memberExpression(t.identifier('cacheOptions'), t.identifier('setOptionsToCache')), [arg.node]);
|
|
234
|
+
astPath.replaceWith(cacheOptionsAstNode);
|
|
235
|
+
// 创建导入 cacheOptions 对象的 ast 节点
|
|
236
|
+
const requireCacheOptionsAst = t.variableDeclaration('const', [
|
|
237
|
+
t.variableDeclarator(t.objectPattern([
|
|
238
|
+
t.objectProperty(t.identifier('cacheOptions'), t.identifier('cacheOptions'), false, true),
|
|
239
|
+
]), t.callExpression(t.identifier('require'), [t.stringLiteral('@tarojs/with-weapp')])),
|
|
240
|
+
]);
|
|
241
|
+
// 若已经引入过 cacheOptions 则不在引入,防止重复引入问题
|
|
242
|
+
if (!hasCacheOptionsRequired) {
|
|
243
|
+
ast.program.body.unshift(requireCacheOptionsAst);
|
|
244
|
+
hasCacheOptionsRequired = true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
206
247
|
}
|
|
207
248
|
},
|
|
208
249
|
MemberExpression(astPath) {
|
|
209
250
|
const node = astPath.node;
|
|
210
251
|
const object = node.object;
|
|
252
|
+
const prettier = node.property;
|
|
211
253
|
if (t.isIdentifier(object) && object.name === 'wx') {
|
|
212
254
|
node.object = t.identifier('Taro');
|
|
213
255
|
needInsertImportTaro = true;
|
|
214
256
|
}
|
|
215
|
-
|
|
257
|
+
else if (t.isIdentifier(prettier) && prettier.name === 'dataset') {
|
|
258
|
+
node.object = t.callExpression(t.identifier('getTarget'), [object, t.identifier('Taro')]);
|
|
259
|
+
// 创建导入 cacheOptions 对象的 ast 节点
|
|
260
|
+
if (!hasDatasetRequired) {
|
|
261
|
+
const requireCacheOptionsAst = t.variableDeclaration('const', [
|
|
262
|
+
t.variableDeclarator(t.objectPattern([
|
|
263
|
+
t.objectProperty(t.identifier('getTarget'), t.identifier('getTarget'), false, true),
|
|
264
|
+
]), t.callExpression(t.identifier('require'), [t.stringLiteral('@tarojs/with-weapp')])),
|
|
265
|
+
]);
|
|
266
|
+
ast.program.body.unshift(requireCacheOptionsAst);
|
|
267
|
+
hasDatasetRequired = true;
|
|
268
|
+
needInsertImportTaro = true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
OptionalMemberExpression(astPath) {
|
|
273
|
+
const node = astPath.node;
|
|
274
|
+
const object = node.object;
|
|
275
|
+
const prettier = node.property;
|
|
276
|
+
if (t.isIdentifier(prettier) && prettier.name === 'dataset') {
|
|
277
|
+
node.object = t.callExpression(t.identifier('getTarget'), [object, t.identifier('Taro')]);
|
|
278
|
+
// 创建导入 getTarget 对象的 ast 节点, 并且防止重复引用
|
|
279
|
+
if (!hasDatasetRequired) {
|
|
280
|
+
const requireCacheOptionsAst = t.variableDeclaration('const', [
|
|
281
|
+
t.variableDeclarator(t.objectPattern([
|
|
282
|
+
t.objectProperty(t.identifier('getTarget'), t.identifier('getTarget'), false, true),
|
|
283
|
+
]), t.callExpression(t.identifier('require'), [t.stringLiteral('@tarojs/with-weapp')])),
|
|
284
|
+
]);
|
|
285
|
+
ast.program.body.unshift(requireCacheOptionsAst);
|
|
286
|
+
hasDatasetRequired = true;
|
|
287
|
+
needInsertImportTaro = true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
// 获取js界面所有用到的自定义标签,不重复
|
|
292
|
+
JSXElement(astPath) {
|
|
293
|
+
const openingElement = astPath.get('openingElement');
|
|
294
|
+
const jsxName = openingElement.get('name');
|
|
295
|
+
if (jsxName.isJSXIdentifier()) {
|
|
296
|
+
const componentName = jsxName.node.name;
|
|
297
|
+
if (!util_1.DEFAULT_Component_SET.has(componentName) && scriptComponents.indexOf(componentName) === -1) {
|
|
298
|
+
scriptComponents.push(componentName);
|
|
299
|
+
}
|
|
300
|
+
if (/^\S(\S)*Tmpl$/.test(componentName)) {
|
|
301
|
+
const templateImport = imports.find((tmplImport) => tmplImport.name === `${componentName}`);
|
|
302
|
+
const templateFuncs = templateImport === null || templateImport === void 0 ? void 0 : templateImport.funcs;
|
|
303
|
+
if (templateFuncs && templateFuncs.size > 0) {
|
|
304
|
+
const attributes = openingElement.node.attributes;
|
|
305
|
+
templateFuncs.forEach((templateFunc) => {
|
|
306
|
+
const memberExpression = t.memberExpression(t.thisExpression(), t.identifier(templateFunc));
|
|
307
|
+
const value = t.jsxExpressionContainer(memberExpression);
|
|
308
|
+
const name = t.jsxIdentifier(templateFunc);
|
|
309
|
+
// 传递的方法插入到Tmpl标签属性中
|
|
310
|
+
attributes.push(t.jsxAttribute(name, value));
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else if (componentName === 'Template') {
|
|
315
|
+
// 处理没被成功转换的模板, 如果被转换了就不会还是Template
|
|
316
|
+
const attrs = openingElement.get('attributes');
|
|
317
|
+
const is = attrs.find((attr) => t.isJSXAttribute(attr) &&
|
|
318
|
+
t.isJSXIdentifier(attr.get('name')) &&
|
|
319
|
+
t.isJSXAttribute(attr.node) &&
|
|
320
|
+
attr.node.name.name === 'is');
|
|
321
|
+
// 处理<template is=包含变量的情况(组件的动态名称)
|
|
322
|
+
if (is && t.isJSXAttribute(is.node)) {
|
|
323
|
+
const value = is.node.value;
|
|
324
|
+
if (value && t.isJSXExpressionContainer(value)) {
|
|
325
|
+
const expression = value.expression;
|
|
326
|
+
// 1、<template is={{var}}> 2、<template is="string{{var}}">
|
|
327
|
+
if (t.isIdentifier(expression) ||
|
|
328
|
+
(t.isBinaryExpression(expression) && expression.operator === '+')) {
|
|
329
|
+
// 加上map, template原名和新名字的映射
|
|
330
|
+
const componentMapList = [];
|
|
331
|
+
for (const order in imports) {
|
|
332
|
+
for (const key in imports[order]) {
|
|
333
|
+
if (key === 'tmplName') {
|
|
334
|
+
const tmplName = imports[order][key];
|
|
335
|
+
const tmplLastName = imports[order].name;
|
|
336
|
+
// imports去重可能会把map里的去掉, 所以要加回去
|
|
337
|
+
if (!scriptComponents.includes(tmplLastName)) {
|
|
338
|
+
scriptComponents.push(tmplLastName);
|
|
339
|
+
}
|
|
340
|
+
componentMapList.push(t.objectProperty(t.stringLiteral('' + tmplName), t.identifier(tmplLastName)));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const withWeappPath = astPath.findParent((p) => p.isClassDeclaration());
|
|
345
|
+
if (withWeappPath) {
|
|
346
|
+
const MapVariableDeclaration = t.variableDeclaration('const', [
|
|
347
|
+
t.variableDeclarator(t.identifier('ComponentMap'), t.objectExpression(componentMapList)),
|
|
348
|
+
]);
|
|
349
|
+
withWeappPath.insertBefore(MapVariableDeclaration);
|
|
350
|
+
}
|
|
351
|
+
// 加上用map给新标签赋值
|
|
352
|
+
const returnPath = astPath.findParent((p) => p.isReturnStatement());
|
|
353
|
+
if (returnPath) {
|
|
354
|
+
const ComponentNameVariableDeclaration = t.variableDeclaration('let', [
|
|
355
|
+
t.variableDeclarator(t.identifier('ComponentName'), t.memberExpression(t.identifier('ComponentMap'), expression, true)),
|
|
356
|
+
]);
|
|
357
|
+
returnPath.insertBefore(ComponentNameVariableDeclaration);
|
|
358
|
+
}
|
|
359
|
+
// 标签非Template的情况下不会加spread, 删除spread属性; 更改开闭合标签为ComponentName
|
|
360
|
+
const attributes = [];
|
|
361
|
+
const data = attrs.find((attr) => t.isJSXAttribute(attr) &&
|
|
362
|
+
t.isJSXIdentifier(attr.get('name')) &&
|
|
363
|
+
t.isJSXAttribute(attr.node) &&
|
|
364
|
+
attr.node.name.name === 'data');
|
|
365
|
+
if (data && t.isJSXAttribute(data.node)) {
|
|
366
|
+
attributes.push(data.node);
|
|
367
|
+
}
|
|
368
|
+
astPath.replaceWith(t.jSXElement(t.jSXOpeningElement(t.jSXIdentifier('ComponentName'), attributes), t.jSXClosingElement(t.jSXIdentifier('ComponentName')), [], true));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
// 处理this.data.xx = XXX 的情况,因为此表达式在taro暂不支持, 转为setData
|
|
376
|
+
AssignmentExpression(astPath) {
|
|
377
|
+
const node = astPath.node;
|
|
378
|
+
if (t.isMemberExpression(node.left) &&
|
|
379
|
+
t.isMemberExpression(node.left.object) &&
|
|
380
|
+
t.isThisExpression(node.left.object.object) &&
|
|
381
|
+
t.isIdentifier(node.left.object.property)) {
|
|
382
|
+
// 确认左边是this.data
|
|
383
|
+
if (node.left.object.property.name === 'data' && t.isIdentifier(node.left.property)) {
|
|
384
|
+
const lastName = node.left.property.name;
|
|
385
|
+
// 右边不能确定数据类型,所以直接存整个对象
|
|
386
|
+
const rightValue = node.right;
|
|
387
|
+
// 由于合并setData会导致打乱代码顺序, 影响代码逻辑, 所以每一句this.data.xx单独转成一句setData
|
|
388
|
+
const memberExp = t.memberExpression(t.thisExpression(), t.identifier('setData'));
|
|
389
|
+
const objExp = t.objectExpression([t.objectProperty(t.identifier(lastName), rightValue)]);
|
|
390
|
+
astPath.replaceWith(t.expressionStatement(t.callExpression(memberExp, [objExp])));
|
|
391
|
+
console.log(`转换 语法 this.data.xx=XX暂不支持,原地替换为setData()`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
},
|
|
216
395
|
});
|
|
217
396
|
},
|
|
218
397
|
exit(astPath) {
|
|
219
398
|
const bodyNode = astPath.get('body');
|
|
220
|
-
const lastImport = bodyNode.filter(p => p.isImportDeclaration()).pop();
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
399
|
+
const lastImport = bodyNode.filter((p) => p.isImportDeclaration() || (0, astConvert_1.isCommonjsImport)(p)).pop();
|
|
400
|
+
if (needInsertImportTaro && !(0, astConvert_1.hasTaroImport)(bodyNode)) {
|
|
401
|
+
// 根据模块类型(commonjs/es6) 确定导入taro模块的类型
|
|
402
|
+
if ((0, astConvert_1.isCommonjsModule)(ast.program.body)) {
|
|
403
|
+
astPath.node.body.unshift(t.variableDeclaration('const', [
|
|
404
|
+
t.variableDeclarator(t.identifier('Taro'), t.callExpression(t.identifier('require'), [t.stringLiteral('@tarojs/taro')])),
|
|
405
|
+
]));
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
astPath.node.body.unshift(t.importDeclaration([t.importDefaultSpecifier(t.identifier('Taro'))], t.stringLiteral('@tarojs/taro')));
|
|
409
|
+
}
|
|
224
410
|
}
|
|
225
411
|
astPath.traverse({
|
|
226
412
|
StringLiteral(astPath) {
|
|
@@ -237,7 +423,7 @@ class Convertor {
|
|
|
237
423
|
const imageRelativePath = (0, helper_1.promoteRelativePath)(path.relative(sourceFilePath, sourceImagePath));
|
|
238
424
|
const outputImagePath = self.getDistFilePath(sourceImagePath);
|
|
239
425
|
if (helper_1.fs.existsSync(sourceImagePath)) {
|
|
240
|
-
|
|
426
|
+
(0, util_1.copyFileToTaro)(sourceImagePath, outputImagePath);
|
|
241
427
|
(0, helper_1.printLog)("copy" /* processTypeEnum.COPY */, '图片', self.generateShowPath(outputImagePath));
|
|
242
428
|
}
|
|
243
429
|
else if (!t.isBinaryExpression(astPath.parent) || astPath.parent.operator !== '+') {
|
|
@@ -250,11 +436,18 @@ class Convertor {
|
|
|
250
436
|
astPath.replaceWith(t.jSXExpressionContainer(t.callExpression(t.identifier('require'), [t.stringLiteral(imageRelativePath)])));
|
|
251
437
|
}
|
|
252
438
|
}
|
|
253
|
-
}
|
|
439
|
+
},
|
|
254
440
|
});
|
|
255
441
|
if (lastImport) {
|
|
256
442
|
if (importStylePath) {
|
|
257
|
-
|
|
443
|
+
if ((0, astConvert_1.isCommonjsModule)(ast.program.body)) {
|
|
444
|
+
lastImport.insertAfter(t.callExpression(t.identifier('require'), [
|
|
445
|
+
t.stringLiteral((0, helper_1.promoteRelativePath)(path.relative(sourceFilePath, importStylePath))),
|
|
446
|
+
]));
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
lastImport.insertAfter(t.importDeclaration([], t.stringLiteral((0, helper_1.promoteRelativePath)(path.relative(sourceFilePath, importStylePath)))));
|
|
450
|
+
}
|
|
258
451
|
}
|
|
259
452
|
if (imports && imports.length) {
|
|
260
453
|
imports.forEach(({ name, ast, wxs }) => {
|
|
@@ -262,34 +455,172 @@ class Convertor {
|
|
|
262
455
|
if (componentClassName === importName) {
|
|
263
456
|
return;
|
|
264
457
|
}
|
|
265
|
-
const importPath = path.join(self.importsDir, importName + (wxs ? self.wxsIncrementId() : '') + '.js');
|
|
458
|
+
const importPath = path.join(self.importsDir, importName + (wxs ? self.wxsIncrementId() : '') + (self.isTsProject ? '.ts' : '.js'));
|
|
266
459
|
if (!self.hadBeenBuiltImports.has(importPath)) {
|
|
267
460
|
self.hadBeenBuiltImports.add(importPath);
|
|
268
461
|
self.writeFileToTaro(importPath, prettier.format((0, astConvert_1.generateMinimalEscapeCode)(ast), prettierJSConfig));
|
|
269
462
|
}
|
|
270
|
-
|
|
463
|
+
if (scriptComponents.indexOf(importName) !== -1 || (wxs && wxs === true)) {
|
|
464
|
+
lastImport.insertAfter((0, template_1.default)(`import ${importName} from '${(0, helper_1.promoteRelativePath)(path.relative(outputFilePath, importPath))}'`, babylonConfig)());
|
|
465
|
+
}
|
|
271
466
|
});
|
|
272
467
|
}
|
|
273
468
|
if (depComponents && depComponents.size) {
|
|
274
|
-
depComponents.forEach(componentObj => {
|
|
275
|
-
const name = (0, helper_1.pascalCase)(componentObj.name);
|
|
276
|
-
|
|
277
|
-
|
|
469
|
+
depComponents.forEach((componentObj) => {
|
|
470
|
+
const name = (0, helper_1.pascalCase)(componentObj.name.toLowerCase());
|
|
471
|
+
// 如果不是js页面用到的组件,无需导入
|
|
472
|
+
if (scriptComponents.indexOf(name) === -1) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
// 如果用到了,从scriptComponents中移除
|
|
476
|
+
const index = scriptComponents.indexOf(name);
|
|
477
|
+
scriptComponents.splice(index, 1);
|
|
478
|
+
let componentPath = componentObj.path;
|
|
479
|
+
if (componentPath.indexOf(self.root) !== -1) {
|
|
480
|
+
componentPath = path.relative(sourceFilePath, componentPath);
|
|
481
|
+
}
|
|
482
|
+
lastImport.insertAfter((0, template_1.default)(`import ${name} from '${(0, helper_1.promoteRelativePath)(componentPath)}'`, babylonConfig)());
|
|
278
483
|
});
|
|
279
484
|
}
|
|
280
485
|
}
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
});
|
|
489
|
+
// 遍历 ast ,将多次 const { xxx } = require('@tarojs/with-weapp') 引入压缩为一次引入
|
|
490
|
+
(0, traverse_1.default)(ast, {
|
|
491
|
+
VariableDeclaration(astPath) {
|
|
492
|
+
const { kind, declarations } = astPath.node;
|
|
493
|
+
let currentAstIsWithWeapp = false;
|
|
494
|
+
if (kind === 'const') {
|
|
495
|
+
declarations.forEach((declaration) => {
|
|
496
|
+
const { id, init } = declaration;
|
|
497
|
+
if (t.isObjectPattern(id) &&
|
|
498
|
+
t.isCallExpression(init) &&
|
|
499
|
+
t.isIdentifier(init.callee) &&
|
|
500
|
+
t.isStringLiteral(init.arguments[0])) {
|
|
501
|
+
const name = init.callee.name;
|
|
502
|
+
const args = init.arguments[0].value;
|
|
503
|
+
if (name === 'require' && args === '@tarojs/with-weapp') {
|
|
504
|
+
currentAstIsWithWeapp = true;
|
|
505
|
+
id.properties.forEach((propertie) => {
|
|
506
|
+
if (t.isObjectProperty(propertie) && t.isIdentifier(propertie.value)) {
|
|
507
|
+
set.add(propertie.value.name);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
});
|
|
281
513
|
}
|
|
282
|
-
|
|
514
|
+
if (currentAstIsWithWeapp) {
|
|
515
|
+
astPath.remove();
|
|
516
|
+
}
|
|
517
|
+
},
|
|
283
518
|
});
|
|
519
|
+
// 若 set 为空则不引入 @tarojs/with-weapp
|
|
520
|
+
if (set.size !== 0) {
|
|
521
|
+
if ((0, astConvert_1.isCommonjsModule)(ast.program.body)) {
|
|
522
|
+
const objectPropertyArray = [];
|
|
523
|
+
set.forEach((key) => {
|
|
524
|
+
if (key === 'withWeapp') {
|
|
525
|
+
objectPropertyArray.push(t.objectProperty(t.identifier('default'), t.identifier('withWeapp'), false, true));
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
objectPropertyArray.push(t.objectProperty(t.identifier(key), t.identifier(key), false, true));
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
const requireWithWeappAst = t.variableDeclaration('const', [
|
|
532
|
+
t.variableDeclarator(t.objectPattern(objectPropertyArray), t.callExpression(t.identifier('require'), [t.stringLiteral('@tarojs/with-weapp')])),
|
|
533
|
+
]);
|
|
534
|
+
ast.program.body.unshift(requireWithWeappAst);
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
const objectPropertyArray = [];
|
|
538
|
+
let hasWithWeapp = false;
|
|
539
|
+
set.forEach((key) => {
|
|
540
|
+
if (key === 'withWeapp') {
|
|
541
|
+
hasWithWeapp = true;
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
objectPropertyArray.push(t.importSpecifier(t.identifier(key), t.identifier(key)));
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
if (hasWithWeapp) {
|
|
548
|
+
objectPropertyArray.unshift(t.importDefaultSpecifier(t.identifier('withWeapp')));
|
|
549
|
+
}
|
|
550
|
+
const importWithWeapp = t.importDeclaration(objectPropertyArray, t.stringLiteral('@tarojs/with-weapp'));
|
|
551
|
+
ast.program.body.unshift(importWithWeapp);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
284
554
|
return {
|
|
285
555
|
ast,
|
|
286
|
-
scriptFiles
|
|
556
|
+
scriptFiles,
|
|
287
557
|
};
|
|
288
558
|
}
|
|
559
|
+
convertSelfDefinedConfig() {
|
|
560
|
+
// 搬运自定义的配置文件
|
|
561
|
+
const selfDefinedConfig = [];
|
|
562
|
+
// 目前只有tsconfig.json,还有的话继续加到array里
|
|
563
|
+
selfDefinedConfig[0] = `tsconfig${this.fileTypes.CONFIG}`;
|
|
564
|
+
for (const tempConfig of selfDefinedConfig) {
|
|
565
|
+
const tempConfigPath = path.join(this.root, tempConfig);
|
|
566
|
+
if (helper_1.fs.existsSync(tempConfig)) {
|
|
567
|
+
try {
|
|
568
|
+
const outputFilePath = path.join(this.convertRoot, tempConfig);
|
|
569
|
+
(0, util_1.copyFileToTaro)(tempConfigPath, outputFilePath);
|
|
570
|
+
}
|
|
571
|
+
catch (err) {
|
|
572
|
+
// 失败不退出,仅提示
|
|
573
|
+
console.log(helper_1.chalk.red(`tsconfig${this.fileTypes.CONFIG} 拷贝失败,请检查!`));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
getConvertConfig() {
|
|
579
|
+
// 处理convert.config.json,并存储到convertConfig中
|
|
580
|
+
const convertJsonPath = path.join(this.root, `convert.config${this.fileTypes.CONFIG}`);
|
|
581
|
+
if (helper_1.fs.existsSync(convertJsonPath)) {
|
|
582
|
+
try {
|
|
583
|
+
const convertJson = JSON.parse(String(helper_1.fs.readFileSync(convertJsonPath)));
|
|
584
|
+
this.convertConfig = Object.assign({}, convertJson);
|
|
585
|
+
this.convertConfig.external = (0, util_1.transRelToAbsPath)(convertJsonPath, this.convertConfig.external);
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
console.log(helper_1.chalk.red(`convert.config${this.fileTypes.CONFIG} 读取失败,请检查!`));
|
|
589
|
+
process.exit(1);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
289
593
|
getApp() {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
594
|
+
try {
|
|
595
|
+
const projectConfigPath = path.join(this.root, `project.config${this.fileTypes.CONFIG}`); // project.config.json 文件路径
|
|
596
|
+
// 解析 project.config.json 文件,获取 miniprogramRoot 字段的值
|
|
597
|
+
const projectConfig = JSON.parse(helper_1.fs.readFileSync(projectConfigPath, 'utf8'));
|
|
598
|
+
this.miniprogramRoot = projectConfig.miniprogramRoot;
|
|
599
|
+
}
|
|
600
|
+
catch (err) {
|
|
601
|
+
console.error('读取 project.config.json 文件失败:', err);
|
|
602
|
+
process.exit(1);
|
|
603
|
+
}
|
|
604
|
+
// 如果找到 miniprogramRoot字段,则以对应目录作为小程序逻辑目录
|
|
605
|
+
if (this.miniprogramRoot) {
|
|
606
|
+
this.root = path.resolve(this.miniprogramRoot);
|
|
607
|
+
}
|
|
608
|
+
if (this.isTsProject) {
|
|
609
|
+
this.entryJSPath = path.join(this.miniprogramRoot, `app${this.fileTypes.SCRIPT}`);
|
|
610
|
+
this.entryJSONPath = path.join(this.miniprogramRoot, `app${this.fileTypes.CONFIG}`);
|
|
611
|
+
this.entryStylePath = path.join(this.miniprogramRoot, `app${this.fileTypes.STYLE}`);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
this.entryJSPath = path.join(this.root, `app${this.fileTypes.SCRIPT}`);
|
|
615
|
+
this.entryJSONPath = path.join(this.root, `app${this.fileTypes.CONFIG}`);
|
|
616
|
+
this.entryStylePath = path.join(this.root, `app${this.fileTypes.STYLE}`);
|
|
617
|
+
}
|
|
618
|
+
// 如果在 miniprogramRoot 目录下找到 app.json 文件,则将入口文件和配置文件路径修改为对应的路径
|
|
619
|
+
if (this.miniprogramRoot && helper_1.fs.existsSync(path.join(this.root, `app${this.fileTypes.CONFIG}`))) {
|
|
620
|
+
this.entryJSPath = path.join(this.root, `app${this.fileTypes.SCRIPT}`);
|
|
621
|
+
this.entryJSONPath = path.join(this.root, `app${this.fileTypes.CONFIG}`);
|
|
622
|
+
this.entryStylePath = path.join(this.root, `app${this.fileTypes.STYLE}`);
|
|
623
|
+
}
|
|
293
624
|
try {
|
|
294
625
|
this.entryJSON = JSON.parse(String(helper_1.fs.readFileSync(this.entryJSONPath)));
|
|
295
626
|
const using = this.entryJSON.usingComponents;
|
|
@@ -298,7 +629,10 @@ class Convertor {
|
|
|
298
629
|
if (using[key].startsWith('plugin://'))
|
|
299
630
|
continue;
|
|
300
631
|
const componentPath = using[key];
|
|
301
|
-
|
|
632
|
+
// 非三方库的路径需要处理
|
|
633
|
+
if (!this.isThirdPartyLib(componentPath, this.root)) {
|
|
634
|
+
using[key] = path.join(this.root, componentPath);
|
|
635
|
+
}
|
|
302
636
|
}
|
|
303
637
|
this.entryUsingComponents = using;
|
|
304
638
|
delete this.entryJSON.usingComponents;
|
|
@@ -329,10 +663,10 @@ class Convertor {
|
|
|
329
663
|
if (!subPackages || !subPackages.length) {
|
|
330
664
|
return;
|
|
331
665
|
}
|
|
332
|
-
subPackages.forEach(item => {
|
|
666
|
+
subPackages.forEach((item) => {
|
|
333
667
|
if (item.pages && item.pages.length) {
|
|
334
668
|
const root = item.root;
|
|
335
|
-
item.pages.forEach(page => {
|
|
669
|
+
item.pages.forEach((page) => {
|
|
336
670
|
let pagePath = `${root}/${page}`;
|
|
337
671
|
pagePath = pagePath.replace(/\/{2,}/g, '/');
|
|
338
672
|
this.pages.add(pagePath);
|
|
@@ -347,7 +681,7 @@ class Convertor {
|
|
|
347
681
|
const sitemapFilePath = path.join(this.root, sitemapLocation);
|
|
348
682
|
if (helper_1.fs.existsSync(sitemapFilePath)) {
|
|
349
683
|
const outputFilePath = path.join(this.convertRoot, sitemapLocation);
|
|
350
|
-
|
|
684
|
+
(0, util_1.copyFileToTaro)(sitemapFilePath, outputFilePath);
|
|
351
685
|
}
|
|
352
686
|
}
|
|
353
687
|
}
|
|
@@ -356,32 +690,49 @@ class Convertor {
|
|
|
356
690
|
return;
|
|
357
691
|
}
|
|
358
692
|
if (files.size) {
|
|
359
|
-
files.forEach(file => {
|
|
693
|
+
files.forEach((file) => {
|
|
694
|
+
var _a, _b;
|
|
695
|
+
// 处理三方库引用,可在convert.config.json中nodePath字段自定义配置配置,默认node_modules
|
|
696
|
+
if (!path.isAbsolute(file)) {
|
|
697
|
+
(0, util_1.handleThirdPartyLib)(file, (_a = this.convertConfig) === null || _a === void 0 ? void 0 : _a.nodePath, this.root, this.convertRoot);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
360
700
|
if (!helper_1.fs.existsSync(file) || this.hadBeenCopyedFiles.has(file)) {
|
|
361
701
|
return;
|
|
362
702
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
703
|
+
// 处理不转换的目录,可在convert.config.json中external字段配置
|
|
704
|
+
const matchUnconvertDir = (0, util_1.getMatchUnconvertDir)(file, (_b = this.convertConfig) === null || _b === void 0 ? void 0 : _b.external);
|
|
705
|
+
if (matchUnconvertDir !== null) {
|
|
706
|
+
(0, util_1.handleUnconvertDir)(matchUnconvertDir, this.root, this.convertDir);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
try {
|
|
710
|
+
const code = helper_1.fs.readFileSync(file).toString();
|
|
711
|
+
let outputFilePath = file.replace(this.isTsProject ? this.miniprogramRoot : this.root, this.convertDir);
|
|
712
|
+
const extname = path.extname(outputFilePath);
|
|
713
|
+
if (/\.wxs/.test(extname)) {
|
|
714
|
+
outputFilePath += '.js';
|
|
715
|
+
}
|
|
716
|
+
const transformResult = (0, transformer_wx_1.default)({
|
|
717
|
+
code,
|
|
718
|
+
sourcePath: file,
|
|
719
|
+
isNormal: true,
|
|
720
|
+
isTyped: helper_1.REG_TYPESCRIPT.test(file),
|
|
721
|
+
});
|
|
722
|
+
const { ast, scriptFiles } = this.parseAst({
|
|
723
|
+
ast: transformResult.ast,
|
|
724
|
+
outputFilePath,
|
|
725
|
+
sourceFilePath: file,
|
|
726
|
+
});
|
|
727
|
+
const jsCode = (0, astConvert_1.generateMinimalEscapeCode)(ast);
|
|
728
|
+
this.writeFileToTaro(outputFilePath, prettier.format(jsCode, prettierJSConfig));
|
|
729
|
+
(0, helper_1.printLog)("copy" /* processTypeEnum.COPY */, 'JS 文件', this.generateShowPath(outputFilePath));
|
|
730
|
+
this.hadBeenCopyedFiles.add(file);
|
|
731
|
+
this.generateScriptFiles(scriptFiles);
|
|
732
|
+
}
|
|
733
|
+
catch (error) {
|
|
734
|
+
console.log(`转换文件${file}异常,errorMessage:${error}`);
|
|
368
735
|
}
|
|
369
|
-
const transformResult = (0, transformer_wx_1.default)({
|
|
370
|
-
code,
|
|
371
|
-
sourcePath: file,
|
|
372
|
-
isNormal: true,
|
|
373
|
-
isTyped: helper_1.REG_TYPESCRIPT.test(file)
|
|
374
|
-
});
|
|
375
|
-
const { ast, scriptFiles } = this.parseAst({
|
|
376
|
-
ast: transformResult.ast,
|
|
377
|
-
outputFilePath,
|
|
378
|
-
sourceFilePath: file
|
|
379
|
-
});
|
|
380
|
-
const jsCode = (0, astConvert_1.generateMinimalEscapeCode)(ast);
|
|
381
|
-
this.writeFileToTaro(outputFilePath, prettier.format(jsCode, prettierJSConfig));
|
|
382
|
-
(0, helper_1.printLog)("copy" /* processTypeEnum.COPY */, 'JS 文件', this.generateShowPath(outputFilePath));
|
|
383
|
-
this.hadBeenCopyedFiles.add(file);
|
|
384
|
-
this.generateScriptFiles(scriptFiles);
|
|
385
736
|
});
|
|
386
737
|
}
|
|
387
738
|
}
|
|
@@ -389,19 +740,19 @@ class Convertor {
|
|
|
389
740
|
helper_1.fs.ensureDirSync(path.dirname(dist));
|
|
390
741
|
helper_1.fs.writeFileSync(dist, code);
|
|
391
742
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (helper_1.fs.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
helper_1.fs.ensureDir(path.dirname(to));
|
|
399
|
-
return helper_1.fs.copySync(from, to, options);
|
|
743
|
+
// 自定义组件,如果组件文件命名为index,引入时可省略index这一层,解析时需加上
|
|
744
|
+
getComponentPath(component, extname) {
|
|
745
|
+
if (helper_1.fs.existsSync(component + extname))
|
|
746
|
+
return component + extname;
|
|
747
|
+
else
|
|
748
|
+
return component + '/index' + extname;
|
|
400
749
|
}
|
|
401
750
|
getDistFilePath(src, extname) {
|
|
402
751
|
if (!extname)
|
|
403
|
-
return src.replace(this.root, this.convertDir);
|
|
404
|
-
return src
|
|
752
|
+
return src.replace(this.isTsProject ? this.miniprogramRoot : this.root, this.convertDir);
|
|
753
|
+
return src
|
|
754
|
+
.replace(this.isTsProject ? this.miniprogramRoot : this.root, this.convertDir)
|
|
755
|
+
.replace(path.extname(src), extname);
|
|
405
756
|
}
|
|
406
757
|
getConfigFilePath(src) {
|
|
407
758
|
const { dir, name } = path.parse(src);
|
|
@@ -413,10 +764,7 @@ class Convertor {
|
|
|
413
764
|
this.writeFileToTaro(configSrc, prettier.format(code, prettierJSConfig));
|
|
414
765
|
}
|
|
415
766
|
generateShowPath(filePath) {
|
|
416
|
-
return filePath
|
|
417
|
-
.replace(path.join(this.root, '/'), '')
|
|
418
|
-
.split(path.sep)
|
|
419
|
-
.join('/');
|
|
767
|
+
return filePath.replace(path.join(this.root, '/'), '').split(path.sep).join('/');
|
|
420
768
|
}
|
|
421
769
|
formatFile(jsCode, template = '') {
|
|
422
770
|
let code = jsCode;
|
|
@@ -442,10 +790,12 @@ ${code}
|
|
|
442
790
|
const taroizeResult = taroize({
|
|
443
791
|
json: entryJSON,
|
|
444
792
|
script: entryJS,
|
|
793
|
+
scriptPath: this.entryJSPath,
|
|
445
794
|
path: this.root,
|
|
446
795
|
rootPath: this.root,
|
|
447
796
|
framework: this.framework,
|
|
448
|
-
isApp: true
|
|
797
|
+
isApp: true,
|
|
798
|
+
logFilePath: global_1.globals.logFilePath,
|
|
449
799
|
});
|
|
450
800
|
const { ast, scriptFiles } = this.parseAst({
|
|
451
801
|
ast: taroizeResult.ast,
|
|
@@ -454,7 +804,7 @@ ${code}
|
|
|
454
804
|
importStylePath: this.entryStyle
|
|
455
805
|
? this.entryStylePath.replace(path.extname(this.entryStylePath), OUTPUT_STYLE_EXTNAME)
|
|
456
806
|
: null,
|
|
457
|
-
isApp: true
|
|
807
|
+
isApp: true,
|
|
458
808
|
});
|
|
459
809
|
const jsCode = (0, astConvert_1.generateMinimalEscapeCode)(ast);
|
|
460
810
|
this.writeFileToTaro(entryDistJSPath, jsCode);
|
|
@@ -477,7 +827,7 @@ ${code}
|
|
|
477
827
|
const { list = [] } = tabBar;
|
|
478
828
|
const icons = new Set();
|
|
479
829
|
if (Array.isArray(list) && list.length) {
|
|
480
|
-
list.forEach(item => {
|
|
830
|
+
list.forEach((item) => {
|
|
481
831
|
if (typeof item.iconPath === 'string')
|
|
482
832
|
icons.add(item.iconPath);
|
|
483
833
|
if (typeof item.selectedIconPath === 'string')
|
|
@@ -485,10 +835,10 @@ ${code}
|
|
|
485
835
|
});
|
|
486
836
|
if (icons.size > 0) {
|
|
487
837
|
Array.from(icons)
|
|
488
|
-
.map(icon => path.join(this.root, icon))
|
|
489
|
-
.forEach(iconPath => {
|
|
838
|
+
.map((icon) => path.join(this.root, icon))
|
|
839
|
+
.forEach((iconPath) => {
|
|
490
840
|
const iconDistPath = this.getDistFilePath(iconPath);
|
|
491
|
-
|
|
841
|
+
(0, util_1.copyFileToTaro)(iconPath, iconDistPath);
|
|
492
842
|
(0, helper_1.printLog)("copy" /* processTypeEnum.COPY */, 'TabBar 图标', this.generateShowPath(iconDistPath));
|
|
493
843
|
});
|
|
494
844
|
}
|
|
@@ -500,7 +850,7 @@ ${code}
|
|
|
500
850
|
const customTabbarPath = path.join(this.root, 'custom-tab-bar');
|
|
501
851
|
if (helper_1.fs.existsSync(customTabbarPath)) {
|
|
502
852
|
const customTabbarDistPath = this.getDistFilePath(customTabbarPath);
|
|
503
|
-
|
|
853
|
+
(0, util_1.copyFileToTaro)(customTabbarPath, customTabbarDistPath);
|
|
504
854
|
(0, helper_1.printLog)("copy" /* processTypeEnum.COPY */, '自定义 TabBar', this.generateShowPath(customTabbarDistPath));
|
|
505
855
|
}
|
|
506
856
|
}
|
|
@@ -510,9 +860,52 @@ ${code}
|
|
|
510
860
|
}
|
|
511
861
|
return path.join(path.dirname(file), path.basename(file, path.extname(file)) + '.vue');
|
|
512
862
|
}
|
|
863
|
+
// 判断是否是三方库
|
|
864
|
+
isThirdPartyLib(modulePath, curPageDir) {
|
|
865
|
+
// 相对路径和带根目录的路径都不是三方库
|
|
866
|
+
if (modulePath.indexOf('.') === 0 || modulePath.indexOf('/') === 0 || modulePath.indexOf(this.root) !== -1) {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
// 通过格式如component/component引用组件
|
|
870
|
+
// app.json中引用组件
|
|
871
|
+
if (curPageDir === this.root) {
|
|
872
|
+
if (helper_1.fs.existsSync((0, helper_1.resolveScriptPath)(path.join(curPageDir, modulePath)))) {
|
|
873
|
+
return false;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
// 页面中引用组件
|
|
878
|
+
if (helper_1.fs.existsSync((0, helper_1.resolveScriptPath)(path.join(curPageDir, modulePath))) ||
|
|
879
|
+
helper_1.fs.existsSync((0, helper_1.resolveScriptPath)(path.join(this.root, modulePath)))) {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
// 判断三方库是否安装
|
|
886
|
+
isInNodeModule(modulePath) {
|
|
887
|
+
const nodeModules = path.resolve(this.root, 'node_modules');
|
|
888
|
+
if (!helper_1.fs.existsSync(nodeModules)) {
|
|
889
|
+
return false;
|
|
890
|
+
}
|
|
891
|
+
const modules = helper_1.fs.readdirSync(nodeModules);
|
|
892
|
+
const parts = modulePath.split('/');
|
|
893
|
+
if (modules.indexOf(parts[0]) === -1) {
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
return true;
|
|
897
|
+
}
|
|
513
898
|
traversePages() {
|
|
514
|
-
this.pages.forEach(page => {
|
|
515
|
-
|
|
899
|
+
this.pages.forEach((page) => {
|
|
900
|
+
var _a;
|
|
901
|
+
(0, util_1.printToLogFile)(`开始转换页面 ${page} ${(0, util_1.getLineBreak)()}`);
|
|
902
|
+
const pagePath = this.isTsProject ? path.join(this.miniprogramRoot, page) : path.join(this.root, page);
|
|
903
|
+
// 处理不转换的页面,可在convert.config.json中external字段配置
|
|
904
|
+
const matchUnconvertDir = (0, util_1.getMatchUnconvertDir)(pagePath, (_a = this.convertConfig) === null || _a === void 0 ? void 0 : _a.external);
|
|
905
|
+
if (matchUnconvertDir !== null) {
|
|
906
|
+
(0, util_1.handleUnconvertDir)(matchUnconvertDir, this.root, this.convertDir);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
516
909
|
const pageJSPath = pagePath + this.fileTypes.SCRIPT;
|
|
517
910
|
const pageDistJSPath = this.getDistFilePath(pageJSPath);
|
|
518
911
|
const pageConfigPath = pagePath + this.fileTypes.CONFIG;
|
|
@@ -542,11 +935,15 @@ ${code}
|
|
|
542
935
|
if (pageUsingComponents) {
|
|
543
936
|
// 页面依赖组件
|
|
544
937
|
const usingComponents = {};
|
|
545
|
-
Object.keys(pageUsingComponents).forEach(component => {
|
|
938
|
+
Object.keys(pageUsingComponents).forEach((component) => {
|
|
939
|
+
var _a;
|
|
546
940
|
const unResolveComponentPath = pageUsingComponents[component];
|
|
547
941
|
if (unResolveComponentPath.startsWith('plugin://')) {
|
|
548
942
|
usingComponents[component] = unResolveComponentPath;
|
|
549
943
|
}
|
|
944
|
+
else if (this.isThirdPartyLib(unResolveComponentPath, path.resolve(pagePath, '..'))) {
|
|
945
|
+
(0, util_1.handleThirdPartyLib)(unResolveComponentPath, (_a = this.convertConfig) === null || _a === void 0 ? void 0 : _a.nodePath, this.root, this.convertRoot);
|
|
946
|
+
}
|
|
550
947
|
else {
|
|
551
948
|
let componentPath;
|
|
552
949
|
if (unResolveComponentPath.startsWith(this.root)) {
|
|
@@ -554,13 +951,14 @@ ${code}
|
|
|
554
951
|
}
|
|
555
952
|
else {
|
|
556
953
|
componentPath = path.resolve(pageConfigPath, '..', pageUsingComponents[component]);
|
|
954
|
+
// 支持将组件库放在工程根目录下
|
|
557
955
|
if (!helper_1.fs.existsSync((0, helper_1.resolveScriptPath)(componentPath))) {
|
|
558
956
|
componentPath = path.join(this.root, pageUsingComponents[component]);
|
|
559
957
|
}
|
|
560
958
|
}
|
|
561
959
|
depComponents.add({
|
|
562
960
|
name: component,
|
|
563
|
-
path: componentPath
|
|
961
|
+
path: componentPath,
|
|
564
962
|
});
|
|
565
963
|
}
|
|
566
964
|
});
|
|
@@ -574,6 +972,7 @@ ${code}
|
|
|
574
972
|
param.json = JSON.stringify(pageConfig);
|
|
575
973
|
}
|
|
576
974
|
param.script = String(helper_1.fs.readFileSync(pageJSPath));
|
|
975
|
+
param.scriptPath = pageJSPath;
|
|
577
976
|
if (helper_1.fs.existsSync(pageTemplPath)) {
|
|
578
977
|
(0, helper_1.printLog)("convert" /* processTypeEnum.CONVERT */, '页面模板', this.generateShowPath(pageTemplPath));
|
|
579
978
|
param.wxml = String(helper_1.fs.readFileSync(pageTemplPath));
|
|
@@ -585,6 +984,7 @@ ${code}
|
|
|
585
984
|
}
|
|
586
985
|
param.path = path.dirname(pageJSPath);
|
|
587
986
|
param.rootPath = this.root;
|
|
987
|
+
param.logFilePath = global_1.globals.logFilePath;
|
|
588
988
|
const taroizeResult = taroize(Object.assign(Object.assign({}, param), { framework: this.framework }));
|
|
589
989
|
const { ast, scriptFiles } = this.parseAst({
|
|
590
990
|
ast: taroizeResult.ast,
|
|
@@ -592,10 +992,11 @@ ${code}
|
|
|
592
992
|
outputFilePath: pageDistJSPath,
|
|
593
993
|
importStylePath: pageStyle ? pageStylePath.replace(path.extname(pageStylePath), OUTPUT_STYLE_EXTNAME) : null,
|
|
594
994
|
depComponents,
|
|
595
|
-
imports: taroizeResult.imports
|
|
995
|
+
imports: taroizeResult.imports,
|
|
596
996
|
});
|
|
597
997
|
const jsCode = (0, astConvert_1.generateMinimalEscapeCode)(ast);
|
|
598
998
|
this.writeFileToTaro(this.getComponentDest(pageDistJSPath), this.formatFile(jsCode, taroizeResult.template));
|
|
999
|
+
(0, helper_1.printLog)("generate" /* processTypeEnum.GENERATE */, 'writeFileToTaro', this.generateShowPath(pageDistJSPath));
|
|
599
1000
|
this.writeFileToConfig(pageDistJSPath, param.json);
|
|
600
1001
|
(0, helper_1.printLog)("generate" /* processTypeEnum.GENERATE */, '页面文件', this.generateShowPath(pageDistJSPath));
|
|
601
1002
|
if (pageStyle) {
|
|
@@ -607,6 +1008,7 @@ ${code}
|
|
|
607
1008
|
catch (err) {
|
|
608
1009
|
(0, helper_1.printLog)("error" /* processTypeEnum.ERROR */, '页面转换', this.generateShowPath(pageJSPath));
|
|
609
1010
|
console.log(err);
|
|
1011
|
+
(0, util_1.printToLogFile)(`转换页面异常 ${err.stack} ${(0, util_1.getLineBreak)()}`);
|
|
610
1012
|
}
|
|
611
1013
|
});
|
|
612
1014
|
}
|
|
@@ -614,21 +1016,21 @@ ${code}
|
|
|
614
1016
|
if (!components || !components.size) {
|
|
615
1017
|
return;
|
|
616
1018
|
}
|
|
617
|
-
components.forEach(componentObj => {
|
|
1019
|
+
components.forEach((componentObj) => {
|
|
618
1020
|
const component = componentObj.path;
|
|
619
1021
|
if (this.hadBeenBuiltComponents.has(component))
|
|
620
1022
|
return;
|
|
621
1023
|
this.hadBeenBuiltComponents.add(component);
|
|
622
|
-
const componentJSPath = component
|
|
1024
|
+
const componentJSPath = this.getComponentPath(component, this.fileTypes.SCRIPT);
|
|
623
1025
|
const componentDistJSPath = this.getDistFilePath(componentJSPath);
|
|
624
|
-
const componentConfigPath = component
|
|
625
|
-
const componentStylePath = component
|
|
626
|
-
const componentTemplPath = component
|
|
1026
|
+
const componentConfigPath = this.getComponentPath(component, this.fileTypes.CONFIG);
|
|
1027
|
+
const componentStylePath = this.getComponentPath(component, this.fileTypes.STYLE);
|
|
1028
|
+
const componentTemplPath = this.getComponentPath(component, this.fileTypes.TEMPL);
|
|
627
1029
|
try {
|
|
628
1030
|
const param = {};
|
|
629
1031
|
const depComponents = new Set();
|
|
630
1032
|
if (!helper_1.fs.existsSync(componentJSPath)) {
|
|
631
|
-
throw new Error(
|
|
1033
|
+
throw new Error(`自定义组件 ${component} 没有 JS 文件!`);
|
|
632
1034
|
}
|
|
633
1035
|
(0, helper_1.printLog)("convert" /* processTypeEnum.CONVERT */, '组件文件', this.generateShowPath(componentJSPath));
|
|
634
1036
|
if (helper_1.fs.existsSync(componentConfigPath)) {
|
|
@@ -638,14 +1040,17 @@ ${code}
|
|
|
638
1040
|
const componentUsingComponnets = componentConfig.usingComponents;
|
|
639
1041
|
if (componentUsingComponnets) {
|
|
640
1042
|
// 页面依赖组件
|
|
641
|
-
Object.keys(componentUsingComponnets).forEach(component => {
|
|
1043
|
+
Object.keys(componentUsingComponnets).forEach((component) => {
|
|
642
1044
|
let componentPath = path.resolve(componentConfigPath, '..', componentUsingComponnets[component]);
|
|
643
1045
|
if (!helper_1.fs.existsSync((0, helper_1.resolveScriptPath)(componentPath))) {
|
|
644
1046
|
componentPath = path.join(this.root, componentUsingComponnets[component]);
|
|
645
1047
|
}
|
|
1048
|
+
if (!helper_1.fs.existsSync(componentPath + this.fileTypes.SCRIPT)) {
|
|
1049
|
+
componentPath = path.join(componentPath, `/index`);
|
|
1050
|
+
}
|
|
646
1051
|
depComponents.add({
|
|
647
1052
|
name: component,
|
|
648
|
-
path: componentPath
|
|
1053
|
+
path: componentPath,
|
|
649
1054
|
});
|
|
650
1055
|
});
|
|
651
1056
|
delete componentConfig.usingComponents;
|
|
@@ -664,6 +1069,7 @@ ${code}
|
|
|
664
1069
|
}
|
|
665
1070
|
param.path = path.dirname(componentJSPath);
|
|
666
1071
|
param.rootPath = this.root;
|
|
1072
|
+
param.logFilePath = global_1.globals.logFilePath;
|
|
667
1073
|
const taroizeResult = taroize(Object.assign(Object.assign({}, param), { framework: this.framework }));
|
|
668
1074
|
const { ast, scriptFiles } = this.parseAst({
|
|
669
1075
|
ast: taroizeResult.ast,
|
|
@@ -673,7 +1079,7 @@ ${code}
|
|
|
673
1079
|
? componentStylePath.replace(path.extname(componentStylePath), OUTPUT_STYLE_EXTNAME)
|
|
674
1080
|
: null,
|
|
675
1081
|
depComponents,
|
|
676
|
-
imports: taroizeResult.imports
|
|
1082
|
+
imports: taroizeResult.imports,
|
|
677
1083
|
});
|
|
678
1084
|
const jsCode = (0, astConvert_1.generateMinimalEscapeCode)(ast);
|
|
679
1085
|
this.writeFileToTaro(this.getComponentDest(componentDistJSPath), this.formatFile(jsCode, taroizeResult.template));
|
|
@@ -693,7 +1099,7 @@ ${code}
|
|
|
693
1099
|
styleUnitTransform(filePath, content) {
|
|
694
1100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
695
1101
|
const postcssResult = yield (0, postcss_1.default)([unitTransform()]).process(content, {
|
|
696
|
-
from: filePath
|
|
1102
|
+
from: filePath,
|
|
697
1103
|
});
|
|
698
1104
|
return postcssResult;
|
|
699
1105
|
});
|
|
@@ -705,10 +1111,7 @@ ${code}
|
|
|
705
1111
|
styleDist = path.dirname(styleDist);
|
|
706
1112
|
while (token === null || token === void 0 ? void 0 : token.length) {
|
|
707
1113
|
let url = token[1];
|
|
708
|
-
if (url &&
|
|
709
|
-
url.indexOf('data:') !== 0 &&
|
|
710
|
-
url.indexOf('#') !== 0 &&
|
|
711
|
-
!(/^[a-z]+:\/\//.test(url))) {
|
|
1114
|
+
if (url && url.indexOf('data:') !== 0 && url.indexOf('#') !== 0 && !/^[a-z]+:\/\//.test(url)) {
|
|
712
1115
|
url = url.trim();
|
|
713
1116
|
url.replace(/[/\\]/g, path.sep);
|
|
714
1117
|
url = url.split('?')[0];
|
|
@@ -743,7 +1146,7 @@ ${code}
|
|
|
743
1146
|
this.writeFileToTaro(styleDist, css);
|
|
744
1147
|
(0, helper_1.printLog)("generate" /* processTypeEnum.GENERATE */, '样式文件', this.generateShowPath(styleDist));
|
|
745
1148
|
if (imports && imports.length) {
|
|
746
|
-
imports.forEach(importItem => {
|
|
1149
|
+
imports.forEach((importItem) => {
|
|
747
1150
|
const importPath = path.isAbsolute(importItem)
|
|
748
1151
|
? path.join(this.root, importItem)
|
|
749
1152
|
: path.resolve(path.dirname(filePath), importItem);
|
|
@@ -773,44 +1176,48 @@ ${code}
|
|
|
773
1176
|
typescript: false,
|
|
774
1177
|
template: templateName,
|
|
775
1178
|
framework: this.framework,
|
|
776
|
-
compiler: 'webpack5'
|
|
1179
|
+
compiler: 'webpack5',
|
|
777
1180
|
});
|
|
778
1181
|
creator.template(templateName, path.join('config', 'index.js'), path.join(configDir, 'index.js'), {
|
|
779
1182
|
date,
|
|
780
1183
|
projectName,
|
|
781
1184
|
framework: this.framework,
|
|
782
|
-
compiler: 'webpack5'
|
|
1185
|
+
compiler: 'webpack5',
|
|
1186
|
+
typescript: false,
|
|
783
1187
|
});
|
|
784
1188
|
creator.template(templateName, path.join('config', 'dev.js'), path.join(configDir, 'dev.js'), {
|
|
785
|
-
framework: this.framework
|
|
1189
|
+
framework: this.framework,
|
|
1190
|
+
compiler: 'webpack5',
|
|
1191
|
+
typescript: false,
|
|
786
1192
|
});
|
|
787
1193
|
creator.template(templateName, path.join('config', 'prod.js'), path.join(configDir, 'prod.js'), {
|
|
788
|
-
framework: this.framework
|
|
1194
|
+
framework: this.framework,
|
|
1195
|
+
typescript: false,
|
|
789
1196
|
});
|
|
790
1197
|
creator.template(templateName, 'project.config.json', path.join(this.convertRoot, 'project.config.json'), {
|
|
791
1198
|
description,
|
|
792
1199
|
projectName,
|
|
793
|
-
framework: this.framework
|
|
1200
|
+
framework: this.framework,
|
|
794
1201
|
});
|
|
795
1202
|
creator.template(templateName, '.gitignore', path.join(this.convertRoot, '.gitignore'));
|
|
796
1203
|
creator.template(templateName, '.editorconfig', path.join(this.convertRoot, '.editorconfig'));
|
|
797
1204
|
creator.template(templateName, '.eslintrc.js', path.join(this.convertRoot, '.eslintrc.js'), {
|
|
798
1205
|
typescript: false,
|
|
799
|
-
framework: this.framework
|
|
1206
|
+
framework: this.framework,
|
|
800
1207
|
});
|
|
801
1208
|
creator.template(templateName, 'babel.config.js', path.join(this.convertRoot, 'babel.config.js'), {
|
|
802
1209
|
typescript: false,
|
|
803
|
-
framework: this.framework
|
|
1210
|
+
framework: this.framework,
|
|
804
1211
|
});
|
|
805
1212
|
creator.template(templateName, path.join('src', 'index.html'), path.join(this.convertDir, 'index.html'), {
|
|
806
|
-
projectName
|
|
1213
|
+
projectName,
|
|
807
1214
|
});
|
|
808
1215
|
creator.fs.commit(() => {
|
|
809
1216
|
const pkgObj = JSON.parse(helper_1.fs.readFileSync(pkgPath).toString());
|
|
810
1217
|
pkgObj.dependencies['@tarojs/with-weapp'] = `^${version}`;
|
|
811
1218
|
helper_1.fs.writeJSONSync(pkgPath, pkgObj, {
|
|
812
1219
|
spaces: 2,
|
|
813
|
-
EOL: '\n'
|
|
1220
|
+
EOL: '\n',
|
|
814
1221
|
});
|
|
815
1222
|
(0, helper_1.printLog)("generate" /* processTypeEnum.GENERATE */, '文件', this.generateShowPath(path.join(configDir, 'index.js')));
|
|
816
1223
|
(0, helper_1.printLog)("generate" /* processTypeEnum.GENERATE */, '文件', this.generateShowPath(path.join(configDir, 'dev.js')));
|
|
@@ -824,15 +1231,27 @@ ${code}
|
|
|
824
1231
|
this.showLog();
|
|
825
1232
|
});
|
|
826
1233
|
}
|
|
1234
|
+
/**
|
|
1235
|
+
* generateReport: 为转换后的 taroConvert 工程添加转换报告
|
|
1236
|
+
*/
|
|
1237
|
+
generateReport() {
|
|
1238
|
+
const reportDir = path.join(this.convertRoot, 'report');
|
|
1239
|
+
const reportBundleFilePath = path.resolve(__dirname, '../', 'report/bundle.js');
|
|
1240
|
+
const reportIndexFilePath = path.resolve(__dirname, '../', 'report/report.html');
|
|
1241
|
+
(0, util_1.generateReportFile)(reportBundleFilePath, reportDir, 'bundle.js', this.reportErroMsg);
|
|
1242
|
+
(0, util_1.generateReportFile)(reportIndexFilePath, reportDir, 'report.html');
|
|
1243
|
+
}
|
|
827
1244
|
showLog() {
|
|
828
1245
|
console.log();
|
|
829
1246
|
console.log(`${helper_1.chalk.green('✔ ')} 转换成功,请进入 ${helper_1.chalk.bold('taroConvert')} 目录下使用 npm 或者 yarn 安装项目依赖后再运行!`);
|
|
1247
|
+
console.log(`转换报告已生成,请在浏览器中打开 ${path.join(this.convertRoot, 'report', 'report.html')} 查看转换报告`);
|
|
830
1248
|
}
|
|
831
1249
|
run() {
|
|
832
1250
|
this.framework = 'react';
|
|
833
1251
|
this.generateEntry();
|
|
834
1252
|
this.traversePages();
|
|
835
1253
|
this.generateConfigFiles();
|
|
1254
|
+
this.generateReport();
|
|
836
1255
|
}
|
|
837
1256
|
}
|
|
838
1257
|
exports.default = Convertor;
|