@netoyed/ux4g-design-system-v3-cli 1.0.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/ux4g.js +622 -0
- package/package.json +30 -0
package/dist/ux4g.js
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// bin/ux4g.js
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
|
|
12
|
+
// commands/build.js
|
|
13
|
+
import fg from "fast-glob";
|
|
14
|
+
import path2 from "path";
|
|
15
|
+
import fs5 from "fs";
|
|
16
|
+
|
|
17
|
+
// config/loadConfig.js
|
|
18
|
+
import fs from "fs";
|
|
19
|
+
import path from "path";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
|
|
22
|
+
// ../core/config/defaultConfig.js
|
|
23
|
+
var defaultConfig = {
|
|
24
|
+
/**
|
|
25
|
+
* --------------------------------------------------
|
|
26
|
+
* CORE
|
|
27
|
+
* --------------------------------------------------
|
|
28
|
+
*/
|
|
29
|
+
prefix: "ux4g-",
|
|
30
|
+
/**
|
|
31
|
+
* dev | build | cdn
|
|
32
|
+
* NOTE: CLI command will override this
|
|
33
|
+
*/
|
|
34
|
+
mode: "build",
|
|
35
|
+
/**
|
|
36
|
+
* --------------------------------------------------
|
|
37
|
+
* CONTENT (used for purge / JIT)
|
|
38
|
+
* --------------------------------------------------
|
|
39
|
+
*/
|
|
40
|
+
content: [
|
|
41
|
+
"./index.html",
|
|
42
|
+
"./src/**/*.{js,ts,jsx,tsx,vue,html}",
|
|
43
|
+
"./pages/**/*.{js,ts,jsx,tsx}",
|
|
44
|
+
"./components/**/*.{js,ts,jsx,tsx}",
|
|
45
|
+
"./**/*.php"
|
|
46
|
+
],
|
|
47
|
+
/**
|
|
48
|
+
* --------------------------------------------------
|
|
49
|
+
* THEME (tokens)
|
|
50
|
+
* --------------------------------------------------
|
|
51
|
+
*/
|
|
52
|
+
theme: {
|
|
53
|
+
colors: {
|
|
54
|
+
primary: {
|
|
55
|
+
50: "#EFF6FF",
|
|
56
|
+
500: "#3B82F6",
|
|
57
|
+
700: "#1D4ED8"
|
|
58
|
+
},
|
|
59
|
+
secondary: {
|
|
60
|
+
500: "#9333EA"
|
|
61
|
+
},
|
|
62
|
+
danger: {
|
|
63
|
+
500: "#EF4444"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
spacing: {
|
|
67
|
+
0: "0px",
|
|
68
|
+
1: "4px",
|
|
69
|
+
2: "8px",
|
|
70
|
+
4: "16px",
|
|
71
|
+
6: "24px",
|
|
72
|
+
8: "32px"
|
|
73
|
+
},
|
|
74
|
+
fontSize: {
|
|
75
|
+
xs: "12px",
|
|
76
|
+
sm: "14px",
|
|
77
|
+
md: "16px",
|
|
78
|
+
lg: "18px",
|
|
79
|
+
xl: "20px"
|
|
80
|
+
},
|
|
81
|
+
fontWeight: {
|
|
82
|
+
regular: 400,
|
|
83
|
+
medium: 500,
|
|
84
|
+
bold: 700
|
|
85
|
+
},
|
|
86
|
+
radius: {
|
|
87
|
+
sm: "4px",
|
|
88
|
+
md: "8px",
|
|
89
|
+
lg: "12px",
|
|
90
|
+
xl: "16px"
|
|
91
|
+
},
|
|
92
|
+
shadow: {
|
|
93
|
+
sm: "0 1px 2px rgba(0,0,0,0.05)",
|
|
94
|
+
md: "0 4px 6px rgba(0,0,0,0.1)"
|
|
95
|
+
},
|
|
96
|
+
zIndex: {
|
|
97
|
+
dropdown: 1e3,
|
|
98
|
+
modal: 1100,
|
|
99
|
+
toast: 1200
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* --------------------------------------------------
|
|
104
|
+
* RESPONSIVE
|
|
105
|
+
* --------------------------------------------------
|
|
106
|
+
*/
|
|
107
|
+
breakpoints: {
|
|
108
|
+
sm: "640px",
|
|
109
|
+
md: "768px",
|
|
110
|
+
lg: "1024px",
|
|
111
|
+
xl: "1280px"
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* --------------------------------------------------
|
|
115
|
+
* DARK MODE / THEMES
|
|
116
|
+
* --------------------------------------------------
|
|
117
|
+
*/
|
|
118
|
+
darkMode: {
|
|
119
|
+
enabled: true,
|
|
120
|
+
strategy: "data-attribute",
|
|
121
|
+
// class | data-attribute
|
|
122
|
+
attribute: "data-theme",
|
|
123
|
+
themes: {
|
|
124
|
+
light: "light",
|
|
125
|
+
dark: "dark"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
/**
|
|
129
|
+
* --------------------------------------------------
|
|
130
|
+
* SAFELIST (dynamic classes)
|
|
131
|
+
* --------------------------------------------------
|
|
132
|
+
*/
|
|
133
|
+
safelist: [],
|
|
134
|
+
/**
|
|
135
|
+
* --------------------------------------------------
|
|
136
|
+
* COMPONENTS
|
|
137
|
+
* --------------------------------------------------
|
|
138
|
+
*/
|
|
139
|
+
components: {
|
|
140
|
+
button: true,
|
|
141
|
+
card: true,
|
|
142
|
+
input: true,
|
|
143
|
+
modal: false
|
|
144
|
+
},
|
|
145
|
+
/**
|
|
146
|
+
* --------------------------------------------------
|
|
147
|
+
* PLUGINS
|
|
148
|
+
* --------------------------------------------------
|
|
149
|
+
*/
|
|
150
|
+
plugins: [],
|
|
151
|
+
/**
|
|
152
|
+
* --------------------------------------------------
|
|
153
|
+
* OUTPUT
|
|
154
|
+
* --------------------------------------------------
|
|
155
|
+
*/
|
|
156
|
+
output: {
|
|
157
|
+
dir: "dist",
|
|
158
|
+
file: "ux4g.css",
|
|
159
|
+
minify: true,
|
|
160
|
+
sourceMap: false
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// config/mergeConfig.js
|
|
165
|
+
function deepMerge(target, source) {
|
|
166
|
+
if (!isObject(target) || !isObject(source)) {
|
|
167
|
+
return source === void 0 ? target : source;
|
|
168
|
+
}
|
|
169
|
+
const result = { ...target };
|
|
170
|
+
for (const key of Object.keys(source)) {
|
|
171
|
+
const sourceValue = source[key];
|
|
172
|
+
const targetValue = target[key];
|
|
173
|
+
if (sourceValue === void 0) continue;
|
|
174
|
+
if (Array.isArray(sourceValue)) {
|
|
175
|
+
result[key] = sourceValue;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
179
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
result[key] = sourceValue;
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
function isObject(value) {
|
|
187
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// config/loadConfig.js
|
|
191
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
192
|
+
var __dirname = path.dirname(__filename);
|
|
193
|
+
function loadUX4GConfig() {
|
|
194
|
+
const projectRoot = process.cwd();
|
|
195
|
+
const userConfigPath = path.join(projectRoot, "ux4g.config.js");
|
|
196
|
+
let userConfig = {};
|
|
197
|
+
if (fs.existsSync(userConfigPath)) {
|
|
198
|
+
try {
|
|
199
|
+
userConfig = __require(userConfigPath);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
console.error("\u274C Failed to load ux4g.config.js");
|
|
202
|
+
console.error(err);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const finalConfig = deepMerge(
|
|
207
|
+
structuredClone(defaultConfig),
|
|
208
|
+
userConfig
|
|
209
|
+
);
|
|
210
|
+
finalConfig.prefix = "ux4g-";
|
|
211
|
+
finalConfig.content = normalizeContentPaths(
|
|
212
|
+
finalConfig.content,
|
|
213
|
+
projectRoot
|
|
214
|
+
);
|
|
215
|
+
finalConfig.output = normalizeOutput(finalConfig.output, projectRoot);
|
|
216
|
+
applyModeDefaults(finalConfig);
|
|
217
|
+
return finalConfig;
|
|
218
|
+
}
|
|
219
|
+
function normalizeContentPaths(content = [], root) {
|
|
220
|
+
return content.map(
|
|
221
|
+
(p) => path.isAbsolute(p) ? p : path.join(root, p)
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
function normalizeOutput(output = {}, root) {
|
|
225
|
+
const dir = output.dir || "dist";
|
|
226
|
+
const file = output.file || "ux4g.css";
|
|
227
|
+
return {
|
|
228
|
+
...output,
|
|
229
|
+
dir: path.join(root, dir),
|
|
230
|
+
file,
|
|
231
|
+
filePath: path.join(root, dir, file)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function applyModeDefaults(config) {
|
|
235
|
+
if (config.mode === "dev") {
|
|
236
|
+
config.minify = false;
|
|
237
|
+
config.purge = false;
|
|
238
|
+
}
|
|
239
|
+
if (config.mode === "build") {
|
|
240
|
+
config.minify = true;
|
|
241
|
+
config.purge = true;
|
|
242
|
+
}
|
|
243
|
+
if (config.mode === "cdn") {
|
|
244
|
+
config.minify = true;
|
|
245
|
+
config.purge = false;
|
|
246
|
+
config.content = [];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// jit/scanner.js
|
|
251
|
+
import fs2 from "fs";
|
|
252
|
+
|
|
253
|
+
// jit/state.js
|
|
254
|
+
import crypto from "crypto";
|
|
255
|
+
|
|
256
|
+
// ../core/jit/state.js
|
|
257
|
+
function createJITState() {
|
|
258
|
+
return {
|
|
259
|
+
usedClasses: /* @__PURE__ */ new Set(),
|
|
260
|
+
generatedCSS: /* @__PURE__ */ new Map()
|
|
261
|
+
// class → css
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// jit/state.js
|
|
266
|
+
function createJITState2(config) {
|
|
267
|
+
const state = createJITState();
|
|
268
|
+
state.fileHashes = /* @__PURE__ */ new Map();
|
|
269
|
+
state.configHash = hash(JSON.stringify(config));
|
|
270
|
+
return state;
|
|
271
|
+
}
|
|
272
|
+
function hash(input) {
|
|
273
|
+
return crypto.createHash("md5").update(input).digest("hex");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// jit/scanner.js
|
|
277
|
+
function scanFiles(files, state, config) {
|
|
278
|
+
const found = /* @__PURE__ */ new Set();
|
|
279
|
+
const prefix = config.prefix.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
280
|
+
const CLASS_REGEX = new RegExp(`(sm:|md:|lg:|xl:)?${prefix}[a-z0-9\\-]+`, "g");
|
|
281
|
+
for (const file of files) {
|
|
282
|
+
const content = fs2.readFileSync(file, "utf8");
|
|
283
|
+
const contentHash = hash(content);
|
|
284
|
+
if (state.fileHashes.get(file) === contentHash) continue;
|
|
285
|
+
state.fileHashes.set(file, contentHash);
|
|
286
|
+
const matches = content.match(CLASS_REGEX);
|
|
287
|
+
if (matches) matches.forEach((c) => found.add(c));
|
|
288
|
+
}
|
|
289
|
+
return found;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ../core/jit/registry.js
|
|
293
|
+
var registry = {
|
|
294
|
+
// --- Spacing ---
|
|
295
|
+
"p": { type: "space", property: "padding" },
|
|
296
|
+
"pt": { type: "space", property: "padding-top" },
|
|
297
|
+
"pr": { type: "space", property: "padding-right" },
|
|
298
|
+
"pb": { type: "space", property: "padding-bottom" },
|
|
299
|
+
"pl": { type: "space", property: "padding-left" },
|
|
300
|
+
"px": { type: "space", property: ["padding-left", "padding-right"] },
|
|
301
|
+
"py": { type: "space", property: ["padding-top", "padding-bottom"] },
|
|
302
|
+
"m": { type: "space", property: "margin" },
|
|
303
|
+
"mt": { type: "space", property: "margin-top" },
|
|
304
|
+
"mr": { type: "space", property: "margin-right" },
|
|
305
|
+
"mb": { type: "space", property: "margin-bottom" },
|
|
306
|
+
"ml": { type: "space", property: "margin-left" },
|
|
307
|
+
"mx": { type: "space", property: ["margin-left", "margin-right"] },
|
|
308
|
+
"my": { type: "space", property: ["margin-top", "margin-bottom"] },
|
|
309
|
+
// --- Colors ---
|
|
310
|
+
"text": { type: "color", property: "color" },
|
|
311
|
+
"bg": { type: "color", property: "background-color" },
|
|
312
|
+
"border": { type: "color", property: "border-color" },
|
|
313
|
+
// --- Typography ---
|
|
314
|
+
"font": { type: "fontDetail", property: "font-weight" },
|
|
315
|
+
"text-size": { type: "text", property: "font-size" },
|
|
316
|
+
"leading": { type: "value", property: "line-height" },
|
|
317
|
+
"tracking": { type: "value", property: "letter-spacing" },
|
|
318
|
+
"align": { type: "static", property: "text-align" },
|
|
319
|
+
// text-center
|
|
320
|
+
// --- Layout ---
|
|
321
|
+
"flex": { type: "static", property: "display", value: "flex" },
|
|
322
|
+
"inline-flex": { type: "static", property: "display", value: "inline-flex" },
|
|
323
|
+
"grid": { type: "static", property: "display", value: "grid" },
|
|
324
|
+
"hidden": { type: "static", property: "display", value: "none" },
|
|
325
|
+
"block": { type: "static", property: "display", value: "block" },
|
|
326
|
+
"inline-block": { type: "static", property: "display", value: "inline-block" },
|
|
327
|
+
"items": { type: "static", property: "align-items" },
|
|
328
|
+
// start, end, center, baseline, stretch
|
|
329
|
+
"justify": { type: "static", property: "justify-content" },
|
|
330
|
+
// start, end, center, between, around, evenly
|
|
331
|
+
"self": { type: "static", property: "align-self" },
|
|
332
|
+
"flex-col": { type: "static", property: "flex-direction", value: "column" },
|
|
333
|
+
"flex-row": { type: "static", property: "flex-direction", value: "row" },
|
|
334
|
+
"flex-wrap": { type: "static", property: "flex-wrap", value: "wrap" },
|
|
335
|
+
"flex-nowrap": { type: "static", property: "flex-wrap", value: "nowrap" },
|
|
336
|
+
"gap": { type: "space", property: "gap" },
|
|
337
|
+
"gap-x": { type: "space", property: "column-gap" },
|
|
338
|
+
"gap-y": { type: "space", property: "row-gap" },
|
|
339
|
+
// --- Sizing ---
|
|
340
|
+
"w": { type: "size", property: "width" },
|
|
341
|
+
"h": { type: "size", property: "height" },
|
|
342
|
+
"min-w": { type: "size", property: "min-width" },
|
|
343
|
+
"min-h": { type: "size", property: "min-height" },
|
|
344
|
+
"max-w": { type: "size", property: "max-width" },
|
|
345
|
+
"max-h": { type: "size", property: "max-height" },
|
|
346
|
+
// --- Borders & Effects ---
|
|
347
|
+
"rounded": { type: "radius", property: "border-radius" },
|
|
348
|
+
"shadow": { type: "shadow", property: "box-shadow" },
|
|
349
|
+
"opacity": { type: "value", property: "opacity" },
|
|
350
|
+
"z": { type: "zIndex", property: "z-index" },
|
|
351
|
+
// --- Position ---
|
|
352
|
+
"absolute": { type: "static", property: "position", value: "absolute" },
|
|
353
|
+
"relative": { type: "static", property: "position", value: "relative" },
|
|
354
|
+
"fixed": { type: "static", property: "position", value: "fixed" },
|
|
355
|
+
"top": { type: "space", property: "top" },
|
|
356
|
+
"right": { type: "space", property: "right" },
|
|
357
|
+
"bottom": { type: "space", property: "bottom" },
|
|
358
|
+
"left": { type: "space", property: "left" }
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// ../core/jit/generator.js
|
|
362
|
+
function generateUtility(className, config) {
|
|
363
|
+
let bp = null;
|
|
364
|
+
let util = className;
|
|
365
|
+
if (className.includes(":")) {
|
|
366
|
+
[bp, util] = className.split(":");
|
|
367
|
+
}
|
|
368
|
+
let css = "";
|
|
369
|
+
if (!util.startsWith(config.prefix)) return null;
|
|
370
|
+
const coreUtil = util.replace(config.prefix, "");
|
|
371
|
+
for (const [key, def] of Object.entries(registry)) {
|
|
372
|
+
const prefix = `${key}-`;
|
|
373
|
+
if (coreUtil.startsWith(prefix)) {
|
|
374
|
+
const value = coreUtil.slice(prefix.length);
|
|
375
|
+
let varName = "";
|
|
376
|
+
if (def.type === "space") varName = `var(--${config.prefix}space-${value})`;
|
|
377
|
+
else if (def.type === "color") varName = `var(--${config.prefix}color-${value})`;
|
|
378
|
+
else if (def.type === "radius") varName = `var(--${config.prefix}radius-${value || "DEFAULT"})`;
|
|
379
|
+
else if (def.type === "shadow") varName = `var(--${config.prefix}shadow-${value || "DEFAULT"})`;
|
|
380
|
+
else if (def.type === "zIndex") varName = `var(--${config.prefix}zIndex-${value})`;
|
|
381
|
+
else if (def.type === "fontDetail") varName = `var(--${config.prefix}fontWeight-${value})`;
|
|
382
|
+
else if (def.type === "static") {
|
|
383
|
+
if (def.value) {
|
|
384
|
+
if (value !== "" && !def.allowValue) continue;
|
|
385
|
+
varName = def.value;
|
|
386
|
+
} else {
|
|
387
|
+
varName = value;
|
|
388
|
+
}
|
|
389
|
+
} else if (def.type === "size") {
|
|
390
|
+
if (config.theme.spacing[value]) {
|
|
391
|
+
varName = `var(--${config.prefix}space-${value})`;
|
|
392
|
+
} else if (value.includes("/")) {
|
|
393
|
+
const [num, den] = value.split("/");
|
|
394
|
+
varName = `${parseInt(num) / parseInt(den) * 100}%`;
|
|
395
|
+
} else {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
} else continue;
|
|
399
|
+
const props = Array.isArray(def.property) ? def.property : [def.property];
|
|
400
|
+
const decls = def.type === "static" && def.value ? varName : props.map((p) => `${p}:${varName}`).join(";");
|
|
401
|
+
css = `.${escape(className)}{${decls};}`;
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (!css) return null;
|
|
406
|
+
if (bp) {
|
|
407
|
+
const size = config.breakpoints[bp];
|
|
408
|
+
return `@media (min-width:${size}){${css}}`;
|
|
409
|
+
}
|
|
410
|
+
return css;
|
|
411
|
+
}
|
|
412
|
+
function escape(cls) {
|
|
413
|
+
return cls.replace(/:/g, "\\:");
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// jit/writer.js
|
|
417
|
+
import fs3 from "fs-extra";
|
|
418
|
+
function writeCSS(state, outputPath) {
|
|
419
|
+
let css = "/* UX4G v3 \u2013 JIT build */\n";
|
|
420
|
+
for (const rule of state.generatedCSS.values()) {
|
|
421
|
+
css += rule + "\n";
|
|
422
|
+
}
|
|
423
|
+
fs3.ensureFileSync(outputPath);
|
|
424
|
+
fs3.writeFileSync(outputPath, css);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// plugins/runPlugins.js
|
|
428
|
+
function runPlugins(hook, state, config) {
|
|
429
|
+
if (!config.plugins || !config.plugins.length) return;
|
|
430
|
+
for (const plugin of config.plugins) {
|
|
431
|
+
let pluginDef = plugin;
|
|
432
|
+
if (typeof plugin === "function") {
|
|
433
|
+
pluginDef = plugin();
|
|
434
|
+
}
|
|
435
|
+
if (!pluginDef || typeof pluginDef !== "object") continue;
|
|
436
|
+
if (typeof pluginDef[hook] === "function") {
|
|
437
|
+
const api = createPluginAPI(state, config);
|
|
438
|
+
pluginDef[hook](api);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function createPluginAPI(state, config) {
|
|
443
|
+
return {
|
|
444
|
+
addUtility(className, css) {
|
|
445
|
+
state.generatedCSS.set(className, css);
|
|
446
|
+
},
|
|
447
|
+
hasUtility(className) {
|
|
448
|
+
return state.generatedCSS.has(className);
|
|
449
|
+
},
|
|
450
|
+
theme(path3) {
|
|
451
|
+
return path3.split(".").reduce((o, k) => o == null ? void 0 : o[k], config.theme);
|
|
452
|
+
},
|
|
453
|
+
config(path3) {
|
|
454
|
+
return path3.split(".").reduce((o, k) => o == null ? void 0 : o[k], config);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// minify/minifyCSS.lightning.js
|
|
460
|
+
import fs4 from "fs";
|
|
461
|
+
import { transform } from "lightningcss";
|
|
462
|
+
function minifyCSS(inputFile, outputFile) {
|
|
463
|
+
const css = fs4.readFileSync(inputFile, "utf8");
|
|
464
|
+
const result = transform({
|
|
465
|
+
filename: inputFile,
|
|
466
|
+
code: Buffer.from(css),
|
|
467
|
+
minify: true,
|
|
468
|
+
sourceMap: false,
|
|
469
|
+
targets: {
|
|
470
|
+
chrome: 90,
|
|
471
|
+
firefox: 90,
|
|
472
|
+
safari: 14,
|
|
473
|
+
edge: 90
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
fs4.writeFileSync(outputFile, result.code);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// ../core/config/preflight.js
|
|
480
|
+
var preflight = `
|
|
481
|
+
/* UX4G Preflight (Reset) */
|
|
482
|
+
*, ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }
|
|
483
|
+
html { line-height: 1.5; -webkit-text-size-adjust: 100%; -moz-tab-size: 4; tab-size: 4; font-family: system-ui, sans-serif; }
|
|
484
|
+
body { margin: 0; line-height: inherit; }
|
|
485
|
+
hr { height: 0; color: inherit; border-top-width: 1px; }
|
|
486
|
+
abbr:where([title]) { text-decoration: underline dotted; }
|
|
487
|
+
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; }
|
|
488
|
+
a { color: inherit; text-decoration: inherit; }
|
|
489
|
+
b, strong { font-weight: bolder; }
|
|
490
|
+
code, kbd, samp, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 1em; }
|
|
491
|
+
small { font-size: 80%; }
|
|
492
|
+
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
|
|
493
|
+
sub { bottom: -0.25em; }
|
|
494
|
+
sup { top: -0.5em; }
|
|
495
|
+
table { text-indent: 0; border-color: inherit; border-collapse: collapse; }
|
|
496
|
+
button, input, optgroup, select, textarea { font-family: inherit; font-size: 100%; line-height: inherit; color: inherit; margin: 0; padding: 0; }
|
|
497
|
+
button, select { text-transform: none; }
|
|
498
|
+
button, [type='button'], [type='reset'], [type='submit'] { -webkit-appearance: button; background-color: transparent; background-image: none; }
|
|
499
|
+
:-moz-focusring { outline: auto; }
|
|
500
|
+
:-moz-ui-invalid { box-shadow: none; }
|
|
501
|
+
progress { vertical-align: baseline; }
|
|
502
|
+
::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; }
|
|
503
|
+
[type='search'] { -webkit-appearance: textfield; outline-offset: -2px; }
|
|
504
|
+
::-webkit-search-decoration { -webkit-appearance: none; }
|
|
505
|
+
::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; }
|
|
506
|
+
summary { display: list-item; }
|
|
507
|
+
blockquote, dl, dd, h1, h2, h3, h4, h5, h6, hr, figure, p, pre { margin: 0; }
|
|
508
|
+
fieldset { margin: 0; padding: 0; }
|
|
509
|
+
legend { padding: 0; }
|
|
510
|
+
ol, ul, menu { list-style: none; margin: 0; padding: 0; }
|
|
511
|
+
textarea { resize: vertical; }
|
|
512
|
+
input::placeholder, textarea::placeholder { opacity: 1; color: #9ca3af; }
|
|
513
|
+
button, [role="button"] { cursor: pointer; }
|
|
514
|
+
:disabled { cursor: default; }
|
|
515
|
+
img, svg, video, canvas, audio, iframe, embed, object { display: block; vertical-align: middle; }
|
|
516
|
+
img, video { max-width: 100%; height: auto; }
|
|
517
|
+
[hidden] { display: none; }
|
|
518
|
+
`;
|
|
519
|
+
|
|
520
|
+
// commands/build.js
|
|
521
|
+
async function build({ cdn = false, input, output } = {}) {
|
|
522
|
+
const config = loadUX4GConfig();
|
|
523
|
+
config.mode = cdn ? "cdn" : "build";
|
|
524
|
+
if (output) {
|
|
525
|
+
config.output.filePath = path2.resolve(process.cwd(), output);
|
|
526
|
+
config.output.dir = path2.dirname(config.output.filePath);
|
|
527
|
+
}
|
|
528
|
+
const state = createJITState2(config);
|
|
529
|
+
if (cdn) {
|
|
530
|
+
console.log("\u26A0\uFE0F NOTE: Static CDN build is deprecated. Please use the Runtime Engine (@ux4g/cdn).");
|
|
531
|
+
console.log(" Include the following script in your HTML:");
|
|
532
|
+
console.log(' <script src="https://cdn.jsdelivr.net/npm/@netoyed/ux4g-design-system-v3-cdn/dist/ux4g.cdn.js"></script>');
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const files = await fg(config.content);
|
|
536
|
+
const classes = scanFiles(files, state, config);
|
|
537
|
+
config.safelist.forEach((rule) => {
|
|
538
|
+
if (typeof rule === "string") state.usedClasses.add(rule);
|
|
539
|
+
});
|
|
540
|
+
for (const cls of classes) {
|
|
541
|
+
state.usedClasses.add(cls);
|
|
542
|
+
}
|
|
543
|
+
for (const cls of state.usedClasses) {
|
|
544
|
+
const css = generateUtility(cls, config);
|
|
545
|
+
if (css) state.generatedCSS.set(cls, css);
|
|
546
|
+
}
|
|
547
|
+
runPlugins("beforeBuild", state, config);
|
|
548
|
+
let finalCSS = "";
|
|
549
|
+
let utilitiesCSS = Array.from(state.generatedCSS.values()).join("");
|
|
550
|
+
if (input) {
|
|
551
|
+
const inputPath = path2.resolve(process.cwd(), input);
|
|
552
|
+
if (fs5.existsSync(inputPath)) {
|
|
553
|
+
let inputContent = fs5.readFileSync(inputPath, "utf8");
|
|
554
|
+
inputContent = inputContent.replace("@ux4g base;", preflight);
|
|
555
|
+
inputContent = inputContent.replace("@ux4g utilities;", utilitiesCSS);
|
|
556
|
+
finalCSS = inputContent;
|
|
557
|
+
} else {
|
|
558
|
+
console.error(`\u274C Input file not found: ${inputPath}`);
|
|
559
|
+
process.exit(1);
|
|
560
|
+
}
|
|
561
|
+
} else {
|
|
562
|
+
finalCSS = preflight + "\n" + utilitiesCSS;
|
|
563
|
+
}
|
|
564
|
+
if (!fs5.existsSync(config.output.dir)) fs5.mkdirSync(config.output.dir, { recursive: true });
|
|
565
|
+
fs5.writeFileSync(config.output.filePath, finalCSS);
|
|
566
|
+
if (config.output.minify) {
|
|
567
|
+
const minFile = config.output.filePath.replace(".css", ".min.css");
|
|
568
|
+
minifyCSS(config.output.filePath, minFile);
|
|
569
|
+
}
|
|
570
|
+
runPlugins("afterBuild", state, config);
|
|
571
|
+
console.log(`\u2705 UX4G production build complete: ${config.output.filePath}`);
|
|
572
|
+
console.log(` Import this file in your main app entry:`);
|
|
573
|
+
console.log(` import './${path2.relative(process.cwd(), config.output.filePath).replace(/\\/g, "/")}';`);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// jit/watcher.js
|
|
577
|
+
import chokidar from "chokidar";
|
|
578
|
+
import fg2 from "fast-glob";
|
|
579
|
+
function startWatcher(config, state) {
|
|
580
|
+
const watcher = chokidar.watch(config.content, {
|
|
581
|
+
ignoreInitial: true
|
|
582
|
+
});
|
|
583
|
+
watcher.on("all", async () => {
|
|
584
|
+
const files = await fg2(config.content);
|
|
585
|
+
const classes = scanFiles(files, state, config);
|
|
586
|
+
let changed = false;
|
|
587
|
+
for (const cls of classes) {
|
|
588
|
+
if (!state.generatedCSS.has(cls)) {
|
|
589
|
+
const css = generateUtility(cls, config);
|
|
590
|
+
if (css) {
|
|
591
|
+
state.generatedCSS.set(cls, css);
|
|
592
|
+
changed = true;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (changed) {
|
|
597
|
+
writeCSS(state, config.output.filePath);
|
|
598
|
+
console.log("\u267B\uFE0F UX4G JIT updated");
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// commands/watch.js
|
|
604
|
+
async function watch() {
|
|
605
|
+
console.log("\u{1F440} Starting UX4G Watch Mode...");
|
|
606
|
+
await build({ cdn: false });
|
|
607
|
+
const config = loadUX4GConfig();
|
|
608
|
+
config.mode = "dev";
|
|
609
|
+
const state = createJITState2(config);
|
|
610
|
+
startWatcher(config, state);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// bin/ux4g.js
|
|
614
|
+
var program = new Command();
|
|
615
|
+
program.name("ux4g").description("UX4G Design System CLI").version("1.0.0");
|
|
616
|
+
program.command("build").description("Build CSS for production").option("--cdn", "Build for CDN (Runtime Engine)").option("-i, --input <file>", "Input CSS file").option("-o, --output <file>", "Output CSS file").action((options) => {
|
|
617
|
+
build(options);
|
|
618
|
+
});
|
|
619
|
+
program.command("watch").description("Watch files for changes and rebuild CSS").action(() => {
|
|
620
|
+
watch();
|
|
621
|
+
});
|
|
622
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@netoyed/ux4g-design-system-v3-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI for UX4G Design System",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ux4g": "./dist/ux4g.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup bin/ux4g.js --format esm --out-dir dist --clean --platform node",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"postcss": "^8.0.0",
|
|
19
|
+
"tsup": "^8.0.0",
|
|
20
|
+
"typescript": "^5.9.3"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"chokidar": "^5.0.0",
|
|
24
|
+
"colorette": "^2.0.20",
|
|
25
|
+
"commander": "^14.0.3",
|
|
26
|
+
"fast-glob": "^3.3.3",
|
|
27
|
+
"fs-extra": "^11.3.3",
|
|
28
|
+
"lightningcss": "^1.31.1"
|
|
29
|
+
}
|
|
30
|
+
}
|