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