@tmsfe/tmskit 0.0.36 → 0.0.38

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/dist/index.cjs.js CHANGED
@@ -9,25 +9,27 @@ var require$$0$2 = require('shelljs');
9
9
  var require$$4 = require('glob-ignore');
10
10
  var require$$1$2 = require('os');
11
11
  var require$$0$3 = require('lodash');
12
+ var require$$1$3 = require('preprocess');
13
+ var require$$4$1 = require('json5');
12
14
  var require$$0$4 = require('async');
13
- var require$$1$3 = require('ejs');
14
- var require$$1$4 = require('inquirer');
15
+ var require$$1$4 = require('ejs');
16
+ var require$$1$5 = require('inquirer');
15
17
  var require$$0$5 = require('metalsmith');
16
18
  var require$$0$6 = require('request');
17
19
  var require$$10 = require('unzipper');
18
- var require$$1$5 = require('crypto');
20
+ var require$$1$6 = require('crypto');
19
21
  var require$$0$7 = require('miniprogram-ci');
20
- var require$$1$6 = require('fs-extra');
21
- var require$$1$7 = require('semver');
22
- var require$$0$8 = require('gulp');
22
+ var require$$1$7 = require('fs-extra');
23
+ var require$$1$8 = require('semver');
24
+ var require$$0$8 = require('through2');
25
+ var require$$0$9 = require('gulp');
23
26
  var require$$2 = require('minimatch');
24
27
  var require$$3$1 = require('gulp-if');
25
- var require$$6 = require('through2');
26
- var require$$0$9 = require('object-assign');
28
+ var require$$0$a = require('object-assign');
27
29
  var require$$3$2 = require('fancy-log');
28
- var require$$4$1 = require('ansi-colors');
30
+ var require$$4$2 = require('ansi-colors');
29
31
  var require$$5 = require('chokidar');
30
- var require$$6$1 = require('readable-stream');
32
+ var require$$6 = require('readable-stream');
31
33
  var require$$7 = require('vinyl-file');
32
34
  var require$$8 = require('vinyl');
33
35
  var require$$9 = require('anymatch');
@@ -35,7 +37,7 @@ var require$$11 = require('glob-parent');
35
37
  var require$$2$1 = require('plugin-error');
36
38
  var require$$10$1 = require('path-is-absolute');
37
39
  var require$$12$1 = require('slash');
38
- var require$$1$8 = require('commander');
40
+ var require$$1$9 = require('commander');
39
41
 
40
42
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
41
43
 
@@ -48,25 +50,27 @@ var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
48
50
  var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
49
51
  var require$$1__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$1$2);
50
52
  var require$$0__default$3 = /*#__PURE__*/_interopDefaultLegacy(require$$0$3);
51
- var require$$0__default$4 = /*#__PURE__*/_interopDefaultLegacy(require$$0$4);
52
53
  var require$$1__default$3 = /*#__PURE__*/_interopDefaultLegacy(require$$1$3);
54
+ var require$$4__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$4$1);
55
+ var require$$0__default$4 = /*#__PURE__*/_interopDefaultLegacy(require$$0$4);
53
56
  var require$$1__default$4 = /*#__PURE__*/_interopDefaultLegacy(require$$1$4);
57
+ var require$$1__default$5 = /*#__PURE__*/_interopDefaultLegacy(require$$1$5);
54
58
  var require$$0__default$5 = /*#__PURE__*/_interopDefaultLegacy(require$$0$5);
55
59
  var require$$0__default$6 = /*#__PURE__*/_interopDefaultLegacy(require$$0$6);
56
60
  var require$$10__default = /*#__PURE__*/_interopDefaultLegacy(require$$10);
57
- var require$$1__default$5 = /*#__PURE__*/_interopDefaultLegacy(require$$1$5);
58
- var require$$0__default$7 = /*#__PURE__*/_interopDefaultLegacy(require$$0$7);
59
61
  var require$$1__default$6 = /*#__PURE__*/_interopDefaultLegacy(require$$1$6);
62
+ var require$$0__default$7 = /*#__PURE__*/_interopDefaultLegacy(require$$0$7);
60
63
  var require$$1__default$7 = /*#__PURE__*/_interopDefaultLegacy(require$$1$7);
64
+ var require$$1__default$8 = /*#__PURE__*/_interopDefaultLegacy(require$$1$8);
61
65
  var require$$0__default$8 = /*#__PURE__*/_interopDefaultLegacy(require$$0$8);
66
+ var require$$0__default$9 = /*#__PURE__*/_interopDefaultLegacy(require$$0$9);
62
67
  var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
63
68
  var require$$3__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$3$1);
64
- var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
65
- var require$$0__default$9 = /*#__PURE__*/_interopDefaultLegacy(require$$0$9);
69
+ var require$$0__default$a = /*#__PURE__*/_interopDefaultLegacy(require$$0$a);
66
70
  var require$$3__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$3$2);
67
- var require$$4__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$4$1);
71
+ var require$$4__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$4$2);
68
72
  var require$$5__default = /*#__PURE__*/_interopDefaultLegacy(require$$5);
69
- var require$$6__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$6$1);
73
+ var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
70
74
  var require$$7__default = /*#__PURE__*/_interopDefaultLegacy(require$$7);
71
75
  var require$$8__default = /*#__PURE__*/_interopDefaultLegacy(require$$8);
72
76
  var require$$9__default = /*#__PURE__*/_interopDefaultLegacy(require$$9);
@@ -74,11 +78,11 @@ var require$$11__default = /*#__PURE__*/_interopDefaultLegacy(require$$11);
74
78
  var require$$2__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$2$1);
75
79
  var require$$10__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$10$1);
76
80
  var require$$12__default = /*#__PURE__*/_interopDefaultLegacy(require$$12$1);
77
- var require$$1__default$8 = /*#__PURE__*/_interopDefaultLegacy(require$$1$8);
81
+ var require$$1__default$9 = /*#__PURE__*/_interopDefaultLegacy(require$$1$9);
78
82
 
79
83
  var src$3 = {};
80
84
 
81
- const chalk$4 = require$$3__default;
85
+ const chalk$5 = require$$3__default;
82
86
  const moment$1 = require$$1__default;
83
87
 
84
88
  /**
@@ -114,7 +118,7 @@ const succeed$2 = (message = '') => {
114
118
  * @returns {undefined} 无
115
119
  */
116
120
  const warn$2 = message => {
117
- console.log(`${moment$1().format('YYYY-MM-DD HH:mm:ss')}`, chalk$4.yellow(message));
121
+ console.log(`${moment$1().format('YYYY-MM-DD HH:mm:ss')}`, chalk$5.yellow(message));
118
122
  };
119
123
  const info$j = (...args) => console.log(`${moment$1().format('YYYY-MM-DD HH:mm:ss')}`, ...args);
120
124
  const infoNoTime$1 = (...args) => console.log(...args);
@@ -127,7 +131,7 @@ var log$1 = {
127
131
  };
128
132
 
129
133
  const ora$2 = require$$0__default;
130
- const path$g = require$$1__default$1;
134
+ const path$h = require$$1__default$1;
131
135
  const fs$j = require$$0__default$1;
132
136
  const shelljs$7 = require$$0__default$2;
133
137
  const glob = require$$4__default;
@@ -142,7 +146,7 @@ const shelljsOptions = {
142
146
  // 获取当前目录
143
147
  const cwd = process.cwd();
144
148
  function resolve$j(...args) {
145
- return path$g.resolve(cwd, ...args);
149
+ return path$h.resolve(cwd, ...args);
146
150
  }
147
151
 
148
152
  /**
@@ -175,7 +179,7 @@ function downloadRepoForGit$1(url, dest, branch) {
175
179
  return new Promise((resolve, reject) => {
176
180
  // 如果目标目录不存在
177
181
  if (fs$j.existsSync(dest)) {
178
- shelljs$7.rm('-rf', path$g.join(dest));
182
+ shelljs$7.rm('-rf', path$h.join(dest));
179
183
  }
180
184
  shelljs$7.mkdir('-p', dest);
181
185
  shelljs$7.cd(dest);
@@ -296,7 +300,7 @@ const mergeMap$1 = function (obj, src) {
296
300
  return obj;
297
301
  };
298
302
  const relativeCwdPath$1 = function (file) {
299
- return path$g.relative(process.cwd(), file);
303
+ return path$h.relative(process.cwd(), file);
300
304
  };
301
305
 
302
306
  /**
@@ -383,35 +387,35 @@ var widgets = {
383
387
 
384
388
  var tmsMpconfig = {exports: {}};
385
389
 
386
- const path$f = require$$1__default$1;
390
+ const path$g = require$$1__default$1;
387
391
  const os = require$$1__default$2;
388
392
 
389
393
  // 用户目录
390
394
  const HOME_DIR = os.homedir();
391
395
 
392
396
  // 所有文件的缓存目录
393
- const CACHE_DIR = path$f.resolve(HOME_DIR, '.tmskit');
397
+ const CACHE_DIR = path$g.resolve(HOME_DIR, '.tmskit');
394
398
 
395
399
  // 版本管理的CDN地址
396
400
  const VERSION_URL = 'https://tms-web-1g1czzwka2fd06f2-1301126013.tcloudbaseapp.com/tmskit-template/version.json';
397
401
 
398
402
  // version缓存文件
399
- const VERSION_CACHE_FILE = path$f.resolve(CACHE_DIR, 'version_cache_file.json');
403
+ const VERSION_CACHE_FILE = path$g.resolve(CACHE_DIR, 'version_cache_file.json');
400
404
 
401
405
  // npm缓存文件
402
- const NPM_CACHE_FILE$1 = path$f.resolve(CACHE_DIR, 'npm_cache_file.json');
406
+ const NPM_CACHE_FILE$1 = path$g.resolve(CACHE_DIR, 'npm_cache_file.json');
403
407
 
404
408
  // 脚手架模板代码所在目录
405
- const TEMPLATE_DIR$1 = path$f.resolve(CACHE_DIR, 'template');
409
+ const TEMPLATE_DIR$1 = path$g.resolve(CACHE_DIR, 'template');
406
410
 
407
411
  // 第三方模块源码存放的临时缓存目录
408
- const MODULE_CODE_DIR$2 = path$f.resolve(CACHE_DIR, 'modules_code');
412
+ const MODULE_CODE_DIR$2 = path$g.resolve(CACHE_DIR, 'modules_code');
409
413
 
410
414
  // 缓存分包node_modules的目录
411
- const NODE_MODULES_DIR$2 = path$f.resolve(CACHE_DIR, 'node_modules');
415
+ const NODE_MODULES_DIR$2 = path$g.resolve(CACHE_DIR, 'node_modules');
412
416
 
413
417
  // 扩展命令源码的存放处
414
- const EXTEND_CMD$1 = path$f.resolve(CACHE_DIR, 'cmd');
418
+ const EXTEND_CMD$1 = path$g.resolve(CACHE_DIR, 'cmd');
415
419
 
416
420
  // 创建模板的名称
417
421
  const TEMPLATE_NAME$1 = 'tmskit-template';
@@ -437,7 +441,7 @@ const MODULE_CONFIG_FILENAME = 'module.config.json';
437
441
 
438
442
  // 默认的webpack entry
439
443
  const DEFAULT_WEBPACK_ENTRY = {
440
- app: path$f.resolve(process.cwd(), 'app')
444
+ app: path$g.resolve(process.cwd(), 'app')
441
445
  };
442
446
 
443
447
  // 默认从源码拷贝到编译后的配置
@@ -544,6 +548,8 @@ var defaultTmsConfig = {
544
548
  const loadash = require$$0__default$3;
545
549
  const fs = require$$0__default$1;
546
550
  const path = require$$1__default$1;
551
+ const pp = require$$1__default$3;
552
+ const JSON5 = require$$4__default$1;
547
553
  const {
548
554
  TMS_CONFIG_FILENAME,
549
555
  MODULE_CONFIG_FILENAME,
@@ -604,9 +610,18 @@ var defaultTmsConfig = {
604
610
  modules.all = tmsConfig.modules;
605
611
  tmsConfig.modules = modules;
606
612
  }
607
- // 合并默认值
608
- const res = loadash.mergeWith(tmsConfig, tmsPrivateCf, (objValue, srcValue) => {
609
- if (loadash.isArray(objValue) && objValue[0] && loadash.isObject(objValue[0])) {
613
+ // 使用自定义的合并策略:
614
+ // 1. templateVars 字段做浅合并(即把 tms.config.js 中的和 tms.private.config.js 中的对象合并,
615
+ // 如果存在同名字段则以 tms.private.config.js 中的为准)。
616
+ // 2. 对数组(并且数组元素为对象的情况)执行拼接
617
+ const res = loadash.mergeWith({}, tmsConfig, tmsPrivateCf, (objValue, srcValue, key) => {
618
+ if (key === 'templateVars') {
619
+ return {
620
+ ...(objValue || {}),
621
+ ...(srcValue || {})
622
+ };
623
+ }
624
+ if (Array.isArray(objValue) && objValue[0] && isObject(objValue[0])) {
610
625
  return objValue.concat(srcValue);
611
626
  }
612
627
  });
@@ -674,13 +689,20 @@ var defaultTmsConfig = {
674
689
  * @param {array} modules 用户要编译的模块列表
675
690
  * @param { string } appName 小程序的名称
676
691
  */
677
- function getModulesConfig(modules = [], appName) {
692
+ function getModulesConfig(modules = [], tmsConfig) {
693
+ const {
694
+ appName
695
+ } = tmsConfig;
678
696
  const modulesConfig = [];
679
697
  modules.forEach(moduleItem => {
680
698
  const moduleConfigPath = resolve(moduleItem.path, MODULE_CONFIG_FILENAME);
681
699
  let moduleConfig;
682
700
  try {
683
- moduleConfig = JSON.parse(fs.readFileSync(moduleConfigPath, 'utf-8'));
701
+ // 模板渲染:先将 module.config.json 转为字符串,然后通过 preprocess 渲染
702
+ const moduleConfigJsonStr = fs.readFileSync(moduleConfigPath, 'utf-8');
703
+ const preprocessedStr = pp.preprocess(moduleConfigJsonStr, tmsConfig.templateVars || {}, 'json');
704
+ // fs.writeFileSync(resolve(moduleConfigPath), moduleConfigJsonStr, 'utf8');
705
+ moduleConfig = JSON5.parse(preprocessedStr);
684
706
  } catch (e) {
685
707
  throw new Error(`${moduleConfigPath}json解析报错: ${e}`);
686
708
  }
@@ -785,11 +807,11 @@ var defaultTmsConfig = {
785
807
  allModules.set(moduleItem.moduleName, moduleItem);
786
808
  }
787
809
  if (errorIsQuit) {
788
- throw new Error(`${moduleItem.moduleName}模块的配置文件module.config.json在${moduleItem.path}目录下没有找到`);
810
+ throw new Error(`${moduleItem.moduleName}模块的配置文件module.config.json在${moduleItem.path}目录下没有找到 ${moduleConfigPath}`);
789
811
  }
790
812
  return;
791
813
  }
792
- const [moduleConfig = {}] = getModulesConfig([moduleItem], tmsConfig.appName);
814
+ const [moduleConfig = {}] = getModulesConfig([moduleItem], tmsConfig);
793
815
  if (!allModules.has(moduleItem.moduleName)) {
794
816
  allModules.set(moduleItem.moduleName, checkModuleItem(tmsConfig, moduleItem, moduleConfig));
795
817
  const dependenciesModules = getModulesByModuleNames(tmsConfig, moduleConfig === null || moduleConfig === void 0 ? void 0 : moduleConfig.dependencies);
@@ -818,7 +840,7 @@ var defaultTmsConfig = {
818
840
  })(tmsMpconfig);
819
841
 
820
842
  const fs$i = require$$0__default$1;
821
- const path$e = require$$1__default$1;
843
+ const path$f = require$$1__default$1;
822
844
  const {
823
845
  info: info$h
824
846
  } = log$1;
@@ -859,7 +881,7 @@ const copyFile = function (src, dest) {
859
881
  if (fs$i.existsSync(dest)) {
860
882
  fs$i.unlinkSync(dest);
861
883
  }
862
- const dir = path$e.dirname(dest);
884
+ const dir = path$f.dirname(dest);
863
885
  ensureDirExist$6(dir);
864
886
  fs$i.copyFileSync(src, dest);
865
887
  };
@@ -913,7 +935,7 @@ const fileInDir = (dir, file) => {
913
935
  if (!fs$i.existsSync(dir) || !fs$i.existsSync(file)) {
914
936
  return false;
915
937
  }
916
- const relativePath = path$e.relative(dir, file);
938
+ const relativePath = path$f.relative(dir, file);
917
939
  if (relativePath.startsWith('..')) {
918
940
  return false;
919
941
  }
@@ -924,7 +946,7 @@ function findAllFilesOfDir(dir) {
924
946
  function listFile(dir) {
925
947
  const arr = fs$i.readdirSync(dir);
926
948
  arr.forEach(item => {
927
- const fullPath = path$e.join(dir, item);
949
+ const fullPath = path$f.join(dir, item);
928
950
  const stats = fs$i.statSync(fullPath);
929
951
  if (stats.isDirectory()) {
930
952
  listFile(fullPath);
@@ -949,7 +971,7 @@ var io$3 = {
949
971
  };
950
972
 
951
973
  const async = require$$0__default$4;
952
- const ejs = require$$1__default$3;
974
+ const ejs = require$$1__default$4;
953
975
  const render$1 = (files, metalsmith, next) => {
954
976
  const keys = Object.keys(files);
955
977
  const metadata = metalsmith.metadata();
@@ -965,7 +987,7 @@ const render$1 = (files, metalsmith, next) => {
965
987
  var render_1 = render$1;
966
988
 
967
989
  const fs$h = require$$0__default$1;
968
- const inquirer$1 = require$$1__default$4;
990
+ const inquirer$1 = require$$1__default$5;
969
991
  const {
970
992
  resolve: resolve$i
971
993
  } = widgets;
@@ -1076,10 +1098,10 @@ const report$a = (name, attrs = {}) => {
1076
1098
  };
1077
1099
  var report_1 = report$a;
1078
1100
 
1079
- const path$d = require$$1__default$1;
1101
+ const path$e = require$$1__default$1;
1080
1102
  const fs$g = require$$0__default$1;
1081
1103
  const shelljs$6 = require$$0__default$2;
1082
- const inquirer = require$$1__default$4;
1104
+ const inquirer = require$$1__default$5;
1083
1105
  const {
1084
1106
  TEMPLATE_DIR,
1085
1107
  TEMPLATE_URL,
@@ -1154,7 +1176,7 @@ function downloadAndUnZipTemplate(templateDir, templateUrl, templateName) {
1154
1176
  */
1155
1177
  async function create(projectName) {
1156
1178
  const cwd = process.cwd();
1157
- const targetDir = path$d.resolve(cwd, projectName);
1179
+ const targetDir = path$e.resolve(cwd, projectName);
1158
1180
  const {
1159
1181
  projectType
1160
1182
  } = await inquirer.prompt(CREATE_TEMPLATE_QUESTION);
@@ -1177,7 +1199,7 @@ async function create(projectName) {
1177
1199
  await downloadAndUnZipTemplate(TEMPLATE_DIR, TEMPLATE_URL, TEMPLATE_NAME);
1178
1200
 
1179
1201
  // 生成模板(1. 询问问题, 2. ejs生成模板 3.生成到目标目录)
1180
- generator(path$d.join(TEMPLATE_DIR, TEMPLATE_NAME, projectType), targetDir).then(() => {
1202
+ generator(path$e.join(TEMPLATE_DIR, TEMPLATE_NAME, projectType), targetDir).then(() => {
1181
1203
  shelljs$6.cd(projectName);
1182
1204
  const hookFilePath = resolve$h(projectName, TEMPLATE_TKIT_DIR, 'hooks.js');
1183
1205
  if (fs$g.existsSync(hookFilePath)) {
@@ -1207,7 +1229,7 @@ async function create(projectName) {
1207
1229
  var create_1 = create;
1208
1230
 
1209
1231
  const fs$f = require$$0__default$1;
1210
- const path$c = require$$1__default$1;
1232
+ const path$d = require$$1__default$1;
1211
1233
  const shellJs$3 = require$$0__default$2;
1212
1234
  const {
1213
1235
  ensureDirExist: ensureDirExist$5
@@ -1272,7 +1294,7 @@ function loadExtendCmd$1() {
1272
1294
  Object.keys(deps).forEach(name => {
1273
1295
  // 检索cmd的npm包
1274
1296
  if (!/^tmskit-cmd-|^@[^/]+\/tmskit-cmd-/.test(name)) return false;
1275
- const cmdConfig = path$c.join(cmdNpmDir, name, 'tms.config.js');
1297
+ const cmdConfig = path$d.join(cmdNpmDir, name, 'tms.config.js');
1276
1298
  if (fs$f.existsSync(cmdConfig)) {
1277
1299
  cmdConfigs.push(cmdConfig);
1278
1300
  }
@@ -1338,6 +1360,7 @@ var handleError_1 = {
1338
1360
 
1339
1361
  /* eslint-disable no-param-reassign */
1340
1362
  const fs$e = require$$0__default$1;
1363
+ const pp$1 = require$$1__default$3;
1341
1364
  const {
1342
1365
  getSubPackages: getSubPackages$3,
1343
1366
  getModulesConfig
@@ -1366,7 +1389,7 @@ const report$8 = report_1;
1366
1389
  */
1367
1390
  function updateMainPackages(appJson, mainPackages = []) {
1368
1391
  let foundMainPackages = appJson.subpackages.filter(subpackage => mainPackages.includes(subpackage.name));
1369
- if (foundMainPackages.length === 0) {
1392
+ if (foundMainPackages.length === 0 && appJson.pages.length === 0) {
1370
1393
  // 没找到主包
1371
1394
  foundMainPackages = [appJson.subpackages[0]];
1372
1395
  }
@@ -1401,8 +1424,8 @@ const getAppJsonContent = sourceAppJsonPath => {
1401
1424
  }
1402
1425
  const appJson = JSON.parse(fs$e.readFileSync(sourceAppJsonPath), 'utf-8');
1403
1426
  // 加入默认值
1404
- appJson.subpackages = [];
1405
- appJson.pages = [];
1427
+ appJson.subpackages = appJson.subpackages || [];
1428
+ appJson.pages = appJson.pages || [];
1406
1429
  return appJson;
1407
1430
  };
1408
1431
 
@@ -1462,15 +1485,15 @@ const fixAppJson = appJson => {
1462
1485
  * @param {array} modules 用户要编译的模块列表
1463
1486
  * @returns
1464
1487
  */
1465
- async function buildOutputAppJson$2(tmsConfig, modules) {
1488
+ async function buildOutputAppJson$3(tmsConfig, modules) {
1466
1489
  try {
1467
1490
  var _tmsConfig$hooks;
1468
1491
  // 获取所有模块,合并模块依赖的模块
1469
- const modulesConfig = getModulesConfig(modules, tmsConfig.appName, false);
1492
+ const modulesConfig = getModulesConfig(modules, tmsConfig, false);
1470
1493
  // 获取所有的分包
1471
1494
  const subPackages = getSubPackages$3(modulesConfig);
1472
1495
  // 获取app.json的配置
1473
- const appJson = getAppJsonContent(resolve$g('./app.json'));
1496
+ let appJson = getAppJsonContent(resolve$g('./app.json'));
1474
1497
 
1475
1498
  // 更新app.json中的subpackages
1476
1499
  appJson.subpackages = subPackages;
@@ -1480,7 +1503,12 @@ async function buildOutputAppJson$2(tmsConfig, modules) {
1480
1503
  fixAppJson(appJson);
1481
1504
  // 更新主包,需在subpackages处理完成后执行, pages/
1482
1505
  updateMainPackages(appJson, tmsConfig.mainPackages);
1483
- fs$e.writeFileSync(resolve$g(`${tmsConfig.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
1506
+
1507
+ // 模板渲染:先将 app.json 转为字符串,然后通过 preprocess 渲染
1508
+ const appJsonStr = JSON.stringify(appJson, null, 2);
1509
+ const preprocessedStr = pp$1.preprocess(appJsonStr, tmsConfig.templateVars || {}, 'json');
1510
+ fs$e.writeFileSync(resolve$g(`${tmsConfig.outputDir}/app.json`), preprocessedStr, 'utf8');
1511
+ appJson = JSON.parse(preprocessedStr);
1484
1512
  if (typeof (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$hooks = tmsConfig.hooks) === null || _tmsConfig$hooks === void 0 ? void 0 : _tmsConfig$hooks.updateAppJson) === 'function') {
1485
1513
  var _tmsConfig$hooks2;
1486
1514
  await (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$hooks2 = tmsConfig.hooks) === null || _tmsConfig$hooks2 === void 0 ? void 0 : _tmsConfig$hooks2.updateAppJson({
@@ -1499,14 +1527,14 @@ async function buildOutputAppJson$2(tmsConfig, modules) {
1499
1527
  }
1500
1528
  }
1501
1529
  var buildAppJson = {
1502
- buildOutputAppJson: buildOutputAppJson$2
1530
+ buildOutputAppJson: buildOutputAppJson$3
1503
1531
  };
1504
1532
 
1505
1533
  /**
1506
1534
  * 下载第三方代码
1507
1535
  */
1508
1536
  const MetalSmith = require$$0__default$5;
1509
- const crypto$2 = require$$1__default$5;
1537
+ const crypto$2 = require$$1__default$6;
1510
1538
  const {
1511
1539
  downloadRepoForGit,
1512
1540
  pullRepoForGit,
@@ -1544,7 +1572,7 @@ function replaceGitUrlAccount(httpRepoUrl, moduleName) {
1544
1572
  } = (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$gitAccount = tmsConfig.gitAccount) === null || _tmsConfig$gitAccount === void 0 ? void 0 : _tmsConfig$gitAccount[moduleName]) || (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$gitAccount2 = tmsConfig.gitAccount) === null || _tmsConfig$gitAccount2 === void 0 ? void 0 : _tmsConfig$gitAccount2[httpRepoUrl]) || (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$gitAccount3 = tmsConfig.gitAccount) === null || _tmsConfig$gitAccount3 === void 0 ? void 0 : _tmsConfig$gitAccount3[group]) || {};
1545
1573
  const urlPrefixReg = /http(s)?:\/\//;
1546
1574
  if (username && pass && urlPrefixReg.test(gitUrl)) {
1547
- gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${pass}@`);
1575
+ gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${encodeURIComponent(pass)}@`);
1548
1576
  }
1549
1577
  return gitUrl;
1550
1578
  }
@@ -1739,7 +1767,7 @@ var cloneModules_1 = {
1739
1767
  };
1740
1768
 
1741
1769
  const ci = require$$0__default$7;
1742
- const path$b = require$$1__default$1;
1770
+ const path$c = require$$1__default$1;
1743
1771
 
1744
1772
  /**
1745
1773
  * 获取小程序ci的Project对象
@@ -1752,7 +1780,7 @@ const getMpCi = ({
1752
1780
  privateKey = 'TODO'
1753
1781
  }) => {
1754
1782
  var _projectCg$packOption, _projectCg$packOption2;
1755
- const projectCg = require(path$b.join(projectPath, 'project.config.json'));
1783
+ const projectCg = require(path$c.join(projectPath, 'project.config.json'));
1756
1784
  const ignores = (projectCg === null || projectCg === void 0 ? void 0 : (_projectCg$packOption = projectCg.packOptions) === null || _projectCg$packOption === void 0 ? void 0 : (_projectCg$packOption2 = _projectCg$packOption.ignore) === null || _projectCg$packOption2 === void 0 ? void 0 : _projectCg$packOption2.map(({
1757
1785
  value
1758
1786
  }) => value)) || [];
@@ -1871,7 +1899,7 @@ var mpCi$2 = {
1871
1899
  };
1872
1900
 
1873
1901
  const fs$c = require$$0__default$1;
1874
- const path$a = require$$1__default$1;
1902
+ const path$b = require$$1__default$1;
1875
1903
  const {
1876
1904
  NPM_CACHE_FILE
1877
1905
  } = constant;
@@ -1890,7 +1918,7 @@ function getCache$1(projectDir, type) {
1890
1918
  function setCache$1(projectDir, type = 'miniprogram_npm', data) {
1891
1919
  const filePath = NPM_CACHE_FILE;
1892
1920
  if (!fs$c.existsSync(filePath)) {
1893
- const dir = path$a.dirname(filePath);
1921
+ const dir = path$b.dirname(filePath);
1894
1922
  ensureDirExist$4(dir);
1895
1923
  fs$c.writeFileSync(filePath, '{}');
1896
1924
  }
@@ -1912,9 +1940,9 @@ var cache = {
1912
1940
  * 本文件主要负责项目或者分包依赖的npm的安装
1913
1941
  */
1914
1942
  const fs$b = require$$0__default$1;
1915
- const fsExtra = require$$1__default$6;
1916
- const crypto$1 = require$$1__default$5;
1917
- const path$9 = require$$1__default$1;
1943
+ const fsExtra = require$$1__default$7;
1944
+ const crypto$1 = require$$1__default$6;
1945
+ const path$a = require$$1__default$1;
1918
1946
  const shell = require$$0__default$2;
1919
1947
  const log = log$1;
1920
1948
  const {
@@ -1959,15 +1987,15 @@ const collectNpmTasksMap = (packageJsonFiles, cacheDir) => {
1959
1987
  };
1960
1988
  if (Object.keys(md5Obj.dependencies).length !== 0) {
1961
1989
  const md5Key = crypto$1.createHash('md5').update(JSON.stringify(md5Obj)).digest('hex');
1962
- const cacheNMPath = path$9.join(cacheDir, md5Key);
1963
- const cacheNMTarFile = path$9.join(cacheNMPath, 'node_modules.tar.gz');
1990
+ const cacheNMPath = path$a.join(cacheDir, md5Key);
1991
+ const cacheNMTarFile = path$a.join(cacheNMPath, 'node_modules.tar.gz');
1964
1992
 
1965
1993
  // 下载后,添加回调函数 (拷贝node_modules.tar.gz到编译目录并解压)
1966
1994
  const callback = {
1967
1995
  params: {
1968
1996
  cacheNMPath,
1969
1997
  cacheNMTarFile,
1970
- packageJsonDir: path$9.dirname(packageJsonPath),
1998
+ packageJsonDir: path$a.dirname(packageJsonPath),
1971
1999
  shell
1972
2000
  },
1973
2001
  fn: async (cacheNMPath, cacheNMTarFile, packageJsonDir, shell) => {
@@ -2080,7 +2108,7 @@ const findFilesByFilter = (startPath, filter) => {
2080
2108
  }
2081
2109
  const files = fs$b.readdirSync(startPath);
2082
2110
  files.forEach(file => {
2083
- const filename = path$9.join(startPath, file);
2111
+ const filename = path$a.join(startPath, file);
2084
2112
  const stat = fs$b.lstatSync(filename);
2085
2113
  // 当前文件是文件夹类型,继续递归
2086
2114
  if (stat.isDirectory()) {
@@ -2104,10 +2132,10 @@ const findFilesByFilter = (startPath, filter) => {
2104
2132
  const findAllPackageJson = (subRoots = [], contextDir) => {
2105
2133
  const packageJsonName = 'package.json'; // 查找文件名
2106
2134
  const cwd = contextDir || dirPath;
2107
- const result = [path$9.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
2135
+ const result = [path$a.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
2108
2136
 
2109
2137
  subRoots.forEach(subRoot => {
2110
- const toppath = path$9.join(cwd, subRoot.root); // 从该目录开始查找package.json文件
2138
+ const toppath = path$a.join(cwd, subRoot.root); // 从该目录开始查找package.json文件
2111
2139
  const list = findFilesByFilter(toppath, packageJsonName);
2112
2140
  result.push(...list);
2113
2141
  });
@@ -2119,7 +2147,7 @@ var npm = {
2119
2147
  findFilesByFilter
2120
2148
  };
2121
2149
 
2122
- const crypto = require$$1__default$5;
2150
+ const crypto = require$$1__default$6;
2123
2151
  const fs$a = require$$0__default$1;
2124
2152
  function fileMd5$1(filePath) {
2125
2153
  return new Promise((resolve, reject) => {
@@ -2142,12 +2170,12 @@ var md5 = {
2142
2170
  };
2143
2171
 
2144
2172
  const fs$9 = require$$0__default$1;
2145
- const semver$1 = require$$1__default$7;
2173
+ const semver$1 = require$$1__default$8;
2146
2174
  const {
2147
2175
  resolve: resolve$e,
2148
2176
  getAbsolutePath: getAbsolutePath$5
2149
2177
  } = widgets;
2150
- const path$8 = require$$1__default$1;
2178
+ const path$9 = require$$1__default$1;
2151
2179
  const shelljs$4 = require$$0__default$2;
2152
2180
  const {
2153
2181
  handleError: handleError$4
@@ -2165,7 +2193,7 @@ function collectPackageJson(subPackages, cwd, outputDir) {
2165
2193
  const packageJsonName = 'package.json'; // 查找文件名
2166
2194
  // 1.1根目录的package.json
2167
2195
  const packageArr = [{
2168
- srcPackageDir: path$8.join(cwd, packageJsonName),
2196
+ srcPackageDir: path$9.join(cwd, packageJsonName),
2169
2197
  destNpmDir: resolve$e(outputDir, 'node_modules')
2170
2198
  }];
2171
2199
  // 1.2模块的package.json
@@ -2214,11 +2242,11 @@ const checkPackageVersion$1 = packageArr => {
2214
2242
  const dependencies = readPackageDependencies(item.srcPackageDir);
2215
2243
  const dependenciesKeys = Object.keys(dependencies);
2216
2244
  for (const key of dependenciesKeys) {
2217
- const depPath = path$8.join(item.destNpmDir, key);
2245
+ const depPath = path$9.join(item.destNpmDir, key);
2218
2246
  if (!fs$9.existsSync(depPath)) {
2219
2247
  return true;
2220
2248
  }
2221
- const depPackagePath = path$8.join(depPath, 'package.json');
2249
+ const depPackagePath = path$9.join(depPath, 'package.json');
2222
2250
  if (fs$9.existsSync(depPackagePath)) {
2223
2251
  const packageData = require(depPackagePath);
2224
2252
  if (dependencies[key] === 'latest') {
@@ -2242,7 +2270,7 @@ var checkDependencies = {
2242
2270
 
2243
2271
  const shelljs$3 = require$$0__default$2;
2244
2272
  const fs$8 = require$$0__default$1;
2245
- const path$7 = require$$1__default$1;
2273
+ const path$8 = require$$1__default$1;
2246
2274
  const io$1 = io$3;
2247
2275
  const {
2248
2276
  createTask: createTask$4,
@@ -2342,7 +2370,7 @@ async function mpCiInstall(tmsConfig, subPackages, useCache) {
2342
2370
  if (useCache) {
2343
2371
  let flag = true;
2344
2372
  await Promise.all(packageJsonFiles.map(async item => {
2345
- const packageDir = path$7.dirname(item);
2373
+ const packageDir = path$8.dirname(item);
2346
2374
  const mpDir = resolve$d(`${packageDir}/miniprogram_npm`);
2347
2375
  const md5Value = await getMNPMd5(packageDir);
2348
2376
  const preCache = getCache(mpDir, 'miniprogram_npm');
@@ -2361,7 +2389,7 @@ async function mpCiInstall(tmsConfig, subPackages, useCache) {
2361
2389
 
2362
2390
  // 即将构建,在cache中标记开始
2363
2391
  await Promise.all(packageJsonFiles.map(async item => {
2364
- const packageDir = path$7.dirname(item);
2392
+ const packageDir = path$8.dirname(item);
2365
2393
  const mpDir = resolve$d(`${packageDir}/miniprogram_npm`);
2366
2394
  setCache(mpDir, 'miniprogram_npm', {
2367
2395
  md5: '',
@@ -2376,7 +2404,7 @@ async function mpCiInstall(tmsConfig, subPackages, useCache) {
2376
2404
 
2377
2405
  // 构建成功后,计算md5写入cache
2378
2406
  await Promise.all(packageJsonFiles.map(async item => {
2379
- const packageDir = path$7.dirname(item);
2407
+ const packageDir = path$8.dirname(item);
2380
2408
  const mpDir = resolve$d(`${packageDir}/miniprogram_npm`);
2381
2409
  const md5Value = await getMNPMd5(packageDir);
2382
2410
  setCache(mpDir, 'miniprogram_npm', {
@@ -2398,7 +2426,7 @@ async function getMNPMd5(cwd) {
2398
2426
  cwd,
2399
2427
  ...shellJsOption
2400
2428
  });
2401
- const tarDir = path$7.join(cwd, './miniprogram_npm.tar.gz');
2429
+ const tarDir = path$8.join(cwd, './miniprogram_npm.tar.gz');
2402
2430
  const md5Value = await fileMd5(tarDir);
2403
2431
  shelljs$3.rm('-rf', tarDir);
2404
2432
  return md5Value;
@@ -2415,7 +2443,7 @@ const {
2415
2443
  createTask: createTask$3
2416
2444
  } = widgets;
2417
2445
  const {
2418
- buildOutputAppJson: buildOutputAppJson$1
2446
+ buildOutputAppJson: buildOutputAppJson$2
2419
2447
  } = buildAppJson;
2420
2448
  const {
2421
2449
  MODULE_CODE_DIR: MODULE_CODE_DIR$1,
@@ -2466,7 +2494,7 @@ async function task(tmsConfig, targetModules) {
2466
2494
  await install$2(tmsConfig, newSubPackages, true);
2467
2495
 
2468
2496
  // 动态生成编译后的app.json;
2469
- await createTask$3(buildOutputAppJson$1, '开始生成编译后的app.json', '生成编译后的app.json完成')(tmsConfig, newModules);
2497
+ await createTask$3(buildOutputAppJson$2, '开始生成编译后的app.json', '生成编译后的app.json完成')(tmsConfig, newModules);
2470
2498
  return {
2471
2499
  modules: newModules,
2472
2500
  subPackages: newSubPackages
@@ -2501,10 +2529,105 @@ function mpProjectJson$1() {
2501
2529
  }
2502
2530
  var mpProjectJson_1 = mpProjectJson$1;
2503
2531
 
2532
+ /* eslint-disable @typescript-eslint/no-require-imports */
2533
+ const through$1 = require$$0__default$8;
2534
+ const pp = require$$1__default$3;
2535
+ const path$7 = require$$1__default$1;
2536
+ const chalk$4 = require$$3__default;
2537
+ /* eslint-enable @typescript-eslint/no-require-imports */
2538
+
2539
+ // 允许渲染的文件类型列表
2540
+ const TEMPLATE_FILE_EXTENSIONS = ['.json', '.js', '.ts', '.wxml', '.wxss', '.wxs', '.css', '.less', '.scss'];
2541
+
2542
+ /**
2543
+ * 获取预处理器类型
2544
+ * @param {string} extName 文件扩展名
2545
+ * @returns {string} 预处理器类型
2546
+ */
2547
+ const getPreprocessType = extName => {
2548
+ const type = extName.replace('.', '');
2549
+ if (type === 'wxml') return 'html';
2550
+ if (type === 'wxs') return 'js';
2551
+ if (type === 'wxss') return 'css';
2552
+ return type;
2553
+ };
2554
+
2555
+ /**
2556
+ * 获取错误上下文信息
2557
+ * @param {string} content 文件内容
2558
+ * @param {number} errorLine 错误行号
2559
+ * @param {number} contextLines 上下文行数
2560
+ * @returns {string} 格式化的错误上下文
2561
+ */
2562
+ const getErrorContext = (content, errorLine, contextLines = 2) => {
2563
+ const lines = content.split('\n');
2564
+ const start = Math.max(1, errorLine - contextLines);
2565
+ const end = Math.min(lines.length, errorLine + contextLines);
2566
+ let context = '';
2567
+ for (let i = start; i <= end; i++) {
2568
+ const marker = i === errorLine ? ' >> ' : ' ';
2569
+ context += `${marker}${i}| ${lines[i - 1]}\n`;
2570
+ }
2571
+ return context;
2572
+ };
2573
+
2574
+ /**
2575
+ * 打印错误信息
2576
+ * @param {string} filePath 文件路径
2577
+ * @param {string} context 错误上下文
2578
+ * @param {Error} error 错误对象
2579
+ */
2580
+ const printError = (filePath, context, error) => {
2581
+ console.error(`${chalk$4.yellow('渲染模板出错,请检查处理:')}\n${chalk$4.yellow('文件:')}\n${chalk$4.yellow(filePath)}\n${chalk$4.yellow('错误位置:')}\n${chalk$4.gray(context)}\n${chalk$4.red('错误信息:')}\n${chalk$4.red(error.message)}\n${chalk$4.gray('--------------------------------')}`);
2582
+ };
2583
+
2584
+ /**
2585
+ * 模板渲染插件
2586
+ * @param {Object} tmsConfig 配置对象
2587
+ * @returns {Object} through2 转换流
2588
+ */
2589
+ var tmsTemplateRender = function tmsTemplateRender(tmsConfig) {
2590
+ return through$1.obj((file, encoding, callback) => {
2591
+ if (!file.isBuffer()) {
2592
+ return callback(null, file);
2593
+ }
2594
+ const extName = path$7.extname(file.path).toLowerCase();
2595
+ if (!TEMPLATE_FILE_EXTENSIONS.includes(extName)) {
2596
+ return callback(null, file);
2597
+ }
2598
+ const content = file.contents.toString(encoding);
2599
+ try {
2600
+ const vars = tmsConfig.templateVars || {};
2601
+ const ppType = getPreprocessType(extName);
2602
+ // 手动检查 @echo 引用的变量是否存在
2603
+ const echoPattern = /\/\* @echo (\w+) \*\//g;
2604
+ let match;
2605
+ while ((match = echoPattern.exec(content)) !== null) {
2606
+ const variableName = match[1];
2607
+ // eslint-disable-next-line no-prototype-builtins
2608
+ if (!vars.hasOwnProperty(variableName)) {
2609
+ const error = new Error(`变量 ${variableName} 未定义`);
2610
+ error.line = content.substring(0, match.index).split('\n').length;
2611
+ throw error;
2612
+ }
2613
+ }
2614
+ const rendered = pp.preprocess(content, vars, ppType);
2615
+ // eslint-disable-next-line no-param-reassign
2616
+ file.contents = Buffer.from(rendered);
2617
+ } catch (err) {
2618
+ const context = getErrorContext(content, err.line || 1);
2619
+ printError(file.path, context, err);
2620
+ // 直接抛出异常,中断编译流程
2621
+ throw new Error(`模板渲染失败: ${file.path}\n${err.message}`);
2622
+ }
2623
+ callback(null, file);
2624
+ });
2625
+ };
2626
+
2504
2627
  const {
2505
2628
  src: src$2,
2506
2629
  dest: dest$1
2507
- } = require$$0__default$8;
2630
+ } = require$$0__default$9;
2508
2631
  const path$6 = require$$1__default$1;
2509
2632
  const minimatch = require$$2__default;
2510
2633
  const gulpif = require$$3__default$1;
@@ -2512,7 +2635,7 @@ const mpProjectJson = mpProjectJson_1;
2512
2635
  const {
2513
2636
  resolve: resolve$b
2514
2637
  } = widgets;
2515
- const through = require$$6__default;
2638
+ const through = require$$0__default$8;
2516
2639
  const {
2517
2640
  fail: fail$3
2518
2641
  } = log$1;
@@ -2529,7 +2652,7 @@ const addPlugins = function (tmsConfig, srcPipe, pluginParams) {
2529
2652
  glob: '**/project.config.json',
2530
2653
  action: mpProjectJson()
2531
2654
  }, ...plugins];
2532
- return newPlugins.reduce((srcPipe, pluginItem) => srcPipe.pipe(gulpif(vinyl => minimatch(vinyl.path, pluginItem.glob), through.obj(function (vinyl, enc, next) {
2655
+ return newPlugins.reduce((currentPipe, pluginItem) => currentPipe.pipe(gulpif(vinyl => minimatch(vinyl.path, pluginItem.glob), through.obj(function (vinyl, enc, next) {
2533
2656
  const sourceFile = vinyl.history[0];
2534
2657
  pluginItem.action({
2535
2658
  tmsConfig,
@@ -2558,6 +2681,12 @@ var compile$1 = function (tmsConfig, {
2558
2681
  let srcPipe = src$2(newGlobValue, {
2559
2682
  ...srcOption
2560
2683
  });
2684
+
2685
+ // 在文件读取后,插件处理之前先加入模板渲染插件
2686
+ const templateRender = tmsTemplateRender;
2687
+ srcPipe = srcPipe.pipe(templateRender(tmsConfig));
2688
+
2689
+ // 后续步骤继续执行其他插件
2561
2690
  const pluginParams = {
2562
2691
  module,
2563
2692
  isDev
@@ -2573,15 +2702,15 @@ var compile$1 = function (tmsConfig, {
2573
2702
 
2574
2703
  /* eslint-disable */
2575
2704
  // 该文件源于npm包 gulp-watch 但内部有bug, 故源码进行单独修改
2576
- const assign = require$$0__default$9;
2705
+ const assign = require$$0__default$a;
2577
2706
  const path$5 = require$$1__default$1;
2578
2707
  const PluginError = require$$2__default$1;
2579
2708
  const fancyLog = require$$3__default$2;
2580
- const colors = require$$4__default$1;
2709
+ const colors = require$$4__default$2;
2581
2710
  const chokidar = require$$5__default;
2582
2711
  const {
2583
2712
  Duplex
2584
- } = require$$6__default$1;
2713
+ } = require$$6__default;
2585
2714
  const vinyl = require$$7__default;
2586
2715
  const File = require$$8__default;
2587
2716
  const anymatch = require$$9__default;
@@ -2720,7 +2849,7 @@ const path$4 = require$$1__default$1;
2720
2849
  const shellJs$2 = require$$0__default$2;
2721
2850
  const {
2722
2851
  series: series$2
2723
- } = require$$0__default$8;
2852
+ } = require$$0__default$9;
2724
2853
  const {
2725
2854
  info: info$a,
2726
2855
  warn: warn$1,
@@ -2847,7 +2976,7 @@ const chalk$3 = require$$3__default;
2847
2976
  const {
2848
2977
  parallel: parallel$1,
2849
2978
  series: series$1
2850
- } = require$$0__default$8;
2979
+ } = require$$0__default$9;
2851
2980
  const {
2852
2981
  resolve: resolve$9,
2853
2982
  mergeMap,
@@ -2855,7 +2984,7 @@ const {
2855
2984
  getAbsolutePath: getAbsolutePath$3
2856
2985
  } = widgets;
2857
2986
  const {
2858
- buildOutputAppJson
2987
+ buildOutputAppJson: buildOutputAppJson$1
2859
2988
  } = buildAppJson;
2860
2989
  const {
2861
2990
  DEFAULT_COPY_CONFIG
@@ -2921,7 +3050,7 @@ var dev$4 = async (tmsConfig, modules, isDev = true) => {
2921
3050
  // 监听模块配置文件
2922
3051
  watch$1([`${srcModulePath}/**/module.config.json`], {
2923
3052
  events: watchEvents
2924
- }, () => buildOutputAppJson(tmsConfig, modules, isDev), {
3053
+ }, () => buildOutputAppJson$1(tmsConfig, modules, isDev), {
2925
3054
  from: srcModulePath,
2926
3055
  to: buildModulePath
2927
3056
  });
@@ -2934,8 +3063,10 @@ var dev$4 = async (tmsConfig, modules, isDev = true) => {
2934
3063
  }
2935
3064
  return `!${resolve$9(srcModulePath, newPath)}/**/*`;
2936
3065
  });
3066
+ const moduleConfigPath = `${srcModulePath}/**/module.config.json`;
3067
+ const moduleConfigGlob = tmsConfig.isKeepModuleConfig ? `${moduleConfigPath}` : `!${moduleConfigPath}`;
2937
3068
  mergeMap(compileTasksMap, compile(tmsConfig, {
2938
- glob: [`${srcModulePath}/**/*`, `!${srcModulePath}/**/module.config.json`, ...excludes],
3069
+ glob: [`${srcModulePath}/**/*`, moduleConfigGlob, ...excludes],
2939
3070
  destPath: buildModulePath,
2940
3071
  module: {
2941
3072
  from: srcModulePath,
@@ -2991,7 +3122,7 @@ var dev$4 = async (tmsConfig, modules, isDev = true) => {
2991
3122
  watch$1([resolve$9('app.json')], {
2992
3123
  ignoreInitial: false,
2993
3124
  events: watchEvents
2994
- }, async () => await buildOutputAppJson(tmsConfig, modules, isDev), {
3125
+ }, async () => await buildOutputAppJson$1(tmsConfig, modules, isDev), {
2995
3126
  from: resolve$9(),
2996
3127
  to: resolve$9(tmsConfig.outputDir)
2997
3128
  });
@@ -3006,7 +3137,7 @@ var dev$4 = async (tmsConfig, modules, isDev = true) => {
3006
3137
  }, taskFn, module);
3007
3138
  });
3008
3139
  } else {
3009
- await buildOutputAppJson(tmsConfig, modules, isDev);
3140
+ await buildOutputAppJson$1(tmsConfig, modules, isDev);
3010
3141
  }
3011
3142
  eTime = new Date().getTime() - sTime;
3012
3143
  if (typeof (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$hooks = tmsConfig.hooks) === null || _tmsConfig$hooks === void 0 ? void 0 : _tmsConfig$hooks.afterFirstCompile) === 'function') {
@@ -3040,6 +3171,9 @@ const {
3040
3171
  filterField: filterField$3
3041
3172
  } = widgets;
3042
3173
  const init$2 = init_1;
3174
+ const {
3175
+ buildOutputAppJson
3176
+ } = buildAppJson;
3043
3177
  const {
3044
3178
  getModulesByMergeDepModules: getModulesByMergeDepModules$1,
3045
3179
  getSubPackages: getSubPackages$1
@@ -3075,7 +3209,6 @@ function delOtherPackages(tmsConfig, targetSubPackages) {
3075
3209
  }
3076
3210
  });
3077
3211
  }
3078
-
3079
3212
  async function dev$3(tmsConfig, targetModules) {
3080
3213
  var _tmsConfig$hooks;
3081
3214
  const {
@@ -3094,6 +3227,9 @@ async function dev$3(tmsConfig, targetModules) {
3094
3227
  subPackages,
3095
3228
  modules: newModules
3096
3229
  } = await init$2(tmsConfig, targetModules);
3230
+
3231
+ // 在启动开发环境前主动执行生成 app.json
3232
+ await buildOutputAppJson(tmsConfig, newModules);
3097
3233
  info$8('当前dev启动的有效模块', newModules.map(item => item.moduleName).sort());
3098
3234
  if (typeof (tmsConfig === null || tmsConfig === void 0 ? void 0 : (_tmsConfig$hooks = tmsConfig.hooks) === null || _tmsConfig$hooks === void 0 ? void 0 : _tmsConfig$hooks.beforeFirstCompile) === 'function') {
3099
3235
  var _tmsConfig$hooks2;
@@ -3537,7 +3673,7 @@ const {
3537
3673
  dest,
3538
3674
  parallel,
3539
3675
  series
3540
- } = require$$0__default$8;
3676
+ } = require$$0__default$9;
3541
3677
  const watch = gulpWatch;
3542
3678
  const {
3543
3679
  info: info$2,
@@ -3904,7 +4040,7 @@ var entry = [{
3904
4040
 
3905
4041
  var require$$12 = {
3906
4042
  name: "@tmsfe/tmskit",
3907
- version: "0.0.36",
4043
+ version: "0.0.38",
3908
4044
  description: "tmskit",
3909
4045
  main: "dist/index.cjs",
3910
4046
  bin: {
@@ -3957,6 +4093,8 @@ var require$$12 = {
3957
4093
  "gulp-watch": "^5.0.1",
3958
4094
  htmlparser2: "^7.2.0",
3959
4095
  inquirer: "^7.3.3",
4096
+ json5: "^2.2.3",
4097
+ preprocess: "^3.2.0",
3960
4098
  leven: "3.1.0",
3961
4099
  lodash: "^4.17.21",
3962
4100
  metalsmith: "^2.3.0",
@@ -3989,7 +4127,7 @@ var require$$12 = {
3989
4127
  }
3990
4128
  };
3991
4129
 
3992
- const semver = require$$1__default$7;
4130
+ const semver = require$$1__default$8;
3993
4131
  const packageJson = require$$12;
3994
4132
  const chalk$1 = require$$3__default;
3995
4133
  const {
@@ -4025,7 +4163,7 @@ var check_1 = check$1;
4025
4163
 
4026
4164
  /* eslint-disable no-param-reassign */
4027
4165
  const chalk = require$$3__default;
4028
- const commander = require$$1__default$8;
4166
+ const commander = require$$1__default$9;
4029
4167
  const path = require$$1__default$1;
4030
4168
  const fs = require$$0__default$1;
4031
4169
  const {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmsfe/tmskit",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
4
4
  "description": "tmskit",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {
@@ -53,6 +53,8 @@
53
53
  "gulp-watch": "^5.0.1",
54
54
  "htmlparser2": "^7.2.0",
55
55
  "inquirer": "^7.3.3",
56
+ "json5": "^2.2.3",
57
+ "preprocess": "^3.2.0",
56
58
  "leven": "3.1.0",
57
59
  "lodash": "^4.17.21",
58
60
  "metalsmith": "^2.3.0",
@@ -13,13 +13,13 @@ const getTargetFile = (sourceFile, module, outputDir) => {
13
13
  return targetFile;
14
14
  };
15
15
 
16
- const addPlugins = function (tmsConfig, srcPipe, pluginParams) {
16
+ const addPlugins = function (tmsConfig, srcPipe, pluginParams) {
17
17
  const { plugins = [] } = tmsConfig;
18
18
  const newPlugins = [{
19
19
  glob: '**/project.config.json',
20
20
  action: mpProjectJson(),
21
21
  }, ...plugins];
22
- return newPlugins.reduce((srcPipe, pluginItem) => srcPipe.pipe(gulpif(
22
+ return newPlugins.reduce((currentPipe, pluginItem) => currentPipe.pipe(gulpif(
23
23
  vinyl => minimatch(vinyl.path, pluginItem.glob),
24
24
  through.obj(function (vinyl, enc, next) {
25
25
  const sourceFile = vinyl.history[0];
@@ -55,6 +55,12 @@ module.exports = function (
55
55
  const newGlobValue = Array.isArray(sourceFile) ? sourceFile : glob;
56
56
  const newDestPath = targetPath ? targetPath : destPath;
57
57
  let srcPipe = src(newGlobValue, { ...srcOption });
58
+
59
+ // 在文件读取后,插件处理之前先加入模板渲染插件
60
+ const templateRender = require('./plugins/tmsTemplateRender');
61
+ srcPipe = srcPipe.pipe(templateRender(tmsConfig));
62
+
63
+ // 后续步骤继续执行其他插件
58
64
  const pluginParams = { module, isDev };
59
65
  srcPipe = addPlugins(tmsConfig, srcPipe, pluginParams);
60
66
  return srcPipe
@@ -72,8 +72,12 @@ module.exports = async (tmsConfig, modules, isDev = true) => {
72
72
  return `!${resolve(srcModulePath, newPath)}/**/*`;
73
73
  });
74
74
 
75
+ const moduleConfigPath = `${srcModulePath}/**/module.config.json`;
76
+
77
+ const moduleConfigGlob = tmsConfig.isKeepModuleConfig ? `${moduleConfigPath}` : `!${moduleConfigPath}`;
78
+
75
79
  mergeMap(compileTasksMap, compile(tmsConfig, {
76
- glob: [`${srcModulePath}/**/*`, `!${srcModulePath}/**/module.config.json`, ...excludes],
80
+ glob: [`${srcModulePath}/**/*`, moduleConfigGlob, ...excludes],
77
81
  destPath: buildModulePath,
78
82
  module: { from: srcModulePath, to: buildModulePath },
79
83
  srcOption: { allowEmpty: true },
@@ -0,0 +1,122 @@
1
+ /* eslint-disable @typescript-eslint/no-require-imports */
2
+ const through = require('through2');
3
+ const pp = require('preprocess');
4
+ const path = require('path');
5
+ const chalk = require('chalk');
6
+ /* eslint-enable @typescript-eslint/no-require-imports */
7
+
8
+ // 允许渲染的文件类型列表
9
+ const TEMPLATE_FILE_EXTENSIONS = [
10
+ '.json',
11
+ '.js',
12
+ '.ts',
13
+ '.wxml',
14
+ '.wxss',
15
+ '.wxs',
16
+ '.css',
17
+ '.less',
18
+ '.scss',
19
+ ];
20
+
21
+ /**
22
+ * 获取预处理器类型
23
+ * @param {string} extName 文件扩展名
24
+ * @returns {string} 预处理器类型
25
+ */
26
+ const getPreprocessType = (extName) => {
27
+ const type = extName.replace('.', '');
28
+ if (type === 'wxml') return 'html';
29
+ if (type === 'wxs') return 'js';
30
+ if (type === 'wxss') return 'css';
31
+ return type;
32
+ };
33
+
34
+ /**
35
+ * 获取错误上下文信息
36
+ * @param {string} content 文件内容
37
+ * @param {number} errorLine 错误行号
38
+ * @param {number} contextLines 上下文行数
39
+ * @returns {string} 格式化的错误上下文
40
+ */
41
+ const getErrorContext = (content, errorLine, contextLines = 2) => {
42
+ const lines = content.split('\n');
43
+ const start = Math.max(1, errorLine - contextLines);
44
+ const end = Math.min(lines.length, errorLine + contextLines);
45
+
46
+ let context = '';
47
+ for (let i = start; i <= end; i++) {
48
+ const marker = i === errorLine ? ' >> ' : ' ';
49
+ context += `${marker}${i}| ${lines[i - 1]}\n`;
50
+ }
51
+ return context;
52
+ };
53
+
54
+ /**
55
+ * 打印错误信息
56
+ * @param {string} filePath 文件路径
57
+ * @param {string} context 错误上下文
58
+ * @param {Error} error 错误对象
59
+ */
60
+ const printError = (filePath, context, error) => {
61
+ console.error(`${chalk.yellow('渲染模板出错,请检查处理:')
62
+ }\n${
63
+ chalk.yellow('文件:')
64
+ }\n${
65
+ chalk.yellow(filePath)
66
+ }\n${
67
+ chalk.yellow('错误位置:')
68
+ }\n${
69
+ chalk.gray(context)
70
+ }\n${
71
+ chalk.red('错误信息:')
72
+ }\n${
73
+ chalk.red(error.message)
74
+ }\n${
75
+ chalk.gray('--------------------------------')}`);
76
+ };
77
+
78
+ /**
79
+ * 模板渲染插件
80
+ * @param {Object} tmsConfig 配置对象
81
+ * @returns {Object} through2 转换流
82
+ */
83
+ module.exports = function tmsTemplateRender(tmsConfig) {
84
+ return through.obj((file, encoding, callback) => {
85
+ if (!file.isBuffer()) {
86
+ return callback(null, file);
87
+ }
88
+
89
+ const extName = path.extname(file.path).toLowerCase();
90
+ if (!TEMPLATE_FILE_EXTENSIONS.includes(extName)) {
91
+ return callback(null, file);
92
+ }
93
+
94
+ const content = file.contents.toString(encoding);
95
+ try {
96
+ const vars = tmsConfig.templateVars || {};
97
+ const ppType = getPreprocessType(extName);
98
+ // 手动检查 @echo 引用的变量是否存在
99
+ const echoPattern = /\/\* @echo (\w+) \*\//g;
100
+ let match;
101
+ while ((match = echoPattern.exec(content)) !== null) {
102
+ const variableName = match[1];
103
+ // eslint-disable-next-line no-prototype-builtins
104
+ if (!vars.hasOwnProperty(variableName)) {
105
+ const error = new Error(`变量 ${variableName} 未定义`);
106
+ error.line = content.substring(0, match.index).split('\n').length;
107
+ throw error;
108
+ }
109
+ }
110
+ const rendered = pp.preprocess(content, vars, ppType);
111
+ // eslint-disable-next-line no-param-reassign
112
+ file.contents = Buffer.from(rendered);
113
+ } catch (err) {
114
+ const context = getErrorContext(content, err.line || 1);
115
+ printError(file.path, context, err);
116
+ // 直接抛出异常,中断编译流程
117
+ throw new Error(`模板渲染失败: ${file.path}\n${err.message}`);
118
+ }
119
+
120
+ callback(null, file);
121
+ });
122
+ };
@@ -3,6 +3,7 @@
3
3
  */
4
4
  /* eslint-disable no-param-reassign */
5
5
  const fs = require('fs');
6
+ const pp = require('preprocess');
6
7
  const { getSubPackages, getModulesConfig } = require('./tmsMpconfig');
7
8
  const { fail, info } = require('../utils/log');
8
9
  const { resolve, filterField } = require('../utils/widgets');
@@ -19,7 +20,7 @@ const report = require('../core/report');
19
20
  */
20
21
  function updateMainPackages(appJson, mainPackages = []) {
21
22
  let foundMainPackages = appJson.subpackages.filter(subpackage => mainPackages.includes(subpackage.name));
22
- if (foundMainPackages.length === 0) {
23
+ if (foundMainPackages.length === 0 && appJson.pages.length === 0) {
23
24
  // 没找到主包
24
25
  foundMainPackages = [appJson.subpackages[0]];
25
26
  }
@@ -55,8 +56,8 @@ const getAppJsonContent = (sourceAppJsonPath) => {
55
56
  }
56
57
  const appJson = JSON.parse(fs.readFileSync(sourceAppJsonPath), 'utf-8');
57
58
  // 加入默认值
58
- appJson.subpackages = [];
59
- appJson.pages = [];
59
+ appJson.subpackages = appJson.subpackages || [];
60
+ appJson.pages = appJson.pages || [];
60
61
  return appJson;
61
62
  };
62
63
 
@@ -123,11 +124,11 @@ const fixAppJson = (appJson) => {
123
124
  async function buildOutputAppJson(tmsConfig, modules) {
124
125
  try {
125
126
  // 获取所有模块,合并模块依赖的模块
126
- const modulesConfig = getModulesConfig(modules, tmsConfig.appName, false);
127
+ const modulesConfig = getModulesConfig(modules, tmsConfig, false);
127
128
  // 获取所有的分包
128
129
  const subPackages = getSubPackages(modulesConfig);
129
130
  // 获取app.json的配置
130
- const appJson = getAppJsonContent(resolve('./app.json'));
131
+ let appJson = getAppJsonContent(resolve('./app.json'));
131
132
 
132
133
  // 更新app.json中的subpackages
133
134
  appJson.subpackages = subPackages;
@@ -138,7 +139,12 @@ async function buildOutputAppJson(tmsConfig, modules) {
138
139
  // 更新主包,需在subpackages处理完成后执行, pages/
139
140
  updateMainPackages(appJson, tmsConfig.mainPackages);
140
141
 
141
- fs.writeFileSync(resolve(`${tmsConfig.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
142
+ // 模板渲染:先将 app.json 转为字符串,然后通过 preprocess 渲染
143
+ const appJsonStr = JSON.stringify(appJson, null, 2);
144
+ const preprocessedStr = pp.preprocess(appJsonStr, tmsConfig.templateVars || {}, 'json');
145
+ fs.writeFileSync(resolve(`${tmsConfig.outputDir}/app.json`), preprocessedStr, 'utf8');
146
+
147
+ appJson = JSON.parse(preprocessedStr);
142
148
 
143
149
  if (typeof tmsConfig?.hooks?.updateAppJson === 'function') {
144
150
  await tmsConfig?.hooks?.updateAppJson({
@@ -31,7 +31,7 @@ function replaceGitUrlAccount(httpRepoUrl, moduleName) {
31
31
  const urlPrefixReg = /http(s)?:\/\//;
32
32
 
33
33
  if (username && pass && urlPrefixReg.test(gitUrl)) {
34
- gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${pass}@`);
34
+ gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${encodeURIComponent(pass)}@`);
35
35
  }
36
36
 
37
37
  return gitUrl;
@@ -5,6 +5,8 @@
5
5
  const loadash = require('lodash');
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
+ const pp = require('preprocess');
9
+ const JSON5 = require('json5');
8
10
  const { TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME, TMS_PRIVATE_FILENAME } = require('../config/constant');
9
11
  const { resolve, isObject, isArray, getAbsolutePath } = require('../utils/widgets');
10
12
  const defaultTmsConfig = require('../config/defaultTmsConfig');
@@ -57,9 +59,15 @@ const getTmsConfig = (configPath) => {
57
59
  modules.all = tmsConfig.modules;
58
60
  tmsConfig.modules = modules;
59
61
  }
60
- // 合并默认值
61
- const res = loadash.mergeWith(tmsConfig, tmsPrivateCf, (objValue, srcValue) => {
62
- if (loadash.isArray(objValue) && objValue[0] && loadash.isObject(objValue[0])) {
62
+ // 使用自定义的合并策略:
63
+ // 1. templateVars 字段做浅合并(即把 tms.config.js 中的和 tms.private.config.js 中的对象合并,
64
+ // 如果存在同名字段则以 tms.private.config.js 中的为准)。
65
+ // 2. 对数组(并且数组元素为对象的情况)执行拼接
66
+ const res = loadash.mergeWith({}, tmsConfig, tmsPrivateCf, (objValue, srcValue, key) => {
67
+ if (key === 'templateVars') {
68
+ return { ...(objValue || {}), ...(srcValue || {}) };
69
+ }
70
+ if (Array.isArray(objValue) && objValue[0] && isObject(objValue[0])) {
63
71
  return objValue.concat(srcValue);
64
72
  }
65
73
  });
@@ -128,13 +136,18 @@ const adaptSubPackages = function (moduleConfig, appName) {
128
136
  * @param {array} modules 用户要编译的模块列表
129
137
  * @param { string } appName 小程序的名称
130
138
  */
131
- function getModulesConfig(modules = [], appName) {
139
+ function getModulesConfig(modules = [], tmsConfig) {
140
+ const { appName } = tmsConfig;
132
141
  const modulesConfig = [];
133
142
  modules.forEach((moduleItem) => {
134
143
  const moduleConfigPath = resolve(moduleItem.path, MODULE_CONFIG_FILENAME);
135
144
  let moduleConfig;
136
145
  try {
137
- moduleConfig = JSON.parse(fs.readFileSync(moduleConfigPath, 'utf-8'));
146
+ // 模板渲染:先将 module.config.json 转为字符串,然后通过 preprocess 渲染
147
+ const moduleConfigJsonStr = fs.readFileSync(moduleConfigPath, 'utf-8');
148
+ const preprocessedStr = pp.preprocess(moduleConfigJsonStr, tmsConfig.templateVars || {}, 'json');
149
+ // fs.writeFileSync(resolve(moduleConfigPath), moduleConfigJsonStr, 'utf8');
150
+ moduleConfig = JSON5.parse(preprocessedStr);
138
151
  } catch (e) {
139
152
  throw new Error(`${moduleConfigPath}json解析报错: ${e}`);
140
153
  }
@@ -241,11 +254,11 @@ const getModulesByMergeDepModules = (tmsConfig, modules, errorIsQuit = false) =>
241
254
  allModules.set(moduleItem.moduleName, moduleItem);
242
255
  }
243
256
  if (errorIsQuit) {
244
- throw new Error(`${moduleItem.moduleName}模块的配置文件module.config.json在${moduleItem.path}目录下没有找到`);
257
+ throw new Error(`${moduleItem.moduleName}模块的配置文件module.config.json在${moduleItem.path}目录下没有找到 ${moduleConfigPath}`);
245
258
  }
246
259
  return;
247
260
  }
248
- const [moduleConfig = {}] = getModulesConfig([moduleItem], tmsConfig.appName);
261
+ const [moduleConfig = {}] = getModulesConfig([moduleItem], tmsConfig);
249
262
 
250
263
  if (!allModules.has(moduleItem.moduleName)) {
251
264
  allModules.set(moduleItem.moduleName, checkModuleItem(tmsConfig, moduleItem, moduleConfig));
@@ -2,6 +2,7 @@ const shelljs = require('shelljs');
2
2
  const compileDev = require('../../../compile/dev');
3
3
  const { resolve, filterField } = require('../../../utils/widgets');
4
4
  const init = require('../init/index');
5
+ const { buildOutputAppJson } = require('../../../core/buildAppJson');
5
6
  const { getModulesByMergeDepModules, getSubPackages } = require('../../../core/tmsMpconfig');
6
7
  const { info } = require('../../../utils/log');
7
8
  const { global } = require('../../../utils/global');
@@ -40,6 +41,9 @@ async function dev(tmsConfig, targetModules) {
40
41
  // 初始化操作
41
42
  const { subPackages, modules: newModules } = await init(tmsConfig, targetModules);
42
43
 
44
+ // 在启动开发环境前主动执行生成 app.json
45
+ await buildOutputAppJson(tmsConfig, newModules);
46
+
43
47
  info('当前dev启动的有效模块', newModules.map(item => item.moduleName).sort());
44
48
  if (typeof tmsConfig?.hooks?.beforeFirstCompile === 'function') {
45
49
  await tmsConfig?.hooks?.beforeFirstCompile({