@dimina/compiler 1.0.7 → 1.0.8

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.
@@ -0,0 +1,543 @@
1
+ "use strict";
2
+ const fs = require("node:fs");
3
+ const os = require("node:os");
4
+ const path = require("node:path");
5
+ const process = require("node:process");
6
+ function hasCompileInfo(modulePath, list, preList) {
7
+ const mergeList = Array.isArray(preList) ? [...preList, ...list] : list;
8
+ for (const element of mergeList) {
9
+ if (element.path === modulePath) {
10
+ return true;
11
+ }
12
+ }
13
+ return false;
14
+ }
15
+ function getAbsolutePath(workPath, pagePath, src) {
16
+ if (src.startsWith("/")) {
17
+ return path.join(workPath, src);
18
+ }
19
+ if (pagePath.includes("/miniprogram_npm/")) {
20
+ const componentDir = pagePath.split("/").slice(0, -1).join("/");
21
+ const componentFullPath = workPath + componentDir;
22
+ return path.resolve(componentFullPath, src);
23
+ }
24
+ const relativePath = pagePath.split("/").filter((part) => part !== "").slice(0, -1).join("/");
25
+ return path.resolve(workPath, relativePath, src);
26
+ }
27
+ const assetsMap = {};
28
+ function collectAssets(workPath, pagePath, src, targetPath, appId) {
29
+ if (src.startsWith("http") || src.startsWith("//")) {
30
+ return src;
31
+ }
32
+ if (!/\.(?:png|jpe?g|gif|svg)(?:\?.*)?$/.test(src)) {
33
+ return src;
34
+ }
35
+ const relativePath = pagePath.split("/").slice(0, -1).join("/");
36
+ const absolutePath = src.startsWith("/") ? workPath + src : path.resolve(workPath, relativePath, src);
37
+ if (assetsMap[absolutePath]) {
38
+ return assetsMap[absolutePath];
39
+ }
40
+ try {
41
+ const ext = `.${src.split(".").pop()}`;
42
+ const dirPath = absolutePath.split(path.sep).slice(0, -1).join("/");
43
+ const prefix = uuid();
44
+ const targetStatic = `${targetPath}/main/static`;
45
+ if (!fs.existsSync(targetStatic)) {
46
+ fs.mkdirSync(targetStatic, { recursive: true });
47
+ }
48
+ getFilesWithExtension(dirPath, ext).forEach((file) => {
49
+ fs.copyFileSync(path.resolve(dirPath, file), `${targetStatic}/${prefix}_${file}`);
50
+ });
51
+ const filename = src.split("/").pop();
52
+ const pathPrefix = process.env.ASSETS_PATH_PREFIX ? "" : "/";
53
+ assetsMap[absolutePath] = `${pathPrefix}${appId}/main/static/${prefix}_${filename}`;
54
+ } catch (error) {
55
+ console.log(error);
56
+ }
57
+ return assetsMap[absolutePath] || src;
58
+ }
59
+ function getFilesWithExtension(directory, extension) {
60
+ const files = fs.readdirSync(directory);
61
+ const filteredFiles = files.filter((file) => path.extname(file) === extension);
62
+ return filteredFiles;
63
+ }
64
+ function isObjectEmpty(objectName) {
65
+ if (!objectName) {
66
+ return true;
67
+ }
68
+ return Object.keys(objectName).length === 0 && objectName.constructor === Object;
69
+ }
70
+ function isString(o) {
71
+ return Object.prototype.toString.call(o) === "[object String]";
72
+ }
73
+ function transformRpx(styleText) {
74
+ if (!isString(styleText)) {
75
+ return styleText;
76
+ }
77
+ return styleText.replace(/([+-]?\d+(?:\.\d+)?)rpx/g, (_, pixel) => {
78
+ return `${Number(pixel)}rem`;
79
+ });
80
+ }
81
+ function uuid() {
82
+ return Math.random().toString(36).slice(2, 7);
83
+ }
84
+ const tagWhiteList = [
85
+ "page",
86
+ "wrapper",
87
+ "block",
88
+ "button",
89
+ "camera",
90
+ "checkbox-group",
91
+ "checkbox",
92
+ "cover-image",
93
+ "cover-view",
94
+ "form",
95
+ "icon",
96
+ "image",
97
+ "input",
98
+ "keyboard-accessory",
99
+ "label",
100
+ "map",
101
+ "movable-area",
102
+ "movable-view",
103
+ "navigation-bar",
104
+ "navigator",
105
+ "open-data",
106
+ "page-meta",
107
+ "picker-view-column",
108
+ "picker-view",
109
+ "picker",
110
+ "progress",
111
+ "radio-group",
112
+ "radio",
113
+ "rich-text",
114
+ "root-portal",
115
+ "scroll-view",
116
+ "slider",
117
+ "swiper-item",
118
+ "swiper",
119
+ "switch",
120
+ "template",
121
+ "text",
122
+ "textarea",
123
+ "video",
124
+ "view",
125
+ "web-view"
126
+ ];
127
+ class NpmResolver {
128
+ constructor(workPath) {
129
+ this.workPath = workPath;
130
+ this.miniprogramNpmCache = /* @__PURE__ */ new Map();
131
+ this.packageCache = /* @__PURE__ */ new Map();
132
+ }
133
+ /**
134
+ * 解析组件路径,支持 npm 包组件
135
+ * @param {string} componentPath 组件路径
136
+ * @param {string} pageFilePath 页面文件路径
137
+ * @returns {string} 解析后的组件路径
138
+ */
139
+ resolveComponentPath(componentPath, pageFilePath) {
140
+ if (componentPath.startsWith("./") || componentPath.startsWith("../") || componentPath.startsWith("/")) {
141
+ return this.resolveRelativePath(componentPath, pageFilePath);
142
+ }
143
+ const npmPath = this.resolveNpmComponent(componentPath, pageFilePath);
144
+ if (npmPath) {
145
+ return npmPath;
146
+ }
147
+ return this.resolveRelativePath(componentPath, pageFilePath);
148
+ }
149
+ /**
150
+ * 解析相对路径组件
151
+ * @param {string} componentPath 组件路径
152
+ * @param {string} pageFilePath 页面文件路径
153
+ * @returns {string} 解析后的路径
154
+ */
155
+ resolveRelativePath(componentPath, pageFilePath) {
156
+ const lastIndex = pageFilePath.lastIndexOf("/");
157
+ const newPath = pageFilePath.slice(0, lastIndex);
158
+ const res = path.resolve(newPath, componentPath);
159
+ return res.replace(this.workPath, "");
160
+ }
161
+ /**
162
+ * 解析 npm 组件
163
+ * @param {string} componentName 组件名称
164
+ * @param {string} pageFilePath 页面文件路径
165
+ * @returns {string|null} 解析后的组件路径,如果找不到返回 null
166
+ */
167
+ resolveNpmComponent(componentName, pageFilePath) {
168
+ const searchPaths = this.generateSearchPaths(pageFilePath);
169
+ for (const searchPath of searchPaths) {
170
+ const componentPath = this.findComponentInMiniprogramNpm(componentName, searchPath);
171
+ if (componentPath) {
172
+ return componentPath;
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ /**
178
+ * 生成 miniprogram_npm 搜索路径
179
+ * 按照微信小程序的寻址顺序生成搜索路径
180
+ * @param {string} pageFilePath 页面文件路径
181
+ * @returns {string[]} 搜索路径数组
182
+ */
183
+ generateSearchPaths(pageFilePath) {
184
+ const relativePath = pageFilePath.replace(this.workPath, "").replace(/^\//, "");
185
+ const pathParts = relativePath.split("/").slice(0, -1);
186
+ const searchPaths = [];
187
+ for (let i = pathParts.length; i >= 0; i--) {
188
+ const currentPath = pathParts.slice(0, i).join("/");
189
+ const miniprogramNpmPath = currentPath ? `${currentPath}/miniprogram_npm` : "miniprogram_npm";
190
+ searchPaths.push(miniprogramNpmPath);
191
+ }
192
+ return searchPaths;
193
+ }
194
+ /**
195
+ * 在指定的 miniprogram_npm 目录中查找组件
196
+ * @param {string} componentName 组件名称
197
+ * @param {string} miniprogramNpmPath miniprogram_npm 路径
198
+ * @returns {string|null} 组件路径,如果找不到返回 null
199
+ */
200
+ findComponentInMiniprogramNpm(componentName, miniprogramNpmPath) {
201
+ const fullMiniprogramNpmPath = path.join(this.workPath, miniprogramNpmPath);
202
+ if (!fs.existsSync(fullMiniprogramNpmPath)) {
203
+ return null;
204
+ }
205
+ const cacheKey = `${miniprogramNpmPath}/${componentName}`;
206
+ if (this.miniprogramNpmCache.has(cacheKey)) {
207
+ return this.miniprogramNpmCache.get(cacheKey);
208
+ }
209
+ const candidatePaths = [
210
+ componentName,
211
+ `${componentName}/index`
212
+ ];
213
+ for (const candidatePath of candidatePaths) {
214
+ const componentDir = path.join(fullMiniprogramNpmPath, candidatePath);
215
+ if (this.isValidComponent(componentDir)) {
216
+ const resolvedPath = `/${miniprogramNpmPath}/${candidatePath}`.replace(/\/+/g, "/");
217
+ this.miniprogramNpmCache.set(cacheKey, resolvedPath);
218
+ return resolvedPath;
219
+ }
220
+ }
221
+ this.miniprogramNpmCache.set(cacheKey, null);
222
+ return null;
223
+ }
224
+ /**
225
+ * 检查是否为有效的组件
226
+ * @param {string} componentPath 组件路径
227
+ * @returns {boolean} 是否为有效组件
228
+ */
229
+ isValidComponent(componentPath) {
230
+ const requiredFiles = [".json", ".js"];
231
+ const hasRequiredFiles = requiredFiles.some((ext) => {
232
+ return fs.existsSync(`${componentPath}${ext}`);
233
+ });
234
+ if (!hasRequiredFiles) {
235
+ const indexFiles = requiredFiles.some((ext) => {
236
+ return fs.existsSync(path.join(componentPath, `index${ext}`));
237
+ });
238
+ if (!indexFiles) {
239
+ return false;
240
+ }
241
+ const indexJsonFile = path.join(componentPath, "index.json");
242
+ if (fs.existsSync(indexJsonFile)) {
243
+ try {
244
+ const config = JSON.parse(fs.readFileSync(indexJsonFile, "utf-8"));
245
+ return config.component === true;
246
+ } catch (e) {
247
+ return false;
248
+ }
249
+ }
250
+ return true;
251
+ }
252
+ const jsonFile = `${componentPath}.json`;
253
+ if (fs.existsSync(jsonFile)) {
254
+ try {
255
+ const config = JSON.parse(fs.readFileSync(jsonFile, "utf-8"));
256
+ return config.component === true;
257
+ } catch (e) {
258
+ return false;
259
+ }
260
+ }
261
+ return true;
262
+ }
263
+ /**
264
+ * 获取 npm 包信息
265
+ * @param {string} packageName 包名
266
+ * @param {string} searchPath 搜索路径
267
+ * @returns {object|null} 包信息,如果找不到返回 null
268
+ */
269
+ getPackageInfo(packageName, searchPath) {
270
+ const cacheKey = `${searchPath}/${packageName}`;
271
+ if (this.packageCache.has(cacheKey)) {
272
+ return this.packageCache.get(cacheKey);
273
+ }
274
+ const packageJsonPath = path.join(this.workPath, searchPath, packageName, "package.json");
275
+ if (!fs.existsSync(packageJsonPath)) {
276
+ this.packageCache.set(cacheKey, null);
277
+ return null;
278
+ }
279
+ try {
280
+ const packageInfo = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
281
+ this.packageCache.set(cacheKey, packageInfo);
282
+ return packageInfo;
283
+ } catch (e) {
284
+ this.packageCache.set(cacheKey, null);
285
+ return null;
286
+ }
287
+ }
288
+ /**
289
+ * 清除缓存
290
+ */
291
+ clearCache() {
292
+ this.miniprogramNpmCache.clear();
293
+ this.packageCache.clear();
294
+ }
295
+ }
296
+ let pathInfo = {};
297
+ let configInfo = {};
298
+ let npmResolver = null;
299
+ function storeInfo(workPath) {
300
+ storePathInfo(workPath);
301
+ storeProjectConfig();
302
+ storeAppConfig();
303
+ storePageConfig();
304
+ return {
305
+ pathInfo,
306
+ configInfo
307
+ };
308
+ }
309
+ function resetStoreInfo(opts) {
310
+ pathInfo = opts.pathInfo;
311
+ configInfo = opts.configInfo;
312
+ if (pathInfo.workPath) {
313
+ npmResolver = new NpmResolver(pathInfo.workPath);
314
+ }
315
+ }
316
+ function storePathInfo(workPath) {
317
+ pathInfo.workPath = workPath;
318
+ if (process.env.TARGET_PATH) {
319
+ pathInfo.targetPath = process.env.TARGET_PATH;
320
+ } else {
321
+ const tempDir = process.env.GITHUB_WORKSPACE || os.tmpdir();
322
+ const targetDir = path.join(tempDir, `dimina-fe-dist-${Date.now()}`);
323
+ if (!fs.existsSync(targetDir)) {
324
+ fs.mkdirSync(targetDir, { recursive: true });
325
+ }
326
+ pathInfo.targetPath = targetDir;
327
+ }
328
+ npmResolver = new NpmResolver(workPath);
329
+ }
330
+ function storeProjectConfig() {
331
+ const privateConfigPath = `${pathInfo.workPath}/project.private.config.json`;
332
+ const defaultConfigPath = `${pathInfo.workPath}/project.config.json`;
333
+ let privateConfig = {};
334
+ let defaultConfig = {};
335
+ if (fs.existsSync(defaultConfigPath)) {
336
+ try {
337
+ defaultConfig = parseContentByPath(defaultConfigPath);
338
+ } catch (e) {
339
+ console.warn("Failed to parse project.config.json:", e.message);
340
+ }
341
+ }
342
+ if (fs.existsSync(privateConfigPath)) {
343
+ try {
344
+ privateConfig = parseContentByPath(privateConfigPath);
345
+ } catch (e) {
346
+ console.warn("Failed to parse project.private.config.json:", e.message);
347
+ }
348
+ }
349
+ configInfo.projectInfo = { ...defaultConfig, ...privateConfig };
350
+ }
351
+ function storeAppConfig() {
352
+ const filePath = `${pathInfo.workPath}/app.json`;
353
+ const content = parseContentByPath(filePath);
354
+ const newObj = {};
355
+ for (const key in content) {
356
+ if (Object.hasOwn(content, key)) {
357
+ if (key === "subpackages") {
358
+ newObj.subPackages = content[key];
359
+ } else {
360
+ newObj[key] = content[key];
361
+ }
362
+ }
363
+ }
364
+ configInfo.appInfo = newObj;
365
+ }
366
+ function getContentByPath(path2) {
367
+ return fs.readFileSync(path2, { encoding: "utf-8" });
368
+ }
369
+ function parseContentByPath(path2) {
370
+ return JSON.parse(getContentByPath(path2));
371
+ }
372
+ function storePageConfig() {
373
+ const { pages, subPackages } = configInfo.appInfo;
374
+ configInfo.pageInfo = {};
375
+ configInfo.componentInfo = {};
376
+ if (configInfo.appInfo.usingComponents) {
377
+ const appFilePath = `${pathInfo.workPath}/app.json`;
378
+ storeComponentConfig(configInfo.appInfo, appFilePath);
379
+ }
380
+ collectionPageJson(pages);
381
+ if (subPackages) {
382
+ subPackages.forEach((subPkg) => {
383
+ collectionPageJson(subPkg.pages, subPkg.root);
384
+ });
385
+ }
386
+ }
387
+ function collectionPageJson(pages, root) {
388
+ pages.forEach((pagePath) => {
389
+ let np = pagePath;
390
+ if (root) {
391
+ if (!root.endsWith("/")) {
392
+ root += "/";
393
+ }
394
+ np = root + np;
395
+ }
396
+ const pageFilePath = `${pathInfo.workPath}/${np}.json`;
397
+ if (fs.existsSync(pageFilePath)) {
398
+ const pageJsonContent = parseContentByPath(pageFilePath);
399
+ if (root) {
400
+ pageJsonContent.root = transSubDir(root);
401
+ }
402
+ configInfo.pageInfo[np] = pageJsonContent;
403
+ storeComponentConfig(pageJsonContent, pageFilePath);
404
+ }
405
+ });
406
+ }
407
+ function storeComponentConfig(pageJsonContent, pageFilePath) {
408
+ if (isObjectEmpty(pageJsonContent.usingComponents)) {
409
+ return;
410
+ }
411
+ for (const [componentName, componentPath] of Object.entries(pageJsonContent.usingComponents)) {
412
+ const moduleId = getModuleId(componentPath, pageFilePath);
413
+ pageJsonContent.usingComponents[componentName] = moduleId;
414
+ if (configInfo.componentInfo[moduleId]) {
415
+ continue;
416
+ }
417
+ let componentFilePath = path.resolve(getWorkPath(), `./${moduleId}.json`);
418
+ let cContent = null;
419
+ if (fs.existsSync(componentFilePath)) {
420
+ cContent = parseContentByPath(componentFilePath);
421
+ } else {
422
+ const indexJsonPath = path.resolve(getWorkPath(), `./${moduleId}/index.json`);
423
+ if (fs.existsSync(indexJsonPath)) {
424
+ componentFilePath = indexJsonPath;
425
+ cContent = parseContentByPath(componentFilePath);
426
+ } else {
427
+ if (moduleId.includes("/miniprogram_npm/")) {
428
+ console.log(`[env] 为 npm 组件创建默认配置: ${moduleId}`);
429
+ cContent = {
430
+ component: true,
431
+ usingComponents: {}
432
+ };
433
+ } else {
434
+ console.warn(`[env] 组件配置文件不存在: ${componentFilePath}`);
435
+ continue;
436
+ }
437
+ }
438
+ }
439
+ const cUsing = cContent.usingComponents || {};
440
+ const isComponent = cContent.component || false;
441
+ const cComponents = Object.keys(cUsing).reduce((acc, key) => {
442
+ acc[key] = getModuleId(cUsing[key], componentFilePath);
443
+ return acc;
444
+ }, {});
445
+ configInfo.componentInfo[moduleId] = {
446
+ id: uuid(),
447
+ path: moduleId,
448
+ component: isComponent,
449
+ usingComponents: cComponents
450
+ };
451
+ if (cContent.usingComponents && Object.keys(cContent.usingComponents).length > 0) {
452
+ storeComponentConfig(configInfo.componentInfo[moduleId], componentFilePath);
453
+ }
454
+ }
455
+ }
456
+ function getModuleId(src, pageFilePath) {
457
+ if (!npmResolver) {
458
+ const lastIndex = pageFilePath.lastIndexOf("/");
459
+ const newPath = pageFilePath.slice(0, lastIndex);
460
+ const workPath = getWorkPath();
461
+ const res = path.resolve(newPath, src);
462
+ return res.replace(workPath, "");
463
+ }
464
+ return npmResolver.resolveComponentPath(src, pageFilePath);
465
+ }
466
+ function getTargetPath() {
467
+ return pathInfo.targetPath;
468
+ }
469
+ function getComponent(src) {
470
+ return configInfo.componentInfo[src];
471
+ }
472
+ function getPageConfigInfo() {
473
+ return configInfo.pageInfo;
474
+ }
475
+ function getAppConfigInfo() {
476
+ return configInfo.appInfo;
477
+ }
478
+ function getWorkPath() {
479
+ return pathInfo.workPath;
480
+ }
481
+ function getAppId() {
482
+ return configInfo.projectInfo.appid;
483
+ }
484
+ function getAppName() {
485
+ if (configInfo.projectInfo.projectname) {
486
+ return decodeURIComponent(configInfo.projectInfo.projectname);
487
+ }
488
+ return getAppId();
489
+ }
490
+ function transSubDir(name) {
491
+ return `sub_${name.replace(/\/$/, "")}`;
492
+ }
493
+ function getPages() {
494
+ const { pages, subPackages = [], usingComponents: globalComponents = {} } = getAppConfigInfo();
495
+ const pageInfo = getPageConfigInfo();
496
+ const mainPages = pages.map((path2) => {
497
+ const pageComponents = pageInfo[path2]?.usingComponents || {};
498
+ const mergedComponents = { ...globalComponents, ...pageComponents };
499
+ return {
500
+ id: uuid(),
501
+ path: path2,
502
+ usingComponents: mergedComponents
503
+ };
504
+ });
505
+ const subPages = {};
506
+ subPackages.forEach((subPkg) => {
507
+ const rootPath = subPkg.root.endsWith("/") ? subPkg.root : `${subPkg.root}/`;
508
+ const independent = subPkg.independent ? subPkg.independent : false;
509
+ subPages[transSubDir(rootPath)] = {
510
+ independent,
511
+ info: subPkg.pages.map((path2) => {
512
+ const fullPath = rootPath + path2;
513
+ const pageComponents = pageInfo[fullPath]?.usingComponents || {};
514
+ const mergedComponents = { ...globalComponents, ...pageComponents };
515
+ return {
516
+ id: uuid(),
517
+ path: fullPath,
518
+ usingComponents: mergedComponents
519
+ };
520
+ })
521
+ };
522
+ });
523
+ return {
524
+ mainPages,
525
+ subPages
526
+ };
527
+ }
528
+ exports.collectAssets = collectAssets;
529
+ exports.getAbsolutePath = getAbsolutePath;
530
+ exports.getAppConfigInfo = getAppConfigInfo;
531
+ exports.getAppId = getAppId;
532
+ exports.getAppName = getAppName;
533
+ exports.getComponent = getComponent;
534
+ exports.getContentByPath = getContentByPath;
535
+ exports.getPageConfigInfo = getPageConfigInfo;
536
+ exports.getPages = getPages;
537
+ exports.getTargetPath = getTargetPath;
538
+ exports.getWorkPath = getWorkPath;
539
+ exports.hasCompileInfo = hasCompileInfo;
540
+ exports.resetStoreInfo = resetStoreInfo;
541
+ exports.storeInfo = storeInfo;
542
+ exports.tagWhiteList = tagWhiteList;
543
+ exports.transformRpx = transformRpx;