@dimina/compiler 1.0.12 → 1.0.14-beta.0

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.
@@ -1,245 +1,237 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const fs = require("node:fs");
4
- const path = require("node:path");
5
- const node_worker_threads = require("node:worker_threads");
6
- const compilerSfc = require("@vue/compiler-sfc");
7
- const autoprefixer = require("autoprefixer");
8
- const cssnano = require("cssnano");
9
- const less = require("less");
10
- const postcss = require("postcss");
11
- const selectorParser = require("postcss-selector-parser");
12
- const sass = require("sass");
13
- const env = require("../env-Cmen1qwy.cjs");
14
- function _interopNamespaceDefault(e) {
15
- const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
16
- if (e) {
17
- for (const k in e) {
18
- if (k !== "default") {
19
- const d = Object.getOwnPropertyDescriptor(e, k);
20
- Object.defineProperty(n, k, d.get ? d : {
21
- enumerable: true,
22
- get: () => e[k]
23
- });
24
- }
25
- }
26
- }
27
- n.default = e;
28
- return Object.freeze(n);
29
- }
30
- const sass__namespace = /* @__PURE__ */ _interopNamespaceDefault(sass);
31
- const fileType = [".wxss", ".ddss", ".less", ".scss", ".sass"];
32
- const compileRes = /* @__PURE__ */ new Map();
33
- if (!node_worker_threads.isMainThread) {
34
- node_worker_threads.parentPort.on("message", async ({ pages, storeInfo }) => {
35
- try {
36
- env.resetStoreInfo(storeInfo);
37
- const progress = {
38
- _completedTasks: 0,
39
- get completedTasks() {
40
- return this._completedTasks;
41
- },
42
- set completedTasks(value) {
43
- this._completedTasks = value;
44
- node_worker_threads.parentPort.postMessage({ completedTasks: this._completedTasks });
45
- }
46
- };
47
- await compileSS(pages.mainPages, null, progress);
48
- for (const [root, subPages] of Object.entries(pages.subPages)) {
49
- await compileSS(subPages.info, root, progress);
50
- }
51
- compileRes.clear();
52
- node_worker_threads.parentPort.postMessage({ success: true });
53
- } catch (error) {
54
- compileRes.clear();
55
- node_worker_threads.parentPort.postMessage({
56
- success: false,
57
- error: {
58
- message: error.message,
59
- stack: error.stack,
60
- name: error.name
61
- }
62
- });
63
- }
64
- });
65
- }
2
+ const require_env = require("../env-M-7lpbHL.cjs");
3
+ let node_path = require("node:path");
4
+ node_path = require_env.__toESM(node_path, 1);
5
+ let node_worker_threads = require("node:worker_threads");
6
+ let node_fs = require("node:fs");
7
+ node_fs = require_env.__toESM(node_fs, 1);
8
+ let _vue_compiler_sfc = require("@vue/compiler-sfc");
9
+ let autoprefixer = require("autoprefixer");
10
+ autoprefixer = require_env.__toESM(autoprefixer, 1);
11
+ let cssnano = require("cssnano");
12
+ cssnano = require_env.__toESM(cssnano, 1);
13
+ let less = require("less");
14
+ less = require_env.__toESM(less, 1);
15
+ let postcss = require("postcss");
16
+ postcss = require_env.__toESM(postcss, 1);
17
+ let postcss_selector_parser = require("postcss-selector-parser");
18
+ postcss_selector_parser = require_env.__toESM(postcss_selector_parser, 1);
19
+ let sass = require("sass");
20
+ sass = require_env.__toESM(sass, 1);
21
+ //#region src/core/style-compiler.js
22
+ var fileType = [
23
+ ".wxss",
24
+ ".ddss",
25
+ ".less",
26
+ ".scss",
27
+ ".sass"
28
+ ];
29
+ var compileRes = /* @__PURE__ */ new Map();
30
+ if (!node_worker_threads.isMainThread) node_worker_threads.parentPort.on("message", async ({ pages, storeInfo }) => {
31
+ try {
32
+ require_env.resetStoreInfo(storeInfo);
33
+ const progress = {
34
+ _completedTasks: 0,
35
+ get completedTasks() {
36
+ return this._completedTasks;
37
+ },
38
+ set completedTasks(value) {
39
+ this._completedTasks = value;
40
+ node_worker_threads.parentPort.postMessage({ completedTasks: this._completedTasks });
41
+ }
42
+ };
43
+ await compileSS(pages.mainPages, null, progress);
44
+ for (const [root, subPages] of Object.entries(pages.subPages)) await compileSS(subPages.info, root, progress);
45
+ compileRes.clear();
46
+ node_worker_threads.parentPort.postMessage({ success: true });
47
+ } catch (error) {
48
+ compileRes.clear();
49
+ node_worker_threads.parentPort.postMessage({
50
+ success: false,
51
+ error: {
52
+ message: error.message,
53
+ stack: error.stack,
54
+ name: error.name
55
+ }
56
+ });
57
+ }
58
+ });
59
+ /**
60
+ * 编译样式文件
61
+ */
66
62
  async function compileSS(pages, root, progress) {
67
- for (const page of pages) {
68
- const code = await buildCompileCss(page, []) || "";
69
- const filename = `${page.path.replace(/\//g, "_")}`;
70
- if (root) {
71
- const subDir = `${env.getTargetPath()}/${root}`;
72
- if (!fs.existsSync(subDir)) {
73
- fs.mkdirSync(subDir, { recursive: true });
74
- }
75
- fs.writeFileSync(`${subDir}/${filename}.css`, code);
76
- } else {
77
- const mainDir = `${env.getTargetPath()}/main`;
78
- if (!fs.existsSync(mainDir)) {
79
- fs.mkdirSync(mainDir, { recursive: true });
80
- }
81
- fs.writeFileSync(`${mainDir}/${filename}.css`, code);
82
- }
83
- progress.completedTasks++;
84
- }
63
+ for (const page of pages) {
64
+ const code = await buildCompileCss(page, [], /* @__PURE__ */ new Set()) || "";
65
+ const filename = `${page.path.replace(/\//g, "_")}`;
66
+ if (root) {
67
+ const subDir = `${require_env.getTargetPath()}/${root}`;
68
+ if (!node_fs.default.existsSync(subDir)) node_fs.default.mkdirSync(subDir, { recursive: true });
69
+ node_fs.default.writeFileSync(`${subDir}/${filename}.css`, code);
70
+ } else {
71
+ const mainDir = `${require_env.getTargetPath()}/main`;
72
+ if (!node_fs.default.existsSync(mainDir)) node_fs.default.mkdirSync(mainDir, { recursive: true });
73
+ node_fs.default.writeFileSync(`${mainDir}/${filename}.css`, code);
74
+ }
75
+ progress.completedTasks++;
76
+ }
77
+ }
78
+ async function buildCompileCss(module, depthChain = [], compiledPaths = /* @__PURE__ */ new Set()) {
79
+ const currentPath = module.path || module.absolutePath;
80
+ if (depthChain.includes(currentPath)) {
81
+ console.warn("[style]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
82
+ return;
83
+ }
84
+ if (depthChain.length > 20) {
85
+ console.warn("[style]", `检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
86
+ return;
87
+ }
88
+ if (compiledPaths.has(currentPath)) return "";
89
+ compiledPaths.add(currentPath);
90
+ depthChain = [...depthChain, currentPath];
91
+ let result = await enhanceCSS(module) || "";
92
+ if (module.usingComponents) for (const componentInfo of Object.values(module.usingComponents)) {
93
+ const componentModule = require_env.getComponent(componentInfo);
94
+ if (!componentModule) continue;
95
+ result += await buildCompileCss(componentModule, depthChain, compiledPaths);
96
+ }
97
+ return result;
85
98
  }
86
- async function buildCompileCss(module2, depthChain = []) {
87
- const currentPath = module2.path;
88
- if (depthChain.includes(currentPath)) {
89
- console.warn("[style]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
90
- return;
91
- }
92
- if (depthChain.length > 20) {
93
- console.warn("[style]", `检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
94
- return;
95
- }
96
- depthChain = [...depthChain, currentPath];
97
- let result = await enhanceCSS(module2) || "";
98
- if (module2.usingComponents) {
99
- for (const componentInfo of Object.values(module2.usingComponents)) {
100
- const componentModule = env.getComponent(componentInfo);
101
- if (!componentModule) {
102
- continue;
103
- }
104
- result += await buildCompileCss(componentModule, depthChain);
105
- }
106
- }
107
- return result;
99
+ async function enhanceCSS(module) {
100
+ const absolutePath = module.absolutePath ? module.absolutePath : getAbsolutePath(module.path);
101
+ if (!absolutePath) return;
102
+ const inputCSS = require_env.getContentByPath(absolutePath);
103
+ if (!inputCSS) return;
104
+ if (compileRes.has(absolutePath)) return compileRes.get(absolutePath);
105
+ let processedCSS = normalizeRootStyleImports(inputCSS);
106
+ const ext = node_path.default.extname(absolutePath).toLowerCase();
107
+ try {
108
+ if (ext === ".less") processedCSS = (await less.default.render(processedCSS, {
109
+ filename: absolutePath,
110
+ paths: [node_path.default.dirname(absolutePath), require_env.getWorkPath()]
111
+ })).css;
112
+ else if (ext === ".scss" || ext === ".sass") processedCSS = sass.compileString(processedCSS, {
113
+ loadPaths: [node_path.default.dirname(absolutePath), require_env.getWorkPath()],
114
+ syntax: ext === ".sass" ? "indented" : "scss"
115
+ }).css;
116
+ } catch (error) {
117
+ console.error(`[style] 预处理器编译失败 ${absolutePath}:`, error.message);
118
+ processedCSS = inputCSS;
119
+ }
120
+ const fixedCSS = ensureImportSemicolons(processedCSS);
121
+ let ast;
122
+ try {
123
+ ast = postcss.default.parse(fixedCSS);
124
+ } catch (error) {
125
+ console.error(`[style] PostCSS 解析失败 ${absolutePath}:`, error.message);
126
+ return "";
127
+ }
128
+ const promises = [];
129
+ ast.walk(async (node) => {
130
+ if (node.type === "atrule" && node.name === "import") {
131
+ const importFullPath = resolveStyleImportPath(absolutePath, node.params.replace(/^['"]|['"]$/g, ""));
132
+ node.remove();
133
+ promises.push(buildCompileCss({
134
+ absolutePath: importFullPath,
135
+ id: module.id
136
+ }, [], /* @__PURE__ */ new Set()));
137
+ } else if (node.type === "rule") {
138
+ if (node.selector.includes("::v-deep")) node.selector = node.selector.replace(/::v-deep\s+(\S[^{]*)/g, ":deep($1)");
139
+ if (node.selector.includes(":host")) node.selector = processHostSelector(node.selector, module.id);
140
+ node.selector = (0, postcss_selector_parser.default)((selectors) => {
141
+ selectors.walkTags((tag) => {
142
+ if (require_env.tagWhiteList.includes(tag.value)) tag.value = `.dd-${tag.value}`;
143
+ });
144
+ }).processSync(node.selector);
145
+ } else if (node.type === "comment") node.remove();
146
+ });
147
+ ast.walkDecls((decl) => {
148
+ decl.value = normalizeCssUrlValue(decl.value, absolutePath);
149
+ decl.value = require_env.transformRpx(decl.value);
150
+ });
151
+ const cssCode = ast.toResult().css;
152
+ const moduleId = module.id;
153
+ const scopedCode = (0, _vue_compiler_sfc.compileStyle)({
154
+ source: cssCode,
155
+ id: moduleId,
156
+ scoped: !!moduleId
157
+ }).code;
158
+ const cleanedCode = await removeBaseComponentScope(scopedCode, moduleId);
159
+ const res = await (0, postcss.default)([(0, autoprefixer.default)({ overrideBrowserslist: ["cover 99.5%"] }), (0, cssnano.default)()]).process(cleanedCode, { from: void 0 });
160
+ const result = (await Promise.all(promises)).filter(Boolean).join("") + res.css;
161
+ compileRes.set(module.path, result);
162
+ return result;
108
163
  }
109
- async function enhanceCSS(module2) {
110
- const absolutePath = module2.absolutePath ? module2.absolutePath : getAbsolutePath(module2.path);
111
- if (!absolutePath) {
112
- return;
113
- }
114
- const inputCSS = env.getContentByPath(absolutePath);
115
- if (!inputCSS) {
116
- return;
117
- }
118
- if (compileRes.has(absolutePath)) {
119
- return compileRes.get(absolutePath);
120
- }
121
- let processedCSS = inputCSS;
122
- const ext = path.extname(absolutePath).toLowerCase();
123
- try {
124
- if (ext === ".less") {
125
- const result2 = await less.render(inputCSS, {
126
- filename: absolutePath,
127
- paths: [path.dirname(absolutePath)]
128
- });
129
- processedCSS = result2.css;
130
- } else if (ext === ".scss" || ext === ".sass") {
131
- const result2 = sass__namespace.compileString(inputCSS, {
132
- loadPaths: [path.dirname(absolutePath)],
133
- syntax: ext === ".sass" ? "indented" : "scss"
134
- });
135
- processedCSS = result2.css;
136
- }
137
- } catch (error) {
138
- console.error(`[style] 预处理器编译失败 ${absolutePath}:`, error.message);
139
- processedCSS = inputCSS;
140
- }
141
- const fixedCSS = ensureImportSemicolons(processedCSS);
142
- let ast;
143
- try {
144
- ast = postcss.parse(fixedCSS);
145
- } catch (error) {
146
- console.error(`[style] PostCSS 解析失败 ${absolutePath}:`, error.message);
147
- return "";
148
- }
149
- const promises = [];
150
- ast.walk(async (node) => {
151
- if (node.type === "atrule" && node.name === "import") {
152
- const str = node.params.replace(/^['"]|['"]$/g, "");
153
- const importFullPath = path.resolve(absolutePath, `../${str}`);
154
- node.remove();
155
- promises.push(buildCompileCss({ absolutePath: importFullPath, id: module2.id }));
156
- } else if (node.type === "rule") {
157
- if (node.selector.includes("::v-deep")) {
158
- node.selector = node.selector.replace(/::v-deep\s+(\S[^{]*)/g, ":deep($1)");
159
- }
160
- if (node.selector.includes(":host")) {
161
- node.selector = processHostSelector(node.selector, module2.id);
162
- }
163
- node.selector = selectorParser((selectors) => {
164
- selectors.walkTags((tag) => {
165
- if (env.tagWhiteList.includes(tag.value)) {
166
- tag.value = `.dd-${tag.value}`;
167
- }
168
- });
169
- }).processSync(node.selector);
170
- node.walkDecls((decl) => {
171
- const match = decl.value.match(/url\("([^"]*)"\)/);
172
- if (match) {
173
- const imgSrc = match[1].trim();
174
- if (imgSrc.startsWith("data:image")) {
175
- return;
176
- }
177
- const realSrc = env.collectAssets(env.getWorkPath(), absolutePath, imgSrc, env.getTargetPath(), env.getAppId());
178
- decl.value = `url(${realSrc})`;
179
- } else {
180
- decl.value = env.transformRpx(decl.value);
181
- }
182
- });
183
- } else if (node.type === "comment") {
184
- node.remove();
185
- }
186
- });
187
- const cssCode = ast.toResult().css;
188
- const moduleId = module2.id;
189
- const scopedCode = compilerSfc.compileStyle({
190
- source: cssCode,
191
- id: moduleId,
192
- scoped: !!moduleId
193
- }).code;
194
- const cleanedCode = await removeBaseComponentScope(scopedCode, moduleId);
195
- const res = await postcss([
196
- autoprefixer({ overrideBrowserslist: ["cover 99.5%"] }),
197
- cssnano()
198
- ]).process(cleanedCode, { from: void 0 });
199
- const importCss = (await Promise.all(promises)).filter(Boolean).join("");
200
- const result = importCss + res.css;
201
- compileRes.set(module2.path, result);
202
- return result;
164
+ function normalizeCssUrlValue(value, absolutePath) {
165
+ return value.replace(/url\(([^)]+)\)/g, (fullMatch, rawUrl) => {
166
+ const cleanedUrl = rawUrl.trim().replace(/^['"]|['"]$/g, "");
167
+ if (!cleanedUrl || cleanedUrl.startsWith("data:image")) return fullMatch;
168
+ if (cleanedUrl.startsWith("//")) return `url(https:${cleanedUrl})`;
169
+ if (/^(https?:|blob:|data:)/.test(cleanedUrl)) return fullMatch;
170
+ return `url(${require_env.collectAssets(require_env.getWorkPath(), absolutePath, cleanedUrl, require_env.getTargetPath(), require_env.getAppId())})`;
171
+ });
203
172
  }
204
173
  function getAbsolutePath(modulePath) {
205
- const workPath = env.getWorkPath();
206
- const src = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
207
- for (const ssType of fileType) {
208
- const ssFullPath = `${workPath}${src}${ssType}`;
209
- if (fs.existsSync(ssFullPath)) {
210
- return ssFullPath;
211
- }
212
- }
174
+ const workPath = require_env.getWorkPath();
175
+ const src = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
176
+ for (const ssType of fileType) {
177
+ const ssFullPath = `${workPath}${src}${ssType}`;
178
+ if (node_fs.default.existsSync(ssFullPath)) return ssFullPath;
179
+ const indexSsFullPath = `${workPath}${src}/index${ssType}`;
180
+ if (node_fs.default.existsSync(indexSsFullPath)) return indexSsFullPath;
181
+ }
182
+ }
183
+ function resolveStyleImportPath(absolutePath, importPath, workPath = require_env.getWorkPath()) {
184
+ if (importPath.startsWith("/")) return node_path.default.join(workPath, importPath);
185
+ return node_path.default.resolve(node_path.default.dirname(absolutePath), importPath);
186
+ }
187
+ function normalizeRootStyleImports(source, workPath = require_env.getWorkPath()) {
188
+ return source.replace(/(@import\s+(?:\(.*?\)\s*)?(?:url\()?['"])(\/[^'")]+)(['"]\)?)/g, (_, prefix, importPath, suffix) => {
189
+ return `${prefix}${node_path.default.join(workPath, importPath)}${suffix}`;
190
+ });
213
191
  }
192
+ /**
193
+ * 移除基础组件选择器的 scoped 属性
194
+ * @param {string} css - 包含 scoped 属性的 CSS
195
+ * @param {string} moduleId - 模块 ID
196
+ * @returns {Promise<string>} - 清理后的 CSS
197
+ */
214
198
  async function removeBaseComponentScope(css, moduleId) {
215
- if (!moduleId) return css;
216
- const ast = postcss.parse(css);
217
- const scopeAttrName = `data-v-${moduleId}`;
218
- ast.walkRules((rule) => {
219
- const hasBaseComponent = env.tagWhiteList.some(
220
- (tag) => rule.selector.includes(`.dd-${tag}`)
221
- );
222
- if (hasBaseComponent && rule.selector.includes(scopeAttrName)) {
223
- rule.selector = selectorParser((selectors) => {
224
- selectors.walkAttributes((attr) => {
225
- if (attr.attribute === scopeAttrName) {
226
- attr.remove();
227
- }
228
- });
229
- }).processSync(rule.selector);
230
- }
231
- });
232
- return ast.toResult().css;
199
+ if (!moduleId) return css;
200
+ const ast = postcss.default.parse(css);
201
+ const scopeAttrName = `data-v-${moduleId}`;
202
+ ast.walkRules((rule) => {
203
+ if (require_env.tagWhiteList.some((tag) => rule.selector.includes(`.dd-${tag}`)) && rule.selector.includes(scopeAttrName)) rule.selector = (0, postcss_selector_parser.default)((selectors) => {
204
+ selectors.walkAttributes((attr) => {
205
+ if (attr.attribute === scopeAttrName) attr.remove();
206
+ });
207
+ }).processSync(rule.selector);
208
+ });
209
+ return ast.toResult().css;
233
210
  }
211
+ /**
212
+ * Ensures that all @import statements in CSS end with semicolons
213
+ * @param {string} css - The CSS content to process
214
+ * @returns {string} - The processed CSS with semicolons added to @import statements as needed
215
+ */
234
216
  function ensureImportSemicolons(css) {
235
- return css.replace(/@import[^;\n]*$/gm, (match) => {
236
- return match.endsWith(";") ? match : `${match};`;
237
- });
217
+ return css.replace(/@import[^;\n]*$/gm, (match) => {
218
+ return match.endsWith(";") ? match : `${match};`;
219
+ });
238
220
  }
221
+ /**
222
+ * 处理 :host 选择器,将其转换为适合组件根节点的选择器
223
+ * @param {string} selector - 包含 :host 的选择器
224
+ * @param {string} moduleId - 组件的模块ID
225
+ * @returns {string} - 转换后的选择器
226
+ */
239
227
  function processHostSelector(selector, moduleId) {
240
- return selector.replace(/^:host$/, `[data-v-${moduleId}]`).replace(/:host\(([^)]+)\)/g, `[data-v-${moduleId}]$1`).replace(/:host\s+/g, `[data-v-${moduleId}] `).replace(/:host(?=\.|#|:)/g, `[data-v-${moduleId}]`);
228
+ return selector.replace(/^:host$/, `[data-v-${moduleId}]`).replace(/:host\(([^)]+)\)/g, `[data-v-${moduleId}]$1`).replace(/:host\s+/g, `[data-v-${moduleId}] `).replace(/:host(?=\.|#|:)/g, `[data-v-${moduleId}]`);
241
229
  }
230
+ //#endregion
242
231
  exports.compileSS = compileSS;
243
232
  exports.ensureImportSemicolons = ensureImportSemicolons;
233
+ exports.normalizeCssUrlValue = normalizeCssUrlValue;
234
+ exports.normalizeRootStyleImports = normalizeRootStyleImports;
244
235
  exports.processHostSelector = processHostSelector;
245
236
  exports.removeBaseComponentScope = removeBaseComponentScope;
237
+ exports.resolveStyleImportPath = resolveStyleImportPath;