@tmsfe/tmskit 0.0.5-beta.1 → 0.0.5-beta.5
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.md +16 -2
- package/dist/index.cjs.js +945 -296
- package/package.json +11 -4
- package/src/config/constant.js +2 -0
- package/src/config/defaultTmsConfig.js +8 -10
- package/src/gulp/build.js +3 -1
- package/src/gulp/compile.js +32 -12
- package/src/gulp/dev.js +42 -17
- package/src/gulp/plugins/less.js +116 -0
- package/src/gulp/plugins/mpCommonDep.js +131 -0
- package/src/gulp/plugins/mpJsonDep.js +108 -0
- package/src/gulp/plugins/mpWxmlDep.js +194 -0
- package/src/gulp/plugins/postcss-font-base64.js +72 -0
- package/src/gulp/plugins/utils/pluginError.js +25 -0
- package/src/index.js +0 -1
- package/src/scripts/run/build/index.js +1 -1
- package/src/scripts/run/dev/index.js +1 -1
- package/src/scripts/run/init/index.js +5 -5
- package/src/scripts/run/install/index.js +1 -1
- package/src/utils/buildAppJson.js +59 -3
- package/src/utils/cloneModules.js +1 -0
- package/src/utils/findCssImport.js +30 -0
- package/src/utils/io.js +43 -3
- package/src/utils/widgets.js +6 -3
- package/CHANGELOG.md +0 -0
- package/rollup.config.js +0 -179
- package/src/gulp/includeDep.js +0 -130
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
const through = require('through2');
|
|
3
|
+
const htmlparser2 = require('htmlparser2');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { diffContentCopyFile, ext, fileInDir } = require('../../utils/io');
|
|
7
|
+
const { resolve } = require('../../utils/widgets');
|
|
8
|
+
const { dfsFindCommonDep } = require('./mpCommonDep');
|
|
9
|
+
const { pluginError } = require('./utils/pluginError');
|
|
10
|
+
|
|
11
|
+
// 处理后缀(源码引入依赖时,不带后缀的情况)
|
|
12
|
+
const extFile = function (name, file) {
|
|
13
|
+
const extMap = {
|
|
14
|
+
import: '.wxml',
|
|
15
|
+
include: '.wxml',
|
|
16
|
+
wxs: '.wxs',
|
|
17
|
+
};
|
|
18
|
+
let extObj = {};
|
|
19
|
+
|
|
20
|
+
if (Object.keys(extMap).indexOf(name) > -1 && !file.endsWith(extMap[name])) {
|
|
21
|
+
extObj = ext(file, [extMap[name]]);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
extPath: extObj.extPath || '',
|
|
25
|
+
ext: extObj.ext || '',
|
|
26
|
+
file: extObj.file || file,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const dfsFindWxmlDep = function (anaFileOriginFile, anaFileDestFile, isWatch = true) {
|
|
31
|
+
const resDep = {
|
|
32
|
+
image: new Map(),
|
|
33
|
+
wxml: new Map(),
|
|
34
|
+
wxs: new Map(),
|
|
35
|
+
};
|
|
36
|
+
function dfs(anaFileOriginFile, anaFileDestFile) {
|
|
37
|
+
let contents = '';
|
|
38
|
+
try {
|
|
39
|
+
contents = fs.readFileSync(anaFileOriginFile, 'utf8');
|
|
40
|
+
} catch (e) {
|
|
41
|
+
pluginError(e, isWatch);
|
|
42
|
+
}
|
|
43
|
+
const parser = new htmlparser2.Parser({
|
|
44
|
+
onopentag(name, attributes) {
|
|
45
|
+
if (attributes?.src?.startsWith('.')) {
|
|
46
|
+
const depOriginPath = path.join(path.dirname(anaFileOriginFile), attributes.src);
|
|
47
|
+
// 被依赖文件加上后缀
|
|
48
|
+
const { ext, file: depOriginFile, extPath } = extFile(name, depOriginPath);
|
|
49
|
+
|
|
50
|
+
if (!fs.existsSync(depOriginFile)) {
|
|
51
|
+
pluginError(
|
|
52
|
+
new Error(`${anaFileOriginFile}引用的路径${depOriginFile}找不到应用文件,请检查引用路径`),
|
|
53
|
+
isWatch,
|
|
54
|
+
);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const depDestPath = path.join(path.dirname(anaFileDestFile), attributes.src);
|
|
59
|
+
const depDestFile = depDestPath.endsWith(ext) ? depDestPath : depDestPath + extPath;
|
|
60
|
+
|
|
61
|
+
// 收集wxml依赖
|
|
62
|
+
if (['import', 'include'].indexOf(name) > -1) {
|
|
63
|
+
resDep.wxml.set(depDestFile, {
|
|
64
|
+
anaFileOriginFile,
|
|
65
|
+
anaFileDestFile,
|
|
66
|
+
depDestFile,
|
|
67
|
+
depOriginFile,
|
|
68
|
+
});
|
|
69
|
+
dfs(depOriginFile, depDestFile);
|
|
70
|
+
}
|
|
71
|
+
// 收集image依赖
|
|
72
|
+
// if (name === 'image') {
|
|
73
|
+
// resDep.image.set(attributes.src, {
|
|
74
|
+
// anaFileOriginFile,
|
|
75
|
+
// anaFileDestFile,
|
|
76
|
+
// depDestFile,
|
|
77
|
+
// depOriginFile,
|
|
78
|
+
// });
|
|
79
|
+
// dfs(depOriginFile, depDestFile);
|
|
80
|
+
// }
|
|
81
|
+
// 收集wxs依赖
|
|
82
|
+
if (name === 'wxs') {
|
|
83
|
+
resDep.wxs.set(depDestFile, {
|
|
84
|
+
anaFileOriginFile,
|
|
85
|
+
anaFileDestFile,
|
|
86
|
+
depDestFile,
|
|
87
|
+
depOriginFile,
|
|
88
|
+
});
|
|
89
|
+
const defs = dfsFindCommonDep(depOriginFile, depDestFile, ['.wxs']);
|
|
90
|
+
defs.forEach((item, key) => {
|
|
91
|
+
resDep.wxs.set(key, item);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
parser.write(contents);
|
|
98
|
+
parser.end();
|
|
99
|
+
}
|
|
100
|
+
dfs(anaFileOriginFile, anaFileDestFile);
|
|
101
|
+
|
|
102
|
+
return resDep;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
function mpWxmlDep(tmsConfig, module, isWatch) {
|
|
106
|
+
const stream = through.obj(function (file, enc, cb) {
|
|
107
|
+
// 依赖分析的文件
|
|
108
|
+
const anaFileOriginFile = file.history[0];
|
|
109
|
+
const anaFileRelativeModule = path.relative(resolve(module.from), anaFileOriginFile);
|
|
110
|
+
const anaFileDestFile = resolve(tmsConfig.outputDir, module.to, anaFileRelativeModule);
|
|
111
|
+
|
|
112
|
+
if (file.isBuffer()) {
|
|
113
|
+
let contents = String(file.contents);
|
|
114
|
+
const copyModules = new Map();
|
|
115
|
+
const parser = new htmlparser2.Parser({
|
|
116
|
+
onopentag(name, attributes) {
|
|
117
|
+
const nameFilter = ['import', 'include', 'wxs'];
|
|
118
|
+
if (nameFilter.indexOf(name) > -1 && attributes.src) {
|
|
119
|
+
const depOriginPath = path.join(path.dirname(anaFileOriginFile), attributes.src);
|
|
120
|
+
// 处理后缀(源码引入依赖时,后缀不全的情况)
|
|
121
|
+
const { ext, file: depOriginFile, extPath } = extFile(name, depOriginPath);
|
|
122
|
+
|
|
123
|
+
Object.keys(tmsConfig.dependencies).forEach((includeName) => {
|
|
124
|
+
if (attributes.src.indexOf(includeName) > -1) {
|
|
125
|
+
const includePath = tmsConfig.dependencies[includeName];
|
|
126
|
+
|
|
127
|
+
if (!fileInDir(includePath, depOriginFile)) {
|
|
128
|
+
pluginError(
|
|
129
|
+
new Error(`${anaFileOriginFile}引用路径${depOriginFile}不在${includePath}不在文件夹内, 请检查应用路径`),
|
|
130
|
+
isWatch,
|
|
131
|
+
);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// eslint-disable-next-line
|
|
136
|
+
const reg = new RegExp(`^(\.\.\/)+.*\/${includeName}\/(.*)`);
|
|
137
|
+
const regRes = attributes.src.match(reg) || [];
|
|
138
|
+
if (regRes[2]) {
|
|
139
|
+
const depDestPath = resolve(tmsConfig.outputDir, module.to, includeName, regRes[2]);
|
|
140
|
+
const depDestFile = depDestPath.endsWith(ext) ? depDestPath : depDestPath + extPath;
|
|
141
|
+
if (!copyModules.has(depDestFile)) {
|
|
142
|
+
copyModules.set(depDestFile, {
|
|
143
|
+
depOriginFile,
|
|
144
|
+
depDestFile,
|
|
145
|
+
beforeDepPath: attributes.src,
|
|
146
|
+
afterDepPath: path.relative(path.dirname(anaFileDestFile), depDestFile),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
parser.write(contents);
|
|
156
|
+
parser.end();
|
|
157
|
+
|
|
158
|
+
// console.log('wxml copyModules', copyModules);
|
|
159
|
+
copyModules.forEach(({ depOriginFile, depDestFile, beforeDepPath, afterDepPath }) => {
|
|
160
|
+
if (fs.existsSync(depOriginFile)) {
|
|
161
|
+
diffContentCopyFile(depOriginFile, depDestFile);
|
|
162
|
+
const reg = new RegExp(`['"]${beforeDepPath}["']`, 'g');
|
|
163
|
+
contents = contents.replace(reg, `"${afterDepPath}"`);
|
|
164
|
+
}
|
|
165
|
+
if (depOriginFile.endsWith('.wxml')) {
|
|
166
|
+
const defs = dfsFindWxmlDep(depOriginFile, depDestFile, isWatch);
|
|
167
|
+
// console.log('wxml defs', defs);
|
|
168
|
+
[...defs.wxml, ...defs.wxs].forEach(([, item]) => {
|
|
169
|
+
diffContentCopyFile(item.depOriginFile, item.depDestFile);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (depOriginFile.endsWith('.wxs')) {
|
|
173
|
+
const defs = dfsFindCommonDep(depOriginFile, depDestFile, ['.wxs'], isWatch);
|
|
174
|
+
// console.log('wxs defs', defs);
|
|
175
|
+
defs.forEach((item) => {
|
|
176
|
+
diffContentCopyFile(item.depOriginFile, item.depDestFile);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
file.contents = new Buffer(contents);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
this.push(file);
|
|
185
|
+
cb();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return stream;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
module.exports = {
|
|
192
|
+
mpWxmlDep,
|
|
193
|
+
dfsFindWxmlDep,
|
|
194
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
const postcss = require('postcss');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { fail } = require('../../utils/log');
|
|
6
|
+
|
|
7
|
+
module.exports = postcss.plugin('postcss-font-base64', (options) => {
|
|
8
|
+
options = {
|
|
9
|
+
...options,
|
|
10
|
+
...{
|
|
11
|
+
match: { Scrabble: ['fakefont'] },
|
|
12
|
+
format: ['eot', 'woff', 'woff2', 'ttf'],
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return function (css, result) {
|
|
17
|
+
css.walkAtRules('font-face', (fontFace) => {
|
|
18
|
+
const fileTypeRegex = getRegexStringForFileTypes(options.format);
|
|
19
|
+
|
|
20
|
+
fontFace.replaceValues(new RegExp(`url\\(["']?.+\\.${fileTypeRegex}["']?\\)`), (attr) => {
|
|
21
|
+
const fontRePath = attr.replace(/(url|'|"|\(|\)|\?#iefix)/g, '');
|
|
22
|
+
const fontAbPath = path.join(path.dirname(result.opts.from), fontRePath);
|
|
23
|
+
const res64 = base64Encode(fontAbPath);
|
|
24
|
+
const newUrlStr = 'url(data:'.concat(getMimeType(attr)).concat(';charset=utf-8;base64,')
|
|
25
|
+
.concat(res64)
|
|
26
|
+
.concat(')');
|
|
27
|
+
return res64 ? newUrlStr : attr;
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function getRegexStringForFileTypes(fileTypes) {
|
|
32
|
+
const regex = fileTypes.map(fileType => (
|
|
33
|
+
fileType === 'eot'
|
|
34
|
+
? fileType.concat('(\\?#iefix)?')
|
|
35
|
+
: fileType)).join('|');
|
|
36
|
+
return regex ? `(${regex})` : '';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// helper functions
|
|
40
|
+
function getMimeType(attribute) {
|
|
41
|
+
const formats = {
|
|
42
|
+
'.woff': 'application/font-woff',
|
|
43
|
+
'.woff2': 'font/woff2',
|
|
44
|
+
'.ttf': 'application/font-sfnt',
|
|
45
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
46
|
+
'.otf': 'application/font-sfnt',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
let match = '';
|
|
50
|
+
const extension = attribute.match(/\.[a-z]{3,4}/)[0];
|
|
51
|
+
|
|
52
|
+
if (extension in formats) {
|
|
53
|
+
match = formats[extension];
|
|
54
|
+
};
|
|
55
|
+
return match;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function base64Encode(file) {
|
|
59
|
+
if (fs.existsSync(file)) {
|
|
60
|
+
return readAndEncodeFile(file);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fail(`${file} does not exist.`);
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function readAndEncodeFile(file) {
|
|
68
|
+
const bitmap = fs.readFileSync(file);
|
|
69
|
+
return new Buffer(bitmap).toString('base64');
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
const { fail } = require('../../../utils/log');
|
|
3
|
+
|
|
4
|
+
function pluginError(error, isWatch) {
|
|
5
|
+
const errorOptions = { showStack: true };
|
|
6
|
+
|
|
7
|
+
errorOptions.error = error;
|
|
8
|
+
errorOptions.fileName = error.file;
|
|
9
|
+
errorOptions.lineNumber = error.line;
|
|
10
|
+
errorOptions.showProperties = false;
|
|
11
|
+
errorOptions.showStack = false;
|
|
12
|
+
|
|
13
|
+
const errMsg = error.message;
|
|
14
|
+
|
|
15
|
+
if (isWatch) {
|
|
16
|
+
fail(errMsg);
|
|
17
|
+
} else {
|
|
18
|
+
fail(errMsg);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
pluginError,
|
|
25
|
+
};
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const gulpBuild = require('../../../gulp/build');
|
|
|
5
5
|
|
|
6
6
|
async function build(tmsConfig, targetModules, env) {
|
|
7
7
|
// 开始构建前,清理输出目录
|
|
8
|
-
await shelljs.rm('-rf', resolve(tmsConfig.
|
|
8
|
+
await shelljs.rm('-rf', resolve(tmsConfig.outputDir));
|
|
9
9
|
|
|
10
10
|
const { targetModules: newModules } = await init(tmsConfig, targetModules);
|
|
11
11
|
|
|
@@ -45,7 +45,7 @@ function isInit(tmsConfig, targetModules, contextDir) {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// 判断package.json的版本是否有新的版本
|
|
48
|
-
return checkDependencies(targetModules, resolve('./'), tmsConfig.
|
|
48
|
+
return checkDependencies(targetModules, resolve('./'), tmsConfig.outputDir);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async function dev(tmsConfig, targetModules, env) {
|
|
@@ -17,17 +17,17 @@ const install = require('../install');
|
|
|
17
17
|
* @returns
|
|
18
18
|
*/
|
|
19
19
|
const cpFilesToOutput = function (tmsConfig, targetModules, defaultFiles) {
|
|
20
|
-
const outputDir = resolve(tmsConfig.
|
|
20
|
+
const outputDir = resolve(tmsConfig.outputDir);
|
|
21
21
|
io.ensureDirExist(outputDir);
|
|
22
22
|
defaultFiles.forEach((item) => {
|
|
23
23
|
if (fs.existsSync(resolve(item))) {
|
|
24
|
-
shelljs.cp('-rf', resolve(item), resolve(tmsConfig.
|
|
24
|
+
shelljs.cp('-rf', resolve(item), resolve(tmsConfig.outputDir, item));
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
// 拷贝模块的package.json到编译输出目录
|
|
29
29
|
targetModules.forEach((item) => {
|
|
30
|
-
const outputModuleDir = resolve(`${tmsConfig.
|
|
30
|
+
const outputModuleDir = resolve(`${tmsConfig.outputDir}/${item.root}`);
|
|
31
31
|
if (!fs.existsSync(resolve(item.path))) {
|
|
32
32
|
fail(`${item.path}模块代码路径不存在, 请检查tms.config.js的${item.name}模块的path`);
|
|
33
33
|
process.exit(1);
|
|
@@ -69,7 +69,7 @@ async function task(tmsConfig, targetModules) {
|
|
|
69
69
|
|
|
70
70
|
return newModules;
|
|
71
71
|
}
|
|
72
|
-
async function
|
|
72
|
+
async function init(tmsConfig, targetModules) {
|
|
73
73
|
const newModules = await task(tmsConfig, targetModules);
|
|
74
74
|
|
|
75
75
|
return {
|
|
@@ -77,4 +77,4 @@ async function bootstrap(tmsConfig, targetModules) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
module.exports =
|
|
80
|
+
module.exports = init;
|
|
@@ -11,7 +11,7 @@ async function install(tmsConfig, modules, isCloud = true) {
|
|
|
11
11
|
mpNpmInstallAll,
|
|
12
12
|
'小程序 开始npm install',
|
|
13
13
|
'小程序npm install 完成',
|
|
14
|
-
)(newModules, resolve(tmsConfig.
|
|
14
|
+
)(newModules, resolve(tmsConfig.outputDir), `${CACHE_DIR}/node_modules`);
|
|
15
15
|
|
|
16
16
|
// 构建miniprograme_npm
|
|
17
17
|
await createTask(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const { DEFAULT_MODULE_DIR, MODULE_CONFIG_FILENAME } = require('../config/constant');
|
|
2
|
+
const { DEFAULT_MODULE_DIR, MODULE_CONFIG_FILENAME, MODULE_CONFIG_INVALID_KEY } = require('../config/constant');
|
|
3
3
|
const { fail } = require('./log');
|
|
4
4
|
const { resolve, isObject, isArray } = require('./widgets');
|
|
5
5
|
|
|
@@ -98,7 +98,7 @@ const getAppJsonContent = (sourceAppJsonPath) => {
|
|
|
98
98
|
// 加入默认值
|
|
99
99
|
appJson.subpackages = [];
|
|
100
100
|
appJson.pages = [];
|
|
101
|
-
appJson.plugins = {};
|
|
101
|
+
// appJson.plugins = {};
|
|
102
102
|
delete appJson.entranceDeclare;
|
|
103
103
|
return appJson;
|
|
104
104
|
};
|
|
@@ -116,6 +116,60 @@ const updateSubpackages = (appJson, modulesConfig) => {
|
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* 处理合并subpackages后的appjson, 整理重复不合法的地方
|
|
121
|
+
* @param {Object} appJson appjson
|
|
122
|
+
*/
|
|
123
|
+
const processAppJson = (appJson) => {
|
|
124
|
+
const { subpackages } = appJson;
|
|
125
|
+
const pluginsMap = {};
|
|
126
|
+
Object.keys(appJson.plugins || {}).forEach(key => pluginsMap[key] = ['app.json']);
|
|
127
|
+
const subps = subpackages.map((subp) => {
|
|
128
|
+
const invalidKeys = [];
|
|
129
|
+
Object.keys(subp).forEach((key) => {
|
|
130
|
+
if (key === 'plugins') {
|
|
131
|
+
Object.keys(subp.plugins).forEach((pk) => {
|
|
132
|
+
pluginsMap[pk] ? pluginsMap[pk].push(`分包${subp.name}`) : pluginsMap[pk] = [`分包${subp.name}`];
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (MODULE_CONFIG_INVALID_KEY.indexOf(key) > -1) {
|
|
137
|
+
// 如果分包配置中有不支持的key,则错误提醒
|
|
138
|
+
invalidKeys.push(key);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (['requiredBackgroundModes', 'embeddedAppIdList'].indexOf(key) > -1) {
|
|
142
|
+
// 提到appjson最上层处理
|
|
143
|
+
const preVal = appJson[key];
|
|
144
|
+
// eslint-disable-next-line
|
|
145
|
+
preVal ? appJson[key] = Array.from(new Set(preVal
|
|
146
|
+
// eslint-disable-next-line
|
|
147
|
+
.slice(0).concat(subp[key]))) : appJson[key] = subp[key].slice(0);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
if (invalidKeys.length) {
|
|
152
|
+
fail(`不支持分包${subp?.name}配置${invalidKeys.join(',')}\n`);
|
|
153
|
+
}
|
|
154
|
+
// eslint-disable-next-line
|
|
155
|
+
invalidKeys.concat(['requiredBackgroundModes', 'embeddedAppIdList']).forEach(k => delete subp[k]);
|
|
156
|
+
return subp;
|
|
157
|
+
});
|
|
158
|
+
// 如果plugins重复,则错误提示
|
|
159
|
+
const pluginsErrMsg = Object.keys(pluginsMap).map((pk) => {
|
|
160
|
+
if (pluginsMap[pk].length > 1) {
|
|
161
|
+
return `${pluginsMap[pk].join(',')}重复配置plugin(${pk});`;
|
|
162
|
+
}
|
|
163
|
+
return '';
|
|
164
|
+
})
|
|
165
|
+
.reduce((pre, cur) => pre + cur, '');
|
|
166
|
+
if (pluginsErrMsg) {
|
|
167
|
+
fail(pluginsErrMsg);
|
|
168
|
+
}
|
|
169
|
+
// eslint-disable-next-line
|
|
170
|
+
appJson.subpackages = subps;
|
|
171
|
+
};
|
|
172
|
+
|
|
119
173
|
|
|
120
174
|
/**
|
|
121
175
|
* 动态生成编译后的app.json
|
|
@@ -130,10 +184,12 @@ function buildOutputAppJson(tmsConfig, modules) {
|
|
|
130
184
|
const appJson = getAppJsonContent(resolve('./app.json'));
|
|
131
185
|
// 更新app.json中的subpackages
|
|
132
186
|
updateSubpackages(appJson, modulesConfig);
|
|
187
|
+
// 处理appJson中重复||冲突的地方
|
|
188
|
+
processAppJson(appJson);
|
|
133
189
|
// 更新主包,需在subpackages处理完成后执行, pages/
|
|
134
190
|
updateMainPackages(appJson, tmsConfig.mainPackages, DEFAULT_MODULE_DIR);
|
|
135
191
|
|
|
136
|
-
fs.writeFileSync(resolve(`${tmsConfig.
|
|
192
|
+
fs.writeFileSync(resolve(`${tmsConfig.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
|
|
137
193
|
|
|
138
194
|
return appJson;
|
|
139
195
|
}
|
|
@@ -64,6 +64,7 @@ async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo) {
|
|
|
64
64
|
const globalInstance = getGlobalInstance();
|
|
65
65
|
const moduleInCache = globalInstance.getModuleCache(httpRepoUrl, cloneBranch);
|
|
66
66
|
|
|
67
|
+
|
|
67
68
|
try {
|
|
68
69
|
if (!moduleInCache) {
|
|
69
70
|
await downloadRepoForGit(httpRepoUrl, sourcePath, cloneBranch);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
const strip = require('strip-comments');
|
|
3
|
+
// 匹配规则
|
|
4
|
+
const MATCH_RULE = new RegExp(/@import *(?:url\(['"]?([^'")]+)['"]?\)|['"]([^'"]+)['"]);?/g);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 获取样式文件中的@import语句
|
|
8
|
+
* @param code 代码片段
|
|
9
|
+
* @returns 结果数组
|
|
10
|
+
*/
|
|
11
|
+
const findCssImports = (code) => {
|
|
12
|
+
// 将buffer转成字符串
|
|
13
|
+
code = code.toString();
|
|
14
|
+
// 去除注释
|
|
15
|
+
code = strip.block(code);
|
|
16
|
+
// 定义最后返回的结果
|
|
17
|
+
const result = [];
|
|
18
|
+
let matchList;
|
|
19
|
+
// 循环遍历代码段,直至匹配结果为空
|
|
20
|
+
while ((matchList = MATCH_RULE.exec(code))) {
|
|
21
|
+
// 存入结果数组
|
|
22
|
+
result.push(matchList?.[1] || matchList?.[2]);
|
|
23
|
+
}
|
|
24
|
+
// 返回结果
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
findCssImports,
|
|
30
|
+
};
|
package/src/utils/io.js
CHANGED
|
@@ -6,6 +6,17 @@ const path = require('path');
|
|
|
6
6
|
* @returns
|
|
7
7
|
*/
|
|
8
8
|
const isDirEmpty = dirname => fs.promises.readdir(dirname).then(files => files.length === 0);
|
|
9
|
+
|
|
10
|
+
// 判断是否是文件
|
|
11
|
+
const isFile = (pathName) => {
|
|
12
|
+
try {
|
|
13
|
+
const stat = fs.lstatSync(pathName);
|
|
14
|
+
return stat.isFile();
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
9
20
|
/**
|
|
10
21
|
* 确保目录存在,不存在就创建一个
|
|
11
22
|
* @param {*} dirname 目录名
|
|
@@ -26,13 +37,31 @@ const copyFile = function (src, dest) {
|
|
|
26
37
|
fs.copyFileSync(src, dest);
|
|
27
38
|
};
|
|
28
39
|
|
|
40
|
+
// 判断文件内容是否一致,不一致再进行拷贝
|
|
41
|
+
function diffContentCopyFile(originFile, destFile) {
|
|
42
|
+
if (fs.existsSync(destFile)) {
|
|
43
|
+
const depDestContent = fs.readFileSync(destFile, 'utf8');
|
|
44
|
+
const depOriginContent = fs.readFileSync(originFile, 'utf8');
|
|
45
|
+
if (depDestContent !== depOriginContent) {
|
|
46
|
+
console.log(`拷贝${originFile}内容到${destFile}`);
|
|
47
|
+
copyFile(originFile, destFile);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
console.log(`拷贝${originFile}内容到${destFile}`);
|
|
51
|
+
copyFile(originFile, destFile);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
29
55
|
// 添加后缀
|
|
30
56
|
function ext(filePath, extensions) {
|
|
31
57
|
let newFilePath = filePath;
|
|
58
|
+
let extPath = '';
|
|
59
|
+
// try catch需要包裹:用来处理'./lib/timer'没有后缀的情况
|
|
32
60
|
try {
|
|
33
61
|
const stat = fs.lstatSync(newFilePath);
|
|
34
62
|
if (stat.isDirectory()) {
|
|
35
|
-
|
|
63
|
+
extPath = newFilePath[newFilePath.length - 1] === '/' ? 'index' : '/index';
|
|
64
|
+
newFilePath += extPath;
|
|
36
65
|
}
|
|
37
66
|
} catch (e) {}
|
|
38
67
|
|
|
@@ -40,16 +69,24 @@ function ext(filePath, extensions) {
|
|
|
40
69
|
const file = newFilePath.endsWith(ext) ? newFilePath : newFilePath + ext;
|
|
41
70
|
if (fs.existsSync(file)) {
|
|
42
71
|
return {
|
|
43
|
-
file,
|
|
44
72
|
ext,
|
|
73
|
+
extPath: extPath + ext,
|
|
74
|
+
file,
|
|
45
75
|
};
|
|
46
76
|
}
|
|
47
77
|
}
|
|
48
|
-
return
|
|
78
|
+
return {
|
|
79
|
+
ext: '',
|
|
80
|
+
extPath,
|
|
81
|
+
file: filePath,
|
|
82
|
+
};
|
|
49
83
|
}
|
|
50
84
|
|
|
51
85
|
// 判断文件是否在某个目录
|
|
52
86
|
const fileInDir = (dir, file) => {
|
|
87
|
+
if (!fs.existsSync(dir) || !fs.existsSync(file)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
53
90
|
const relativePath = path.relative(dir, file);
|
|
54
91
|
if (relativePath.startsWith('..')) {
|
|
55
92
|
return false;
|
|
@@ -57,10 +94,13 @@ const fileInDir = (dir, file) => {
|
|
|
57
94
|
return true;
|
|
58
95
|
};
|
|
59
96
|
|
|
97
|
+
|
|
60
98
|
module.exports = {
|
|
61
99
|
isDirEmpty,
|
|
62
100
|
copyFile,
|
|
101
|
+
diffContentCopyFile,
|
|
63
102
|
ensureDirExist,
|
|
64
103
|
ext,
|
|
65
104
|
fileInDir,
|
|
105
|
+
isFile,
|
|
66
106
|
};
|
package/src/utils/widgets.js
CHANGED
|
@@ -7,7 +7,7 @@ const fs = require('fs');
|
|
|
7
7
|
const shelljs = require('shelljs');
|
|
8
8
|
const download = require('download-git-repo');
|
|
9
9
|
const chalk = require('chalk');
|
|
10
|
-
const
|
|
10
|
+
const shelljsOptions = { slient: true };
|
|
11
11
|
|
|
12
12
|
// 获取当前目录
|
|
13
13
|
const cwd = process.cwd();
|
|
@@ -96,7 +96,7 @@ function downloadRepo(dest, downloadOptions = { repoUrl: '', gitUrl: '', branch:
|
|
|
96
96
|
function downloadRepoForGit(url, dest, branch) {
|
|
97
97
|
const cwd = process.cwd();
|
|
98
98
|
|
|
99
|
-
return new Promise((resolve) => {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
100
|
// 如果目标目录不存在
|
|
101
101
|
if (fs.existsSync(dest)) {
|
|
102
102
|
shelljs.rm('-rf', path.join(dest));
|
|
@@ -105,7 +105,10 @@ function downloadRepoForGit(url, dest, branch) {
|
|
|
105
105
|
shelljs.mkdir('-p', dest);
|
|
106
106
|
shelljs.cd(dest);
|
|
107
107
|
|
|
108
|
-
shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`,
|
|
108
|
+
const gitCloneRes = shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`, shelljsOptions);
|
|
109
|
+
if (gitCloneRes.code !== 0) {
|
|
110
|
+
reject(gitCloneRes.stderr);
|
|
111
|
+
}
|
|
109
112
|
|
|
110
113
|
shelljs.cd(cwd);
|
|
111
114
|
resolve();
|
package/CHANGELOG.md
DELETED
|
File without changes
|