@dimina/compiler 1.0.15 → 1.0.17

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 CHANGED
@@ -126,6 +126,27 @@ miniprogram_npm/ -> npm包构建 (npm组件支持)
126
126
 
127
127
  详细使用说明请参考:[TypeScript、Less 和 SCSS 支持文档](./docs/typescript-less-scss-support.md)
128
128
 
129
+ ### 自定义文件类型(custom file types)
130
+
131
+ 编译器内置识别 `wx*`(`.wxml/.wxss/.wxs`)与 `dd*`(`.ddml/.ddss`)系扩展名。通过编程入口 `build()` 的 `options.fileTypes`,可在内置之上**追加**自定义品牌扩展名(如 `.qdml/.qdss/.qds`),使其与对应内置类型等价编译:
132
+
133
+ ```js
134
+ import build from '@dimina/compiler'
135
+
136
+ await build(targetPath, workPath, true, {
137
+ fileTypes: {
138
+ template: ['qdml'], // 追加模板扩展名,与 .wxml/.ddml 等价 -> view.js
139
+ style: ['qdss'], // 追加样式扩展名,与 .wxss/.ddss 等价 -> style.css
140
+ viewScript: ['qds'], // 追加 WXS 类视图脚本:同时覆盖 .qds 文件与内联 <qds> 标签
141
+ },
142
+ })
143
+ ```
144
+
145
+ - 自动归一化:补前导点、转小写、去重;内置项在前、自定义项在后即查找优先级。
146
+ - 内置 `wx`/`dd` 系永远保留,仅追加不替换。
147
+ - `viewScript` 同时作用于**文件扩展名**(`.qds`)与**内联标签**(`<qds module>`)。
148
+ - CLI 暂未开放对应 flag,自定义文件类型能力通过编程入口注入。
149
+
129
150
  ### npm 组件支持
130
151
 
131
152
  编译器现已支持微信小程序的 npm 包功能,遵循微信官方的 npm 支持规范:
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_env = require("../env-Dmnqp9bD.cjs");
2
+ const require_env = require("../env-BWsUjuZE.cjs");
3
3
  const require_index = require("../index.cjs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_env.__toESM(node_path, 1);
@@ -10,7 +10,7 @@ chokidar = require_env.__toESM(chokidar, 1);
10
10
  let commander = require("commander");
11
11
  var package_default = {
12
12
  name: "@dimina/compiler",
13
- version: "1.0.15",
13
+ version: "1.0.17",
14
14
  description: "星河编译工具",
15
15
  main: "./dist/index.cjs",
16
16
  module: "./dist/index.js",
@@ -57,22 +57,22 @@ var package_default = {
57
57
  "星河"
58
58
  ],
59
59
  dependencies: {
60
- "@vue/compiler-sfc": "^3.5.34",
61
- "autoprefixer": "^10.5.0",
60
+ "@vue/compiler-sfc": "^3.5.39",
61
+ "autoprefixer": "^10.5.2",
62
62
  "cheerio": "^1.2.0",
63
63
  "chokidar": "^4.0.3",
64
64
  "commander": "^14.0.3",
65
- "cssnano": "^8.0.1",
66
- "esbuild": "^0.28.0",
65
+ "cssnano": "^8.0.2",
66
+ "esbuild": "^0.28.1",
67
67
  "htmlparser2": "^12.0.0",
68
- "less": "^4.6.4",
68
+ "less": "^4.6.7",
69
69
  "listr2": "^9.0.5",
70
70
  "magic-string": "^0.30.21",
71
- "oxc-parser": "^0.129.0",
72
- "oxc-walker": "^0.7.0",
73
- "postcss": "^8.5.14",
74
- "postcss-selector-parser": "^7.1.1",
75
- "sass": "^1.99.0",
71
+ "oxc-parser": "^0.137.0",
72
+ "oxc-walker": "^1.0.0",
73
+ "postcss": "^8.5.15",
74
+ "postcss-selector-parser": "^7.1.4",
75
+ "sass": "^1.101.0",
76
76
  "source-map-js": "^1.2.1"
77
77
  },
78
78
  publishConfig: {
package/dist/bin/index.js CHANGED
@@ -6,7 +6,7 @@ import chokidar from "chokidar";
6
6
  import { program } from "commander";
7
7
  var package_default = {
8
8
  name: "@dimina/compiler",
9
- version: "1.0.15",
9
+ version: "1.0.17",
10
10
  description: "星河编译工具",
11
11
  main: "./dist/index.cjs",
12
12
  module: "./dist/index.js",
@@ -53,22 +53,22 @@ var package_default = {
53
53
  "星河"
54
54
  ],
55
55
  dependencies: {
56
- "@vue/compiler-sfc": "^3.5.34",
57
- "autoprefixer": "^10.5.0",
56
+ "@vue/compiler-sfc": "^3.5.39",
57
+ "autoprefixer": "^10.5.2",
58
58
  "cheerio": "^1.2.0",
59
59
  "chokidar": "^4.0.3",
60
60
  "commander": "^14.0.3",
61
- "cssnano": "^8.0.1",
62
- "esbuild": "^0.28.0",
61
+ "cssnano": "^8.0.2",
62
+ "esbuild": "^0.28.1",
63
63
  "htmlparser2": "^12.0.0",
64
- "less": "^4.6.4",
64
+ "less": "^4.6.7",
65
65
  "listr2": "^9.0.5",
66
66
  "magic-string": "^0.30.21",
67
- "oxc-parser": "^0.129.0",
68
- "oxc-walker": "^0.7.0",
69
- "postcss": "^8.5.14",
70
- "postcss-selector-parser": "^7.1.1",
71
- "sass": "^1.99.0",
67
+ "oxc-parser": "^0.137.0",
68
+ "oxc-walker": "^1.0.0",
69
+ "postcss": "^8.5.15",
70
+ "postcss-selector-parser": "^7.1.4",
71
+ "sass": "^1.101.0",
72
72
  "source-map-js": "^1.2.1"
73
73
  },
74
74
  publishConfig: {
@@ -1,8 +1,10 @@
1
+ import { p as getViewScriptTags } from "./env-iShlMOS1.js";
1
2
  import { Parser } from "htmlparser2";
2
3
  //#region src/common/compatibility-reference.js
3
4
  var supportedBuiltinComponents = [
4
5
  "block",
5
6
  "button",
7
+ "canvas",
6
8
  "checkbox",
7
9
  "checkbox-group",
8
10
  "cover-image",
@@ -42,6 +44,7 @@ var supportedBuiltinComponents = [
42
44
  var supportedWxApis = [
43
45
  "env",
44
46
  "canIUse",
47
+ "getUpdateManager",
45
48
  "openSystemBluetoothSetting",
46
49
  "getWindowInfo",
47
50
  "getSystemSetting",
@@ -63,6 +66,9 @@ var supportedWxApis = [
63
66
  "pageScrollTo",
64
67
  "getMenuButtonBoundingClientRect",
65
68
  "createAnimation",
69
+ "createCanvasContext",
70
+ "createOffscreenCanvas",
71
+ "canvasToTempFilePath",
66
72
  "createSelectorQuery",
67
73
  "createIntersectionObserver",
68
74
  "request",
@@ -123,7 +129,7 @@ function warnUnsupportedWxApi(apiName, filePath, line) {
123
129
  }
124
130
  function warnUnsupportedComponent(tagName, filePath, line) {
125
131
  const { supportedBuiltinComponents } = loadReference();
126
- if (!tagName || supportedBuiltinComponents.has(tagName)) return;
132
+ if (!tagName || supportedBuiltinComponents.has(tagName) || getViewScriptTags().includes(tagName)) return;
127
133
  const location = formatLocation(filePath, line);
128
134
  warnOnce("component", tagName, location, `[compat] Unsupported or undeclared component: <${tagName}>${location}`);
129
135
  }
@@ -1,9 +1,10 @@
1
- require("./env-Dmnqp9bD.cjs");
1
+ const require_env = require("./env-BWsUjuZE.cjs");
2
2
  let htmlparser2 = require("htmlparser2");
3
3
  //#region src/common/compatibility-reference.js
4
4
  var supportedBuiltinComponents = [
5
5
  "block",
6
6
  "button",
7
+ "canvas",
7
8
  "checkbox",
8
9
  "checkbox-group",
9
10
  "cover-image",
@@ -43,6 +44,7 @@ var supportedBuiltinComponents = [
43
44
  var supportedWxApis = [
44
45
  "env",
45
46
  "canIUse",
47
+ "getUpdateManager",
46
48
  "openSystemBluetoothSetting",
47
49
  "getWindowInfo",
48
50
  "getSystemSetting",
@@ -64,6 +66,9 @@ var supportedWxApis = [
64
66
  "pageScrollTo",
65
67
  "getMenuButtonBoundingClientRect",
66
68
  "createAnimation",
69
+ "createCanvasContext",
70
+ "createOffscreenCanvas",
71
+ "canvasToTempFilePath",
67
72
  "createSelectorQuery",
68
73
  "createIntersectionObserver",
69
74
  "request",
@@ -124,7 +129,7 @@ function warnUnsupportedWxApi(apiName, filePath, line) {
124
129
  }
125
130
  function warnUnsupportedComponent(tagName, filePath, line) {
126
131
  const { supportedBuiltinComponents } = loadReference();
127
- if (!tagName || supportedBuiltinComponents.has(tagName)) return;
132
+ if (!tagName || supportedBuiltinComponents.has(tagName) || require_env.getViewScriptTags().includes(tagName)) return;
128
133
  const location = formatLocation(filePath, line);
129
134
  warnOnce("component", tagName, location, `[compat] Unsupported or undeclared component: <${tagName}>${location}`);
130
135
  }
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_env = require("../env-Dmnqp9bD.cjs");
3
- const require_compatibility = require("../compatibility-DlYbbw0F.cjs");
2
+ const require_env = require("../env-BWsUjuZE.cjs");
3
+ const require_compatibility = require("../compatibility-DnN63SVV.cjs");
4
4
  let node_path = require("node:path");
5
5
  let node_worker_threads = require("node:worker_threads");
6
6
  let node_fs = require("node:fs");
@@ -1,5 +1,5 @@
1
- import { a as getContentByPath, d as resetStoreInfo, f as resolveAppAlias, g as hasCompileInfo, i as getComponent, l as getTargetPath, m as collectAssets, n as getAppId, o as getNpmResolver, t as getAppConfigInfo, u as getWorkPath } from "../env-p9Az8lv5.js";
2
- import { n as getWxMemberName, r as warnUnsupportedWxApi } from "../compatibility-C_zWVjYl.js";
1
+ import { a as getContentByPath, b as hasCompileInfo, g as resolveAppAlias, h as resetStoreInfo, i as getComponent, m as getWorkPath, n as getAppId, o as getNpmResolver, t as getAppConfigInfo, u as getTargetPath, v as collectAssets } from "../env-iShlMOS1.js";
2
+ import { n as getWxMemberName, r as warnUnsupportedWxApi } from "../compatibility-DbP7rQJN.js";
3
3
  import { resolve, sep } from "node:path";
4
4
  import { isMainThread, parentPort } from "node:worker_threads";
5
5
  import fs from "node:fs";
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_env = require("../env-Dmnqp9bD.cjs");
2
+ const require_env = require("../env-BWsUjuZE.cjs");
3
3
  let node_path = require("node:path");
4
4
  node_path = require_env.__toESM(node_path, 1);
5
5
  let node_worker_threads = require("node:worker_threads");
@@ -19,13 +19,6 @@ postcss_selector_parser = require_env.__toESM(postcss_selector_parser, 1);
19
19
  let sass = require("sass");
20
20
  sass = require_env.__toESM(sass, 1);
21
21
  //#region src/core/style-compiler.js
22
- var fileType = [
23
- ".wxss",
24
- ".ddss",
25
- ".less",
26
- ".scss",
27
- ".sass"
28
- ];
29
22
  var compileRes = /* @__PURE__ */ new Map();
30
23
  if (!node_worker_threads.isMainThread) node_worker_threads.parentPort.on("message", async ({ pages, storeInfo }) => {
31
24
  try {
@@ -99,9 +92,10 @@ async function buildCompileCss(module, depthChain = [], compiledPaths = /* @__PU
99
92
  async function enhanceCSS(module) {
100
93
  const absolutePath = module.absolutePath ? module.absolutePath : getAbsolutePath(module.path);
101
94
  if (!absolutePath) return "";
95
+ const cacheKey = `${absolutePath}::${module.id || ""}`;
102
96
  const inputCSS = require_env.getContentByPath(absolutePath);
103
97
  if (!inputCSS) return "";
104
- if (compileRes.has(absolutePath)) return compileRes.get(absolutePath);
98
+ if (compileRes.has(cacheKey)) return compileRes.get(cacheKey);
105
99
  let processedCSS = normalizeRootStyleImports(inputCSS);
106
100
  const ext = node_path.default.extname(absolutePath).toLowerCase();
107
101
  try {
@@ -158,7 +152,7 @@ async function enhanceCSS(module) {
158
152
  const cleanedCode = await removeBaseComponentScope(scopedCode, moduleId);
159
153
  const res = await (0, postcss.default)([(0, autoprefixer.default)({ overrideBrowserslist: ["cover 99.5%"] }), (0, cssnano.default)()]).process(cleanedCode, { from: void 0 });
160
154
  const result = (await Promise.all(promises)).filter(Boolean).join("") + res.css;
161
- compileRes.set(absolutePath, result);
155
+ compileRes.set(cacheKey, result);
162
156
  return result;
163
157
  }
164
158
  function normalizeCssUrlValue(value, absolutePath) {
@@ -173,7 +167,7 @@ function normalizeCssUrlValue(value, absolutePath) {
173
167
  function getAbsolutePath(modulePath) {
174
168
  const workPath = require_env.getWorkPath();
175
169
  const src = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
176
- for (const ssType of fileType) {
170
+ for (const ssType of require_env.getStyleExts()) {
177
171
  const ssFullPath = `${workPath}${src}${ssType}`;
178
172
  if (node_fs.default.existsSync(ssFullPath)) return ssFullPath;
179
173
  const indexSsFullPath = `${workPath}${src}/index${ssType}`;
@@ -1,4 +1,4 @@
1
- import { _ as tagWhiteList, a as getContentByPath, d as resetStoreInfo, i as getComponent, l as getTargetPath, m as collectAssets, n as getAppId, u as getWorkPath, v as transformRpx } from "../env-p9Az8lv5.js";
1
+ import { S as transformRpx, a as getContentByPath, h as resetStoreInfo, i as getComponent, l as getStyleExts, m as getWorkPath, n as getAppId, u as getTargetPath, v as collectAssets, x as tagWhiteList } from "../env-iShlMOS1.js";
2
2
  import path from "node:path";
3
3
  import { isMainThread, parentPort } from "node:worker_threads";
4
4
  import fs from "node:fs";
@@ -10,13 +10,6 @@ import postcss from "postcss";
10
10
  import selectorParser from "postcss-selector-parser";
11
11
  import * as sass from "sass";
12
12
  //#region src/core/style-compiler.js
13
- var fileType = [
14
- ".wxss",
15
- ".ddss",
16
- ".less",
17
- ".scss",
18
- ".sass"
19
- ];
20
13
  var compileRes = /* @__PURE__ */ new Map();
21
14
  if (!isMainThread) parentPort.on("message", async ({ pages, storeInfo }) => {
22
15
  try {
@@ -90,9 +83,10 @@ async function buildCompileCss(module, depthChain = [], compiledPaths = /* @__PU
90
83
  async function enhanceCSS(module) {
91
84
  const absolutePath = module.absolutePath ? module.absolutePath : getAbsolutePath(module.path);
92
85
  if (!absolutePath) return "";
86
+ const cacheKey = `${absolutePath}::${module.id || ""}`;
93
87
  const inputCSS = getContentByPath(absolutePath);
94
88
  if (!inputCSS) return "";
95
- if (compileRes.has(absolutePath)) return compileRes.get(absolutePath);
89
+ if (compileRes.has(cacheKey)) return compileRes.get(cacheKey);
96
90
  let processedCSS = normalizeRootStyleImports(inputCSS);
97
91
  const ext = path.extname(absolutePath).toLowerCase();
98
92
  try {
@@ -149,7 +143,7 @@ async function enhanceCSS(module) {
149
143
  const cleanedCode = await removeBaseComponentScope(scopedCode, moduleId);
150
144
  const res = await postcss([autoprefixer({ overrideBrowserslist: ["cover 99.5%"] }), cssnano()]).process(cleanedCode, { from: void 0 });
151
145
  const result = (await Promise.all(promises)).filter(Boolean).join("") + res.css;
152
- compileRes.set(absolutePath, result);
146
+ compileRes.set(cacheKey, result);
153
147
  return result;
154
148
  }
155
149
  function normalizeCssUrlValue(value, absolutePath) {
@@ -164,7 +158,7 @@ function normalizeCssUrlValue(value, absolutePath) {
164
158
  function getAbsolutePath(modulePath) {
165
159
  const workPath = getWorkPath();
166
160
  const src = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
167
- for (const ssType of fileType) {
161
+ for (const ssType of getStyleExts()) {
168
162
  const ssFullPath = `${workPath}${src}${ssType}`;
169
163
  if (fs.existsSync(ssFullPath)) return ssFullPath;
170
164
  const indexSsFullPath = `${workPath}${src}/index${ssType}`;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_env = require("../env-Dmnqp9bD.cjs");
3
- const require_compatibility = require("../compatibility-DlYbbw0F.cjs");
2
+ const require_env = require("../env-BWsUjuZE.cjs");
3
+ const require_compatibility = require("../compatibility-DnN63SVV.cjs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_env.__toESM(node_path, 1);
6
6
  let node_worker_threads = require("node:worker_threads");
@@ -20,7 +20,7 @@ htmlparser2 = require_env.__toESM(htmlparser2, 1);
20
20
  /**
21
21
  * 表达式解析器 - 使用 Oxc AST 解析器提取依赖
22
22
  */
23
- var KEYWORDS = new Set([
23
+ var KEYWORDS = /* @__PURE__ */ new Set([
24
24
  "true",
25
25
  "false",
26
26
  "null",
@@ -129,7 +129,19 @@ function parseBindings(bindings) {
129
129
  }
130
130
  //#endregion
131
131
  //#region src/core/view-compiler.js
132
- var fileType = [".wxml", ".ddml"];
132
+ /**
133
+ * 根据扩展名列表生成匹配尾部扩展名的正则,如 ['.wxs', '.qds'] -> /(\.wxs|\.qds)$/
134
+ */
135
+ function buildExtStripRegex(exts) {
136
+ const alt = exts.map((e) => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
137
+ return new RegExp(`(${alt})$`);
138
+ }
139
+ /**
140
+ * 移除视图脚本文件路径末尾的扩展名,支持 .wxs 和自定义扩展名
141
+ */
142
+ function stripViewScriptExt(p) {
143
+ return p.replace(buildExtStripRegex(require_env.getViewScriptExts()), "");
144
+ }
133
145
  /**
134
146
  * 解析 JavaScript 代码
135
147
  * @param {string} code
@@ -316,8 +328,8 @@ function scanWxsFiles(dir, workPath) {
316
328
  const fullPath = node_path.default.join(dir, item);
317
329
  const stat = node_fs.default.statSync(fullPath);
318
330
  if (stat.isDirectory()) scanWxsFiles(fullPath, workPath);
319
- else if (stat.isFile() && item.endsWith(".wxs")) {
320
- const moduleName = fullPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
331
+ else if (stat.isFile() && require_env.getViewScriptExts().some((ext) => item.endsWith(ext))) {
332
+ const moduleName = stripViewScriptExt(fullPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
321
333
  wxsFilePathMap.set(moduleName, fullPath);
322
334
  }
323
335
  }
@@ -529,7 +541,7 @@ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, file
529
541
  if (filePath && filePath.includes("/miniprogram_npm/")) {
530
542
  const currentWxsDir = node_path.default.dirname(wxsFilePath);
531
543
  resolvedWxsPath = node_path.default.resolve(currentWxsDir, requirePath);
532
- const moduleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
544
+ const moduleName = stripViewScriptExt(resolvedWxsPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
533
545
  processWxsDependency(resolvedWxsPath, moduleName, scriptModule, workPath, filePath);
534
546
  replacements.push({
535
547
  start: node.arguments[0].start,
@@ -539,7 +551,7 @@ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, file
539
551
  } else {
540
552
  const currentWxsDir = node_path.default.dirname(wxsFilePath);
541
553
  resolvedWxsPath = node_path.default.resolve(currentWxsDir, requirePath);
542
- const depModuleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
554
+ const depModuleName = stripViewScriptExt(resolvedWxsPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
543
555
  processWxsDependency(resolvedWxsPath, depModuleName, scriptModule, workPath, filePath);
544
556
  replacements.push({
545
557
  start: node.arguments[0].start,
@@ -747,7 +759,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
747
759
  const src = $(elem).attr("src");
748
760
  if (src) {
749
761
  const includeFullPath = require_env.getAbsolutePath(workPath, path, src);
750
- let includePath = includeFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
762
+ let includePath = includeFullPath.replace(workPath, "").replace(buildExtStripRegex(require_env.getTemplateExts()), "");
751
763
  const includeDiagnosticSource = includeFullPath.startsWith(workPath) ? includeFullPath.slice(workPath.length) : includePath;
752
764
  if (!includePath.startsWith("/")) includePath = "/" + includePath;
753
765
  const includeContent = require_env.getContentByPath(includeFullPath).trim();
@@ -761,8 +773,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
761
773
  transTagWxs($includeContent, scriptModule, includePath);
762
774
  processIncludedFileWxsDependencies(includeContent, includePath, scriptModule, components, processedPaths);
763
775
  $includeContent("template").remove();
764
- $includeContent("wxs").remove();
765
- $includeContent("dds").remove();
776
+ $includeContent(require_env.getViewScriptTags().join(",")).remove();
766
777
  const processedContent = processIncludeConditionalAttrs($, elem, $includeContent.html());
767
778
  $(elem).replaceWith(processedContent);
768
779
  } else $(elem).remove();
@@ -775,7 +786,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
775
786
  const src = $(elem).attr("src");
776
787
  if (src) {
777
788
  const importFullPath = require_env.getAbsolutePath(workPath, path, src);
778
- let importPath = importFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
789
+ let importPath = importFullPath.replace(workPath, "").replace(buildExtStripRegex(require_env.getTemplateExts()), "");
779
790
  const importDiagnosticSource = importFullPath.startsWith(workPath) ? importFullPath.slice(workPath.length) : importPath;
780
791
  if (!importPath.startsWith("/")) importPath = "/" + importPath;
781
792
  const importContent = require_env.getContentByPath(importFullPath).trim();
@@ -810,8 +821,7 @@ function transTagTemplate($, templateModule, path, components, componentPlacehol
810
821
  const templateContent = $(elem);
811
822
  templateContent.find("import").remove();
812
823
  templateContent.find("include").remove();
813
- templateContent.find("wxs").remove();
814
- templateContent.find("dds").remove();
824
+ templateContent.find(require_env.getViewScriptTags().join(",")).remove();
815
825
  transAsses($, templateContent.find("image"), path);
816
826
  const res = [];
817
827
  transHtmlTag(templateContent.html(), res, components, componentPlaceholder);
@@ -1077,7 +1087,7 @@ function parseKeyExpression(exp, itemName = "item", indexName = "index") {
1077
1087
  */
1078
1088
  function getViewPath(workPath, src) {
1079
1089
  const aSrc = src.startsWith("/") ? src : `/${src}`;
1080
- for (const mlType of fileType) {
1090
+ for (const mlType of require_env.getTemplateExts()) {
1081
1091
  const mlFullPath = `${workPath}${aSrc}${mlType}`;
1082
1092
  if (node_fs.default.existsSync(mlFullPath)) return mlFullPath;
1083
1093
  const indexMlFullPath = `${workPath}${aSrc}/index${mlType}`;
@@ -1189,8 +1199,7 @@ function parseTemplateDataExp(exp) {
1189
1199
  return `{${parseBraceExp(exp)}}`;
1190
1200
  }
1191
1201
  function transTagWxs($, scriptModule, filePath) {
1192
- let wxsNodes = $("wxs");
1193
- if (wxsNodes.length === 0) wxsNodes = $("dds");
1202
+ const wxsNodes = $(require_env.getViewScriptTags().join(","));
1194
1203
  wxsNodes.each((_, elem) => {
1195
1204
  const smName = $(elem).attr("module");
1196
1205
  if (smName) {
@@ -1206,7 +1215,7 @@ function transTagWxs($, scriptModule, filePath) {
1206
1215
  wxsFilePath = node_path.default.resolve(componentFullPath, src);
1207
1216
  } else wxsFilePath = require_env.getAbsolutePath(workPath, filePath, src);
1208
1217
  if (wxsFilePath) {
1209
- uniqueModuleName = wxsFilePath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
1218
+ uniqueModuleName = stripViewScriptExt(wxsFilePath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
1210
1219
  cacheKey = wxsFilePath;
1211
1220
  }
1212
1221
  }
@@ -1254,7 +1263,7 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1254
1263
  });
1255
1264
  const dependencies = extractWxsDependencies(moduleCode);
1256
1265
  for (const depPath of dependencies) if (!collectedPaths.has(depPath)) if (scriptRes.has(depPath)) {
1257
- const depModules = collectAllWxsModules(new Map([[depPath, scriptRes.get(depPath)]]), collectedPaths, scriptModule);
1266
+ const depModules = collectAllWxsModules(/* @__PURE__ */ new Map([[depPath, scriptRes.get(depPath)]]), collectedPaths, scriptModule);
1258
1267
  allWxsModules.push(...depModules);
1259
1268
  } else {
1260
1269
  const loaded = loadWxsModule(depPath, workPath, scriptModule);
@@ -1262,7 +1271,7 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1262
1271
  scriptRes.set(depPath, loaded.code);
1263
1272
  allWxsModules.push(loaded);
1264
1273
  collectedPaths.add(depPath);
1265
- const depModules = collectAllWxsModules(new Map([[depPath, loaded.code]]), collectedPaths, scriptModule);
1274
+ const depModules = collectAllWxsModules(/* @__PURE__ */ new Map([[depPath, loaded.code]]), collectedPaths, scriptModule);
1266
1275
  allWxsModules.push(...depModules);
1267
1276
  }
1268
1277
  }
@@ -1278,12 +1287,8 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1278
1287
  * @returns {Object|null} 加载的模块对象或 null
1279
1288
  */
1280
1289
  function loadWxsModule(modulePath, workPath, scriptModule) {
1281
- if (!modulePath.startsWith("miniprogram_npm__") || !modulePath.includes("_wxs_")) return null;
1282
1290
  const wxsFilePath = wxsFilePathMap.get(modulePath);
1283
- if (!wxsFilePath) {
1284
- console.warn(`[view] 无法找到 wxs 模块文件: ${modulePath}`);
1285
- return null;
1286
- }
1291
+ if (!wxsFilePath) return null;
1287
1292
  try {
1288
1293
  const wxsContent = require_env.getContentByPath(wxsFilePath).trim();
1289
1294
  if (!wxsContent) return null;
@@ -1355,6 +1360,8 @@ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render
1355
1360
  exports.compileML = compileML;
1356
1361
  exports.generateSlotDirective = generateSlotDirective;
1357
1362
  exports.generateVModelTemplate = generateVModelTemplate;
1363
+ exports.initWxsFilePathMap = initWxsFilePathMap;
1364
+ exports.loadWxsModule = loadWxsModule;
1358
1365
  exports.parseBraceExp = parseBraceExp;
1359
1366
  exports.parseClassRules = parseClassRules;
1360
1367
  exports.parseKeyExpression = parseKeyExpression;
@@ -1,5 +1,5 @@
1
- import { _ as tagWhiteList, a as getContentByPath, d as resetStoreInfo, h as getAbsolutePath, i as getComponent, l as getTargetPath, m as collectAssets, n as getAppId, u as getWorkPath, v as transformRpx } from "../env-p9Az8lv5.js";
2
- import { t as checkTemplateCompatibility } from "../compatibility-C_zWVjYl.js";
1
+ import { S as transformRpx, a as getContentByPath, d as getTemplateExts, f as getViewScriptExts, h as resetStoreInfo, i as getComponent, m as getWorkPath, n as getAppId, p as getViewScriptTags, u as getTargetPath, v as collectAssets, x as tagWhiteList, y as getAbsolutePath } from "../env-iShlMOS1.js";
2
+ import { t as checkTemplateCompatibility } from "../compatibility-DbP7rQJN.js";
3
3
  import path from "node:path";
4
4
  import { isMainThread, parentPort } from "node:worker_threads";
5
5
  import fs from "node:fs";
@@ -14,7 +14,7 @@ import * as htmlparser2 from "htmlparser2";
14
14
  /**
15
15
  * 表达式解析器 - 使用 Oxc AST 解析器提取依赖
16
16
  */
17
- var KEYWORDS = new Set([
17
+ var KEYWORDS = /* @__PURE__ */ new Set([
18
18
  "true",
19
19
  "false",
20
20
  "null",
@@ -123,7 +123,19 @@ function parseBindings(bindings) {
123
123
  }
124
124
  //#endregion
125
125
  //#region src/core/view-compiler.js
126
- var fileType = [".wxml", ".ddml"];
126
+ /**
127
+ * 根据扩展名列表生成匹配尾部扩展名的正则,如 ['.wxs', '.qds'] -> /(\.wxs|\.qds)$/
128
+ */
129
+ function buildExtStripRegex(exts) {
130
+ const alt = exts.map((e) => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
131
+ return new RegExp(`(${alt})$`);
132
+ }
133
+ /**
134
+ * 移除视图脚本文件路径末尾的扩展名,支持 .wxs 和自定义扩展名
135
+ */
136
+ function stripViewScriptExt(p) {
137
+ return p.replace(buildExtStripRegex(getViewScriptExts()), "");
138
+ }
127
139
  /**
128
140
  * 解析 JavaScript 代码
129
141
  * @param {string} code
@@ -310,8 +322,8 @@ function scanWxsFiles(dir, workPath) {
310
322
  const fullPath = path.join(dir, item);
311
323
  const stat = fs.statSync(fullPath);
312
324
  if (stat.isDirectory()) scanWxsFiles(fullPath, workPath);
313
- else if (stat.isFile() && item.endsWith(".wxs")) {
314
- const moduleName = fullPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
325
+ else if (stat.isFile() && getViewScriptExts().some((ext) => item.endsWith(ext))) {
326
+ const moduleName = stripViewScriptExt(fullPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
315
327
  wxsFilePathMap.set(moduleName, fullPath);
316
328
  }
317
329
  }
@@ -523,7 +535,7 @@ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, file
523
535
  if (filePath && filePath.includes("/miniprogram_npm/")) {
524
536
  const currentWxsDir = path.dirname(wxsFilePath);
525
537
  resolvedWxsPath = path.resolve(currentWxsDir, requirePath);
526
- const moduleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
538
+ const moduleName = stripViewScriptExt(resolvedWxsPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
527
539
  processWxsDependency(resolvedWxsPath, moduleName, scriptModule, workPath, filePath);
528
540
  replacements.push({
529
541
  start: node.arguments[0].start,
@@ -533,7 +545,7 @@ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, file
533
545
  } else {
534
546
  const currentWxsDir = path.dirname(wxsFilePath);
535
547
  resolvedWxsPath = path.resolve(currentWxsDir, requirePath);
536
- const depModuleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
548
+ const depModuleName = stripViewScriptExt(resolvedWxsPath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
537
549
  processWxsDependency(resolvedWxsPath, depModuleName, scriptModule, workPath, filePath);
538
550
  replacements.push({
539
551
  start: node.arguments[0].start,
@@ -741,7 +753,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
741
753
  const src = $(elem).attr("src");
742
754
  if (src) {
743
755
  const includeFullPath = getAbsolutePath(workPath, path, src);
744
- let includePath = includeFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
756
+ let includePath = includeFullPath.replace(workPath, "").replace(buildExtStripRegex(getTemplateExts()), "");
745
757
  const includeDiagnosticSource = includeFullPath.startsWith(workPath) ? includeFullPath.slice(workPath.length) : includePath;
746
758
  if (!includePath.startsWith("/")) includePath = "/" + includePath;
747
759
  const includeContent = getContentByPath(includeFullPath).trim();
@@ -755,8 +767,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
755
767
  transTagWxs($includeContent, scriptModule, includePath);
756
768
  processIncludedFileWxsDependencies(includeContent, includePath, scriptModule, components, processedPaths);
757
769
  $includeContent("template").remove();
758
- $includeContent("wxs").remove();
759
- $includeContent("dds").remove();
770
+ $includeContent(getViewScriptTags().join(",")).remove();
760
771
  const processedContent = processIncludeConditionalAttrs($, elem, $includeContent.html());
761
772
  $(elem).replaceWith(processedContent);
762
773
  } else $(elem).remove();
@@ -769,7 +780,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
769
780
  const src = $(elem).attr("src");
770
781
  if (src) {
771
782
  const importFullPath = getAbsolutePath(workPath, path, src);
772
- let importPath = importFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
783
+ let importPath = importFullPath.replace(workPath, "").replace(buildExtStripRegex(getTemplateExts()), "");
773
784
  const importDiagnosticSource = importFullPath.startsWith(workPath) ? importFullPath.slice(workPath.length) : importPath;
774
785
  if (!importPath.startsWith("/")) importPath = "/" + importPath;
775
786
  const importContent = getContentByPath(importFullPath).trim();
@@ -804,8 +815,7 @@ function transTagTemplate($, templateModule, path, components, componentPlacehol
804
815
  const templateContent = $(elem);
805
816
  templateContent.find("import").remove();
806
817
  templateContent.find("include").remove();
807
- templateContent.find("wxs").remove();
808
- templateContent.find("dds").remove();
818
+ templateContent.find(getViewScriptTags().join(",")).remove();
809
819
  transAsses($, templateContent.find("image"), path);
810
820
  const res = [];
811
821
  transHtmlTag(templateContent.html(), res, components, componentPlaceholder);
@@ -1071,7 +1081,7 @@ function parseKeyExpression(exp, itemName = "item", indexName = "index") {
1071
1081
  */
1072
1082
  function getViewPath(workPath, src) {
1073
1083
  const aSrc = src.startsWith("/") ? src : `/${src}`;
1074
- for (const mlType of fileType) {
1084
+ for (const mlType of getTemplateExts()) {
1075
1085
  const mlFullPath = `${workPath}${aSrc}${mlType}`;
1076
1086
  if (fs.existsSync(mlFullPath)) return mlFullPath;
1077
1087
  const indexMlFullPath = `${workPath}${aSrc}/index${mlType}`;
@@ -1183,8 +1193,7 @@ function parseTemplateDataExp(exp) {
1183
1193
  return `{${parseBraceExp(exp)}}`;
1184
1194
  }
1185
1195
  function transTagWxs($, scriptModule, filePath) {
1186
- let wxsNodes = $("wxs");
1187
- if (wxsNodes.length === 0) wxsNodes = $("dds");
1196
+ const wxsNodes = $(getViewScriptTags().join(","));
1188
1197
  wxsNodes.each((_, elem) => {
1189
1198
  const smName = $(elem).attr("module");
1190
1199
  if (smName) {
@@ -1200,7 +1209,7 @@ function transTagWxs($, scriptModule, filePath) {
1200
1209
  wxsFilePath = path.resolve(componentFullPath, src);
1201
1210
  } else wxsFilePath = getAbsolutePath(workPath, filePath, src);
1202
1211
  if (wxsFilePath) {
1203
- uniqueModuleName = wxsFilePath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
1212
+ uniqueModuleName = stripViewScriptExt(wxsFilePath.replace(workPath, "")).replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
1204
1213
  cacheKey = wxsFilePath;
1205
1214
  }
1206
1215
  }
@@ -1248,7 +1257,7 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1248
1257
  });
1249
1258
  const dependencies = extractWxsDependencies(moduleCode);
1250
1259
  for (const depPath of dependencies) if (!collectedPaths.has(depPath)) if (scriptRes.has(depPath)) {
1251
- const depModules = collectAllWxsModules(new Map([[depPath, scriptRes.get(depPath)]]), collectedPaths, scriptModule);
1260
+ const depModules = collectAllWxsModules(/* @__PURE__ */ new Map([[depPath, scriptRes.get(depPath)]]), collectedPaths, scriptModule);
1252
1261
  allWxsModules.push(...depModules);
1253
1262
  } else {
1254
1263
  const loaded = loadWxsModule(depPath, workPath, scriptModule);
@@ -1256,7 +1265,7 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1256
1265
  scriptRes.set(depPath, loaded.code);
1257
1266
  allWxsModules.push(loaded);
1258
1267
  collectedPaths.add(depPath);
1259
- const depModules = collectAllWxsModules(new Map([[depPath, loaded.code]]), collectedPaths, scriptModule);
1268
+ const depModules = collectAllWxsModules(/* @__PURE__ */ new Map([[depPath, loaded.code]]), collectedPaths, scriptModule);
1260
1269
  allWxsModules.push(...depModules);
1261
1270
  }
1262
1271
  }
@@ -1272,12 +1281,8 @@ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Se
1272
1281
  * @returns {Object|null} 加载的模块对象或 null
1273
1282
  */
1274
1283
  function loadWxsModule(modulePath, workPath, scriptModule) {
1275
- if (!modulePath.startsWith("miniprogram_npm__") || !modulePath.includes("_wxs_")) return null;
1276
1284
  const wxsFilePath = wxsFilePathMap.get(modulePath);
1277
- if (!wxsFilePath) {
1278
- console.warn(`[view] 无法找到 wxs 模块文件: ${modulePath}`);
1279
- return null;
1280
- }
1285
+ if (!wxsFilePath) return null;
1281
1286
  try {
1282
1287
  const wxsContent = getContentByPath(wxsFilePath).trim();
1283
1288
  if (!wxsContent) return null;
@@ -1346,4 +1351,4 @@ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render
1346
1351
  return getProgramCode(transformed, parseJs(transformed, filename));
1347
1352
  }
1348
1353
  //#endregion
1349
- export { compileML, generateSlotDirective, generateVModelTemplate, parseBraceExp, parseClassRules, parseKeyExpression, parseTemplateDataExp, processIncludeConditionalAttrs, processWxsContent, splitWithBraces };
1354
+ export { compileML, generateSlotDirective, generateVModelTemplate, initWxsFilePathMap, loadWxsModule, parseBraceExp, parseClassRules, parseKeyExpression, parseTemplateDataExp, processIncludeConditionalAttrs, processWxsContent, splitWithBraces };
@@ -343,24 +343,113 @@ var NpmResolver = class {
343
343
  var pathInfo = {};
344
344
  var configInfo = {};
345
345
  var npmResolver = null;
346
+ var DEFAULT_TEMPLATE_EXTS = [".wxml", ".ddml"];
347
+ var DEFAULT_STYLE_EXTS = [
348
+ ".wxss",
349
+ ".ddss",
350
+ ".less",
351
+ ".scss",
352
+ ".sass"
353
+ ];
354
+ var DEFAULT_VIEW_SCRIPT_EXTS = [".wxs"];
355
+ var DEFAULT_VIEW_SCRIPT_TAGS = ["wxs", "dds"];
356
+ var RESERVED_EXTS = /* @__PURE__ */ new Set([
357
+ ...DEFAULT_TEMPLATE_EXTS,
358
+ ...DEFAULT_STYLE_EXTS,
359
+ ...DEFAULT_VIEW_SCRIPT_EXTS,
360
+ ".js",
361
+ ".ts",
362
+ ".json"
363
+ ]);
364
+ var compilerOptions = normalizeFileTypes();
365
+ /**
366
+ * 将单项规范化为扩展名:去除首尾空白、转小写并补一个前导点。
367
+ * 仅接受字母、数字、连字符和下划线;空字符串、路径分隔符或其他元字符
368
+ * 均返回 null,由调用方丢弃。扩展名会用于生成尾部匹配正则和查找文件,
369
+ * 放行元字符可能导致误匹配。
370
+ */
371
+ function normalizeExt(raw) {
372
+ if (typeof raw !== "string") return null;
373
+ const v = raw.trim().toLowerCase().replace(/^\.+/, "");
374
+ if (!/^[a-z0-9_-]+$/.test(v)) return null;
375
+ return `.${v}`;
376
+ }
377
+ /**
378
+ * 将单项规范化为内联标签名:去除首尾空白、转小写并移除前导点。
379
+ * 标签名会用于拼接 Cheerio 选择器(如 transTagWxs),因此必须以字母开头,
380
+ * 且只能包含字母、数字、连字符和下划线。拒绝选择器元字符,避免 'qds,view'
381
+ * 误选并删除 <view>,破坏编译产物。
382
+ */
383
+ function normalizeTag(raw) {
384
+ if (typeof raw !== "string") return null;
385
+ const v = raw.trim().toLowerCase().replace(/^\.+/, "");
386
+ if (!/^[a-z][a-z0-9_-]*$/.test(v)) return null;
387
+ return v;
388
+ }
389
+ /**
390
+ * 合并并去重内置项和自定义项;内置项在前,顺序即同名文件的查找优先级。
391
+ * 传入 reserved 时,落在其中的自定义项被丢弃(防止占用其他角色/逻辑/配置的扩展名)。
392
+ */
393
+ function mergeUnique(builtins, custom, normalizer, reserved) {
394
+ const out = [...builtins];
395
+ const seen = new Set(builtins);
396
+ if (Array.isArray(custom)) for (const raw of custom) {
397
+ const n = normalizer(raw);
398
+ if (n && !seen.has(n) && !reserved?.has(n)) {
399
+ seen.add(n);
400
+ out.push(n);
401
+ }
402
+ }
403
+ return out;
404
+ }
405
+ /**
406
+ * 根据 options.fileTypes 生成本次构建使用的自定义扩展名和标签。
407
+ * viewScript 同时用于生成文件扩展名和内联标签。
408
+ */
409
+ function normalizeFileTypes(fileTypes = {}) {
410
+ const ft = fileTypes || {};
411
+ return {
412
+ templateExts: mergeUnique(DEFAULT_TEMPLATE_EXTS, ft.template, normalizeExt, RESERVED_EXTS),
413
+ styleExts: mergeUnique(DEFAULT_STYLE_EXTS, ft.style, normalizeExt, RESERVED_EXTS),
414
+ viewScriptExts: mergeUnique(DEFAULT_VIEW_SCRIPT_EXTS, ft.viewScript, normalizeExt, RESERVED_EXTS),
415
+ viewScriptTags: mergeUnique(DEFAULT_VIEW_SCRIPT_TAGS, ft.viewScript, normalizeTag)
416
+ };
417
+ }
346
418
  /**
347
419
  * 持久化编译过程的上下文
420
+ * @param {string} workPath 编译工作目录
421
+ * @param {{ fileTypes?: { template?: string[], style?: string[], viewScript?: string[] } }} [options] 构建选项
348
422
  */
349
- function storeInfo(workPath) {
423
+ function storeInfo(workPath, options = {}) {
350
424
  storePathInfo(workPath);
351
425
  storeProjectConfig();
352
426
  storeAppConfig();
353
427
  storePageConfig();
428
+ compilerOptions = normalizeFileTypes(options.fileTypes);
354
429
  return {
355
430
  pathInfo,
356
- configInfo
431
+ configInfo,
432
+ compilerOptions
357
433
  };
358
434
  }
359
435
  function resetStoreInfo(opts) {
360
436
  pathInfo = opts.pathInfo;
361
437
  configInfo = opts.configInfo;
438
+ compilerOptions = opts.compilerOptions || normalizeFileTypes();
362
439
  if (pathInfo.workPath) npmResolver = new NpmResolver(pathInfo.workPath);
363
440
  }
441
+ function getTemplateExts() {
442
+ return compilerOptions.templateExts;
443
+ }
444
+ function getStyleExts() {
445
+ return compilerOptions.styleExts;
446
+ }
447
+ function getViewScriptExts() {
448
+ return compilerOptions.viewScriptExts;
449
+ }
450
+ function getViewScriptTags() {
451
+ return compilerOptions.viewScriptTags;
452
+ }
364
453
  function storePathInfo(workPath) {
365
454
  pathInfo.workPath = workPath;
366
455
  if (node_process.default.env.TARGET_PATH) pathInfo.targetPath = node_process.default.env.TARGET_PATH;
@@ -655,12 +744,36 @@ Object.defineProperty(exports, "getPages", {
655
744
  return getPages;
656
745
  }
657
746
  });
747
+ Object.defineProperty(exports, "getStyleExts", {
748
+ enumerable: true,
749
+ get: function() {
750
+ return getStyleExts;
751
+ }
752
+ });
658
753
  Object.defineProperty(exports, "getTargetPath", {
659
754
  enumerable: true,
660
755
  get: function() {
661
756
  return getTargetPath;
662
757
  }
663
758
  });
759
+ Object.defineProperty(exports, "getTemplateExts", {
760
+ enumerable: true,
761
+ get: function() {
762
+ return getTemplateExts;
763
+ }
764
+ });
765
+ Object.defineProperty(exports, "getViewScriptExts", {
766
+ enumerable: true,
767
+ get: function() {
768
+ return getViewScriptExts;
769
+ }
770
+ });
771
+ Object.defineProperty(exports, "getViewScriptTags", {
772
+ enumerable: true,
773
+ get: function() {
774
+ return getViewScriptTags;
775
+ }
776
+ });
664
777
  Object.defineProperty(exports, "getWorkPath", {
665
778
  enumerable: true,
666
779
  get: function() {
@@ -317,24 +317,113 @@ var NpmResolver = class {
317
317
  var pathInfo = {};
318
318
  var configInfo = {};
319
319
  var npmResolver = null;
320
+ var DEFAULT_TEMPLATE_EXTS = [".wxml", ".ddml"];
321
+ var DEFAULT_STYLE_EXTS = [
322
+ ".wxss",
323
+ ".ddss",
324
+ ".less",
325
+ ".scss",
326
+ ".sass"
327
+ ];
328
+ var DEFAULT_VIEW_SCRIPT_EXTS = [".wxs"];
329
+ var DEFAULT_VIEW_SCRIPT_TAGS = ["wxs", "dds"];
330
+ var RESERVED_EXTS = /* @__PURE__ */ new Set([
331
+ ...DEFAULT_TEMPLATE_EXTS,
332
+ ...DEFAULT_STYLE_EXTS,
333
+ ...DEFAULT_VIEW_SCRIPT_EXTS,
334
+ ".js",
335
+ ".ts",
336
+ ".json"
337
+ ]);
338
+ var compilerOptions = normalizeFileTypes();
339
+ /**
340
+ * 将单项规范化为扩展名:去除首尾空白、转小写并补一个前导点。
341
+ * 仅接受字母、数字、连字符和下划线;空字符串、路径分隔符或其他元字符
342
+ * 均返回 null,由调用方丢弃。扩展名会用于生成尾部匹配正则和查找文件,
343
+ * 放行元字符可能导致误匹配。
344
+ */
345
+ function normalizeExt(raw) {
346
+ if (typeof raw !== "string") return null;
347
+ const v = raw.trim().toLowerCase().replace(/^\.+/, "");
348
+ if (!/^[a-z0-9_-]+$/.test(v)) return null;
349
+ return `.${v}`;
350
+ }
351
+ /**
352
+ * 将单项规范化为内联标签名:去除首尾空白、转小写并移除前导点。
353
+ * 标签名会用于拼接 Cheerio 选择器(如 transTagWxs),因此必须以字母开头,
354
+ * 且只能包含字母、数字、连字符和下划线。拒绝选择器元字符,避免 'qds,view'
355
+ * 误选并删除 <view>,破坏编译产物。
356
+ */
357
+ function normalizeTag(raw) {
358
+ if (typeof raw !== "string") return null;
359
+ const v = raw.trim().toLowerCase().replace(/^\.+/, "");
360
+ if (!/^[a-z][a-z0-9_-]*$/.test(v)) return null;
361
+ return v;
362
+ }
363
+ /**
364
+ * 合并并去重内置项和自定义项;内置项在前,顺序即同名文件的查找优先级。
365
+ * 传入 reserved 时,落在其中的自定义项被丢弃(防止占用其他角色/逻辑/配置的扩展名)。
366
+ */
367
+ function mergeUnique(builtins, custom, normalizer, reserved) {
368
+ const out = [...builtins];
369
+ const seen = new Set(builtins);
370
+ if (Array.isArray(custom)) for (const raw of custom) {
371
+ const n = normalizer(raw);
372
+ if (n && !seen.has(n) && !reserved?.has(n)) {
373
+ seen.add(n);
374
+ out.push(n);
375
+ }
376
+ }
377
+ return out;
378
+ }
379
+ /**
380
+ * 根据 options.fileTypes 生成本次构建使用的自定义扩展名和标签。
381
+ * viewScript 同时用于生成文件扩展名和内联标签。
382
+ */
383
+ function normalizeFileTypes(fileTypes = {}) {
384
+ const ft = fileTypes || {};
385
+ return {
386
+ templateExts: mergeUnique(DEFAULT_TEMPLATE_EXTS, ft.template, normalizeExt, RESERVED_EXTS),
387
+ styleExts: mergeUnique(DEFAULT_STYLE_EXTS, ft.style, normalizeExt, RESERVED_EXTS),
388
+ viewScriptExts: mergeUnique(DEFAULT_VIEW_SCRIPT_EXTS, ft.viewScript, normalizeExt, RESERVED_EXTS),
389
+ viewScriptTags: mergeUnique(DEFAULT_VIEW_SCRIPT_TAGS, ft.viewScript, normalizeTag)
390
+ };
391
+ }
320
392
  /**
321
393
  * 持久化编译过程的上下文
394
+ * @param {string} workPath 编译工作目录
395
+ * @param {{ fileTypes?: { template?: string[], style?: string[], viewScript?: string[] } }} [options] 构建选项
322
396
  */
323
- function storeInfo(workPath) {
397
+ function storeInfo(workPath, options = {}) {
324
398
  storePathInfo(workPath);
325
399
  storeProjectConfig();
326
400
  storeAppConfig();
327
401
  storePageConfig();
402
+ compilerOptions = normalizeFileTypes(options.fileTypes);
328
403
  return {
329
404
  pathInfo,
330
- configInfo
405
+ configInfo,
406
+ compilerOptions
331
407
  };
332
408
  }
333
409
  function resetStoreInfo(opts) {
334
410
  pathInfo = opts.pathInfo;
335
411
  configInfo = opts.configInfo;
412
+ compilerOptions = opts.compilerOptions || normalizeFileTypes();
336
413
  if (pathInfo.workPath) npmResolver = new NpmResolver(pathInfo.workPath);
337
414
  }
415
+ function getTemplateExts() {
416
+ return compilerOptions.templateExts;
417
+ }
418
+ function getStyleExts() {
419
+ return compilerOptions.styleExts;
420
+ }
421
+ function getViewScriptExts() {
422
+ return compilerOptions.viewScriptExts;
423
+ }
424
+ function getViewScriptTags() {
425
+ return compilerOptions.viewScriptTags;
426
+ }
338
427
  function storePathInfo(workPath) {
339
428
  pathInfo.workPath = workPath;
340
429
  if (process.env.TARGET_PATH) pathInfo.targetPath = process.env.TARGET_PATH;
@@ -557,4 +646,4 @@ function getPages() {
557
646
  };
558
647
  }
559
648
  //#endregion
560
- export { tagWhiteList as _, getContentByPath as a, getPages as c, resetStoreInfo as d, resolveAppAlias as f, hasCompileInfo as g, getAbsolutePath as h, getComponent as i, getTargetPath as l, collectAssets as m, getAppId as n, getNpmResolver as o, storeInfo as p, getAppName as r, getPageConfigInfo as s, getAppConfigInfo as t, getWorkPath as u, transformRpx as v, art_default as y };
649
+ export { art_default as C, transformRpx as S, storeInfo as _, getContentByPath as a, hasCompileInfo as b, getPages as c, getTemplateExts as d, getViewScriptExts as f, resolveAppAlias as g, resetStoreInfo as h, getComponent as i, getStyleExts as l, getWorkPath as m, getAppId as n, getNpmResolver as o, getViewScriptTags as p, getAppName as r, getPageConfigInfo as s, getAppConfigInfo as t, getTargetPath as u, collectAssets as v, tagWhiteList as x, getAbsolutePath as y };
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_env = require("./env-Dmnqp9bD.cjs");
1
+ const require_env = require("./env-BWsUjuZE.cjs");
2
2
  let node_path = require("node:path");
3
3
  node_path = require_env.__toESM(node_path, 1);
4
4
  let node_url = require("node:url");
@@ -191,13 +191,10 @@ var NpmBuilder = class {
191
191
  const miniprogramExts = [
192
192
  ".js",
193
193
  ".json",
194
- ".wxml",
195
- ".wxss",
196
- ".wxs",
197
194
  ".ts",
198
- ".less",
199
- ".scss",
200
- ".styl"
195
+ ...require_env.getTemplateExts(),
196
+ ...require_env.getStyleExts(),
197
+ ...require_env.getViewScriptExts()
201
198
  ];
202
199
  const ext = node_path.default.extname(filename).toLowerCase();
203
200
  return miniprogramExts.includes(ext) || filename === "package.json" || filename === "README.md" || filename.startsWith(".");
@@ -316,10 +313,15 @@ var isPrinted = false;
316
313
  * 构建命令入口
317
314
  * @param {string} targetPath 编译产物目标路径
318
315
  * @param {string} workPath 编译工作目录
319
- * @param {boolean} useAppIdDir 产物根目录是否包含appId
316
+ * @param {boolean} useAppIdDir 产物根目录是否包含 appId
317
+ * @param {object} [options] 构建选项
318
+ * @param {boolean} [options.sourcemap] 是否生成 sourcemap
319
+ * @param {{ template?: string[], style?: string[], viewScript?: string[] }} [options.fileTypes]
320
+ * 自定义文件类型,在内置 wx/dd 类型基础上追加;template 为模板扩展名,style 为样式扩展名,
321
+ * viewScript 为视图脚本扩展名和内联标签名
320
322
  */
321
323
  async function build(targetPath, workPath, useAppIdDir = true, options = {}) {
322
- const { sourcemap = false } = options;
324
+ const { sourcemap = false, fileTypes } = options;
323
325
  if (!isPrinted) {
324
326
  require_env.art_default();
325
327
  isPrinted = true;
@@ -331,7 +333,7 @@ async function build(targetPath, workPath, useAppIdDir = true, options = {}) {
331
333
  {
332
334
  title: "收集配置信息",
333
335
  task: (ctx) => {
334
- ctx.storeInfo = require_env.storeInfo(workPath);
336
+ ctx.storeInfo = require_env.storeInfo(workPath, { fileTypes });
335
337
  }
336
338
  },
337
339
  {
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { c as getPages, l as getTargetPath, m as collectAssets, n as getAppId, p as storeInfo, r as getAppName, s as getPageConfigInfo, t as getAppConfigInfo, u as getWorkPath, y as art_default } from "./env-p9Az8lv5.js";
1
+ import { C as art_default, _ as storeInfo, c as getPages, d as getTemplateExts, f as getViewScriptExts, l as getStyleExts, m as getWorkPath, n as getAppId, r as getAppName, s as getPageConfigInfo, t as getAppConfigInfo, u as getTargetPath, v as collectAssets } from "./env-iShlMOS1.js";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { Worker } from "node:worker_threads";
@@ -187,13 +187,10 @@ var NpmBuilder = class {
187
187
  const miniprogramExts = [
188
188
  ".js",
189
189
  ".json",
190
- ".wxml",
191
- ".wxss",
192
- ".wxs",
193
190
  ".ts",
194
- ".less",
195
- ".scss",
196
- ".styl"
191
+ ...getTemplateExts(),
192
+ ...getStyleExts(),
193
+ ...getViewScriptExts()
197
194
  ];
198
195
  const ext = path.extname(filename).toLowerCase();
199
196
  return miniprogramExts.includes(ext) || filename === "package.json" || filename === "README.md" || filename.startsWith(".");
@@ -312,10 +309,15 @@ var isPrinted = false;
312
309
  * 构建命令入口
313
310
  * @param {string} targetPath 编译产物目标路径
314
311
  * @param {string} workPath 编译工作目录
315
- * @param {boolean} useAppIdDir 产物根目录是否包含appId
312
+ * @param {boolean} useAppIdDir 产物根目录是否包含 appId
313
+ * @param {object} [options] 构建选项
314
+ * @param {boolean} [options.sourcemap] 是否生成 sourcemap
315
+ * @param {{ template?: string[], style?: string[], viewScript?: string[] }} [options.fileTypes]
316
+ * 自定义文件类型,在内置 wx/dd 类型基础上追加;template 为模板扩展名,style 为样式扩展名,
317
+ * viewScript 为视图脚本扩展名和内联标签名
316
318
  */
317
319
  async function build(targetPath, workPath, useAppIdDir = true, options = {}) {
318
- const { sourcemap = false } = options;
320
+ const { sourcemap = false, fileTypes } = options;
319
321
  if (!isPrinted) {
320
322
  art_default();
321
323
  isPrinted = true;
@@ -327,7 +329,7 @@ async function build(targetPath, workPath, useAppIdDir = true, options = {}) {
327
329
  {
328
330
  title: "收集配置信息",
329
331
  task: (ctx) => {
330
- ctx.storeInfo = storeInfo(workPath);
332
+ ctx.storeInfo = storeInfo(workPath, { fileTypes });
331
333
  }
332
334
  },
333
335
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dimina/compiler",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "星河编译工具",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -51,22 +51,22 @@
51
51
  "星河"
52
52
  ],
53
53
  "dependencies": {
54
- "@vue/compiler-sfc": "^3.5.34",
55
- "autoprefixer": "^10.5.0",
54
+ "@vue/compiler-sfc": "^3.5.39",
55
+ "autoprefixer": "^10.5.2",
56
56
  "cheerio": "^1.2.0",
57
57
  "chokidar": "^4.0.3",
58
58
  "commander": "^14.0.3",
59
- "cssnano": "^8.0.1",
60
- "esbuild": "^0.28.0",
59
+ "cssnano": "^8.0.2",
60
+ "esbuild": "^0.28.1",
61
61
  "htmlparser2": "^12.0.0",
62
- "less": "^4.6.4",
62
+ "less": "^4.6.7",
63
63
  "listr2": "^9.0.5",
64
64
  "magic-string": "^0.30.21",
65
- "oxc-parser": "^0.129.0",
66
- "oxc-walker": "^0.7.0",
67
- "postcss": "^8.5.14",
68
- "postcss-selector-parser": "^7.1.1",
69
- "sass": "^1.99.0",
65
+ "oxc-parser": "^0.137.0",
66
+ "oxc-walker": "^1.0.0",
67
+ "postcss": "^8.5.15",
68
+ "postcss-selector-parser": "^7.1.4",
69
+ "sass": "^1.101.0",
70
70
  "source-map-js": "^1.2.1"
71
71
  },
72
72
  "publishConfig": {