@umoa/saascfm-css 0.0.0-stage → 0.1.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/index.cjs ADDED
@@ -0,0 +1,565 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ default: () => cssModule
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_node_path = __toESM(require("path"), 1);
37
+ var import_node_fs = __toESM(require("fs"), 1);
38
+
39
+ // src/layout/css-spacing.ts
40
+ var SPACING_RULES = {
41
+ // sizing
42
+ w: { props: ["width"] },
43
+ h: { props: ["height"] },
44
+ mw: { props: ["max-width"] },
45
+ mh: { props: ["max-height"] },
46
+ minw: { props: ["min-width"] },
47
+ minh: { props: ["min-height"] },
48
+ // margin
49
+ mt: { props: ["margin-top"] },
50
+ mr: { props: ["margin-right"] },
51
+ mb: { props: ["margin-bottom"] },
52
+ ml: { props: ["margin-left"] },
53
+ mtb: { props: ["margin-top", "margin-bottom"] },
54
+ mrl: { props: ["margin-right", "margin-left"] },
55
+ // padding
56
+ p: { props: ["padding"] },
57
+ pt: { props: ["padding-top"] },
58
+ pr: { props: ["padding-right"] },
59
+ pb: { props: ["padding-bottom"] },
60
+ pl: { props: ["padding-left"] },
61
+ ptb: { props: ["padding-top", "padding-bottom"] },
62
+ prl: { props: ["padding-right", "padding-left"] },
63
+ // gap
64
+ g: { props: ["gap"], nonNegative: true },
65
+ gc: { props: ["column-gap"], nonNegative: true },
66
+ gr: { props: ["row-gap"], nonNegative: true },
67
+ // misc
68
+ bdrd: { props: ["border-radius"] },
69
+ bdw: { props: ["border-width"], companion: { "border-style": "solid" } },
70
+ zdex: { props: ["z-index"], unitless: true }
71
+ };
72
+ var SPACING_PERCENT_ENABLED = /* @__PURE__ */ new Set([
73
+ "w",
74
+ "h",
75
+ "mw",
76
+ "mh",
77
+ "minw",
78
+ "minh",
79
+ "mt",
80
+ "mr",
81
+ "mb",
82
+ "ml",
83
+ "mtb",
84
+ "mrl",
85
+ "p",
86
+ "pt",
87
+ "pr",
88
+ "pb",
89
+ "pl",
90
+ "ptb",
91
+ "prl"
92
+ ]);
93
+ var SPACING_VIEWPORT_ENABLED = /* @__PURE__ */ new Set(["w", "h"]);
94
+ var SPACING_ORDER = [
95
+ "w",
96
+ "h",
97
+ "mw",
98
+ "mh",
99
+ "minw",
100
+ "minh",
101
+ "p",
102
+ "ptb",
103
+ "prl",
104
+ "pt",
105
+ "pr",
106
+ "pb",
107
+ "pl",
108
+ "mtb",
109
+ "mrl",
110
+ "mt",
111
+ "mr",
112
+ "mb",
113
+ "ml",
114
+ "g",
115
+ "gc",
116
+ "gr",
117
+ "bdrd",
118
+ "bdw",
119
+ "zdex"
120
+ ];
121
+ var SPACING_ALTERNATION = Object.keys(SPACING_RULES).sort((a, b) => b.length - a.length).join("|");
122
+
123
+ // src/layout/css-spacing-static.ts
124
+ var SPACING_STATIC_RULES = {
125
+ bn: { border: "none" },
126
+ auto: { margin: "0 auto" },
127
+ hl: { "border-bottom": "1px solid var(--border-default, currentColor)", width: "100%" },
128
+ "hl-muted": { "border-bottom": "1px solid var(--border-muted, var(--border-default, currentColor))", width: "100%" },
129
+ vl: { "border-left": "2px solid var(--border-default, currentColor)", height: "20px" },
130
+ "mcon-480": { "max-width": "480px", margin: "0 auto" },
131
+ "mcon-640": { "max-width": "640px", margin: "0 auto" },
132
+ "mcon-768": { "max-width": "768px", margin: "0 auto" },
133
+ "mcon-1080": { "max-width": "1080px", margin: "0 auto" },
134
+ "mcon-1280": { "max-width": "1280px", margin: "0 auto" },
135
+ "mcon-1440": { "max-width": "1440px", margin: "0 auto" }
136
+ };
137
+ var SPACING_STATIC_ALTERNATION = Object.keys(SPACING_STATIC_RULES).sort((a, b) => b.length - a.length).join("|");
138
+
139
+ // src/layout/css-layout.ts
140
+ var LAYOUT_RULES = {
141
+ // flex container
142
+ flex: { display: "flex" },
143
+ "flex-fdr": { "flex-direction": "row" },
144
+ "flex-fdrr": { "flex-direction": "row-reverse" },
145
+ "flex-fdc": { "flex-direction": "column" },
146
+ "flex-fdcr": { "flex-direction": "column-reverse" },
147
+ "flex-wrap": { "flex-wrap": "wrap" },
148
+ "flex-nowrap": { "flex-wrap": "nowrap" },
149
+ // flex justify-content
150
+ "flex-jcfs": { "justify-content": "flex-start" },
151
+ "flex-jcfe": { "justify-content": "flex-end" },
152
+ "flex-jcc": { "justify-content": "center" },
153
+ "flex-jcsb": { "justify-content": "space-between" },
154
+ "flex-jcsa": { "justify-content": "space-around" },
155
+ "flex-jcse": { "justify-content": "space-evenly" },
156
+ // flex align-items
157
+ "flex-aifs": { "align-items": "flex-start" },
158
+ "flex-aife": { "align-items": "flex-end" },
159
+ "flex-aic": { "align-items": "center" },
160
+ "flex-aist": { "align-items": "stretch" },
161
+ "flex-aib": { "align-items": "baseline" },
162
+ // flex align-content
163
+ "flex-acfs": { "align-content": "flex-start" },
164
+ "flex-acfe": { "align-content": "flex-end" },
165
+ "flex-acc": { "align-content": "center" },
166
+ "flex-acst": { "align-content": "stretch" },
167
+ "flex-acsb": { "align-content": "space-between" },
168
+ "flex-acsa": { "align-content": "space-around" },
169
+ // flex align-self
170
+ "flex-assr": { "align-self": "stretch" },
171
+ "flex-asc": { "align-self": "center" },
172
+ "flex-ass": { "align-self": "start" },
173
+ "flex-ase": { "align-self": "end" },
174
+ // grid justify-items
175
+ "grid-jist": { "justify-items": "start" },
176
+ "grid-jie": { "justify-items": "end" },
177
+ "grid-jic": { "justify-items": "center" },
178
+ "grid-jistr": { "justify-items": "stretch" },
179
+ // grid align-items
180
+ "grid-aist": { "align-items": "start" },
181
+ "grid-aie": { "align-items": "end" },
182
+ "grid-aic": { "align-items": "center" },
183
+ "grid-aistr": { "align-items": "stretch" },
184
+ // text-align (found in the legacy file, was missing from the module)
185
+ "align-l": { "text-align": "left" },
186
+ "align-c": { "text-align": "center" },
187
+ "align-r": { "text-align": "right" },
188
+ // float
189
+ "float-l": { float: "left" },
190
+ "float-r": { float: "right" },
191
+ // float-c in the legacy file was actually `position: fixed; top: 50%; left: 50%`,
192
+ // not a real float — kept as its original (odd) behavior rather than
193
+ // silently "fixing" it into something it never was.
194
+ "float-c": { position: "fixed", top: "50%", left: "50%" }
195
+ };
196
+ var LAYOUT_ALTERNATION = Object.keys(LAYOUT_RULES).sort((a, b) => b.length - a.length).join("|");
197
+
198
+ // src/styling/css-typography.ts
199
+ var TYPOGRAPHY_RULES = {
200
+ // font-weight
201
+ nb: { "font-weight": "normal" },
202
+ b: { "font-weight": "bold" },
203
+ bx: { "font-weight": "bolder" },
204
+ "b-100": { "font-weight": "100" },
205
+ "b-200": { "font-weight": "200" },
206
+ "b-300": { "font-weight": "300" },
207
+ "b-400": { "font-weight": "400" },
208
+ "b-500": { "font-weight": "500" },
209
+ "b-600": { "font-weight": "600" },
210
+ "b-700": { "font-weight": "700" },
211
+ "b-800": { "font-weight": "800" },
212
+ "b-900": { "font-weight": "900" },
213
+ "b-lighter": { "font-weight": "100" },
214
+ "b-light": { "font-weight": "300" },
215
+ lighter: { "font-weight": "100" },
216
+ light: { "font-weight": "300" },
217
+ // text-transform
218
+ uppercase: { "text-transform": "uppercase" },
219
+ "to-uppercase": { "text-transform": "uppercase" },
220
+ lowercase: { "text-transform": "lowercase" },
221
+ "to-lowercase": { "text-transform": "lowercase" },
222
+ capitalize: { "text-transform": "capitalize" },
223
+ "text-none": { "text-transform": "none" },
224
+ // misc
225
+ i: { "font-style": "italic" },
226
+ underline: { "text-decoration": "underline" },
227
+ // word-wrap / hyphenation
228
+ ow: { "overflow-wrap": "break-word", "word-wrap": "break-word", hyphens: "auto" },
229
+ ww: { "overflow-wrap": "break-word", "word-wrap": "break-word", hyphens: "auto" }
230
+ };
231
+ var TYPOGRAPHY_ALTERNATION = Object.keys(TYPOGRAPHY_RULES).sort((a, b) => b.length - a.length).join("|");
232
+ var FONT_SIZE_PATTERN = "(?:fs|ls)-n?(?:\\d+)?(?:[dp]\\d+)?em";
233
+ function parseFontSize(cls) {
234
+ const match = cls.match(/^(fs|ls)-(n)?(\d+)?(?:[dp](\d+))?em$/);
235
+ if (!match) return null;
236
+ const [, kind, neg, intPart, decPart] = match;
237
+ if (!intPart && !decPart) return null;
238
+ if (neg && kind === "fs") return null;
239
+ const whole = intPart ?? "0";
240
+ const num = decPart ? `${whole}.${decPart}` : whole;
241
+ return {
242
+ prop: kind === "fs" ? "font-size" : "letter-spacing",
243
+ value: `${neg ? "-" : ""}${num}em`
244
+ };
245
+ }
246
+
247
+ // src/styling/css-cursor.ts
248
+ var CURSOR_RULES = {
249
+ "cursor-alias": { cursor: "alias" },
250
+ "cursor-all-scroll": { cursor: "all-scroll" },
251
+ "cursor-auto": { cursor: "auto" },
252
+ "cursor-cell": { cursor: "cell" },
253
+ "cursor-context-menu": { cursor: "context-menu" },
254
+ "cursor-col-resize": { cursor: "col-resize" },
255
+ "cursor-copy": { cursor: "copy" },
256
+ "cursor-crosshair": { cursor: "crosshair" },
257
+ "cursor-default": { cursor: "default" },
258
+ "cursor-e-resize": { cursor: "e-resize" },
259
+ "cursor-ew-resize": { cursor: "ew-resize" },
260
+ "cursor-grab": { cursor: "grab" },
261
+ "cursor-grabbing": { cursor: "grabbing" },
262
+ "cursor-help": { cursor: "help" },
263
+ "cursor-move": { cursor: "move" },
264
+ "cursor-n-resize": { cursor: "n-resize" },
265
+ "cursor-ne-resize": { cursor: "ne-resize" },
266
+ "cursor-nesw-resize": { cursor: "nesw-resize" },
267
+ "cursor-ns-resize": { cursor: "ns-resize" },
268
+ "cursor-nw-resize": { cursor: "nw-resize" },
269
+ "cursor-nwse-resize": { cursor: "nwse-resize" },
270
+ "cursor-no-drop": { cursor: "no-drop" },
271
+ "cursor-none": { cursor: "none" },
272
+ "cursor-not-allowed": { cursor: "not-allowed" },
273
+ "cursor-pointer": { cursor: "pointer" },
274
+ "cursor-progress": { cursor: "progress" },
275
+ "cursor-row-resize": { cursor: "row-resize" },
276
+ "cursor-s-resize": { cursor: "s-resize" },
277
+ "cursor-se-resize": { cursor: "se-resize" },
278
+ "cursor-sw-resize": { cursor: "sw-resize" },
279
+ "cursor-text": { cursor: "text" },
280
+ "cursor-w-resize": { cursor: "w-resize" },
281
+ "cursor-wait": { cursor: "wait" },
282
+ "cursor-zoom-in": { cursor: "zoom-in" },
283
+ "cursor-zoom-out": { cursor: "zoom-out" }
284
+ };
285
+ var CURSOR_ALTERNATION = Object.keys(CURSOR_RULES).sort((a, b) => b.length - a.length).join("|");
286
+
287
+ // src/styling/css-border.ts
288
+ var BORDER_STYLE_RULES = {
289
+ "bds-solid": { "border-style": "solid" },
290
+ "bds-dashed": { "border-style": "dashed" },
291
+ "bds-dotted": { "border-style": "dotted" },
292
+ "bds-double": { "border-style": "double" },
293
+ "bds-none": { "border-style": "none" }
294
+ };
295
+ var BORDER_STYLE_ALTERNATION = Object.keys(BORDER_STYLE_RULES).sort((a, b) => b.length - a.length).join("|");
296
+
297
+ // src/styling/css-color.ts
298
+ var PROP_BY_PREFIX = {
299
+ text: "color",
300
+ bg: "background-color",
301
+ border: "border-color"
302
+ };
303
+ var LOOKS_LIKE_KEY = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/i;
304
+ function resolveTokens(tokens, palette) {
305
+ const resolved = {};
306
+ for (const [name, value] of Object.entries(tokens)) {
307
+ if (typeof value !== "string" || !value) {
308
+ console.warn(`[saascfm-css] token "${name}" has no value, skipped`);
309
+ continue;
310
+ }
311
+ const fromPalette = palette[value];
312
+ if (!fromPalette && LOOKS_LIKE_KEY.test(value)) {
313
+ console.warn(`[saascfm-css] token "${name}" references unknown primitive "${value}", skipped`);
314
+ continue;
315
+ }
316
+ resolved[name] = fromPalette ?? value;
317
+ }
318
+ return resolved;
319
+ }
320
+ function generateRootVars(resolved) {
321
+ const lines = Object.entries(resolved).sort(([a], [b]) => a.localeCompare(b)).map(([name, value]) => ` --${name}: ${value};`);
322
+ return `:root {
323
+ ${lines.join("\n")}
324
+ }
325
+ `;
326
+ }
327
+ function buildColorUtilityRules(resolved) {
328
+ const rules = {};
329
+ for (const name of Object.keys(resolved)) {
330
+ const prop = PROP_BY_PREFIX[name.split("-")[0]];
331
+ if (!prop) continue;
332
+ rules[name] = { [prop]: `var(--${name})` };
333
+ }
334
+ return rules;
335
+ }
336
+ function buildPrimitiveRules(primitives) {
337
+ const rules = {};
338
+ for (const [name, value] of Object.entries(primitives)) {
339
+ rules[name] = { color: value };
340
+ if (/^(rgba|hsla)/i.test(value)) continue;
341
+ rules[`bg-${name}`] = { "background-color": value };
342
+ rules[`border-${name}`] = { "border-color": value };
343
+ }
344
+ return rules;
345
+ }
346
+ function colorAlternation(rules) {
347
+ return Object.keys(rules).sort((a, b) => b.length - a.length).join("|");
348
+ }
349
+
350
+ // src/index.ts
351
+ var PKG = "saascfm-css";
352
+ var VIRTUAL_ID = "virtual:css-module.css";
353
+ var RESOLVED_VIRTUAL_ID = "\0" + VIRTUAL_ID;
354
+ function cssModule(options = {}) {
355
+ const srcDir = options.srcDir || "src";
356
+ const extensions = options.extensions || [".vue", ".js", ".jsx", ".ts", ".tsx", ".html"];
357
+ const exclude = options.exclude || [".colors.", ".tokens.", "primitives."];
358
+ const useSpacing = options.spacing !== false;
359
+ const useLayout = options.layout !== false;
360
+ const useTypography = options.typography !== false;
361
+ const useCursor = options.cursor !== false;
362
+ const useBorder = options.border !== false;
363
+ let COLOR_ROOT_VARS = "";
364
+ let COLOR_RULES = {};
365
+ let PRIMITIVE_COLOR_RULES = {};
366
+ let COLOR_ALTERNATION = "";
367
+ const colorsModule = options.colorsModule ?? {};
368
+ const tokens = colorsModule["TOKENS"];
369
+ const primitives = colorsModule["PRIMITIVES"];
370
+ const useColor = !!(tokens || primitives);
371
+ if (useColor) {
372
+ if (tokens) {
373
+ const resolved = resolveTokens(tokens, primitives ?? {});
374
+ COLOR_ROOT_VARS = generateRootVars(resolved);
375
+ COLOR_RULES = buildColorUtilityRules(resolved);
376
+ }
377
+ if (primitives && options.primitiveClasses !== false) {
378
+ PRIMITIVE_COLOR_RULES = buildPrimitiveRules(primitives);
379
+ }
380
+ COLOR_ALTERNATION = colorAlternation({ ...COLOR_RULES, ...PRIMITIVE_COLOR_RULES });
381
+ }
382
+ const alternatives = [];
383
+ if (useSpacing) {
384
+ alternatives.push(`(?:${SPACING_ALTERNATION})-n?\\d+(?:d\\d+)?(?:p|vw|vh)?`);
385
+ alternatives.push(`(?:${SPACING_STATIC_ALTERNATION})`);
386
+ }
387
+ if (useLayout) alternatives.push(`(?:${LAYOUT_ALTERNATION})`);
388
+ if (useTypography) {
389
+ alternatives.push(`(?:${TYPOGRAPHY_ALTERNATION})`);
390
+ alternatives.push(FONT_SIZE_PATTERN);
391
+ }
392
+ if (useCursor) alternatives.push(`(?:${CURSOR_ALTERNATION})`);
393
+ if (useBorder) alternatives.push(`(?:${BORDER_STYLE_ALTERNATION})`);
394
+ if (useColor && COLOR_ALTERNATION) alternatives.push(`(?:${COLOR_ALTERNATION})`);
395
+ const CLASS_RE = new RegExp(
396
+ `(?:^|["'\`\\s(])(${alternatives.join("|")})(!)?(?=["'\`\\s)]|$)`,
397
+ "g"
398
+ );
399
+ function parseClass(cls) {
400
+ if (useSpacing && SPACING_STATIC_RULES[cls]) {
401
+ return { kind: "static", decls: SPACING_STATIC_RULES[cls] };
402
+ }
403
+ if (useLayout && LAYOUT_RULES[cls]) {
404
+ return { kind: "static", decls: LAYOUT_RULES[cls] };
405
+ }
406
+ if (useTypography && TYPOGRAPHY_RULES[cls]) {
407
+ return { kind: "static", decls: TYPOGRAPHY_RULES[cls] };
408
+ }
409
+ if (useCursor && CURSOR_RULES[cls]) {
410
+ return { kind: "static", decls: CURSOR_RULES[cls] };
411
+ }
412
+ if (useBorder && BORDER_STYLE_RULES[cls]) {
413
+ return { kind: "static", decls: BORDER_STYLE_RULES[cls] };
414
+ }
415
+ if (useColor && COLOR_RULES[cls]) {
416
+ return { kind: "static", decls: COLOR_RULES[cls] };
417
+ }
418
+ if (useColor && PRIMITIVE_COLOR_RULES[cls]) {
419
+ return { kind: "static", decls: PRIMITIVE_COLOR_RULES[cls] };
420
+ }
421
+ if (useTypography) {
422
+ const fontSize = parseFontSize(cls);
423
+ if (fontSize) return { kind: "fontsize", prop: fontSize.prop, value: fontSize.value };
424
+ }
425
+ if (useSpacing) {
426
+ const match = cls.match(/^([a-z]+)-(n)?(\d+(?:d\d+)?)(p|vw|vh)?$/);
427
+ if (match) {
428
+ const [, prefix, neg, num, suffix] = match;
429
+ const rule = SPACING_RULES[prefix];
430
+ if (rule) {
431
+ if (suffix === "p" && !SPACING_PERCENT_ENABLED.has(prefix)) return null;
432
+ if ((suffix === "vw" || suffix === "vh") && !SPACING_VIEWPORT_ENABLED.has(prefix)) return null;
433
+ if (rule.unitless && (suffix || num.includes("d"))) return null;
434
+ if (neg && rule.nonNegative) return null;
435
+ const sign = neg ? "-" : "";
436
+ let unit;
437
+ if (rule.unitless) unit = "";
438
+ else if (suffix === "p") unit = "%";
439
+ else if (suffix === "vw") unit = "vw";
440
+ else if (suffix === "vh") unit = "vh";
441
+ else unit = "px";
442
+ return { kind: "numeric", props: rule.props, value: `${sign}${num.replace("d", ".")}${unit}`, companion: rule.companion };
443
+ }
444
+ }
445
+ }
446
+ return null;
447
+ }
448
+ function rank(base) {
449
+ if (useBorder && BORDER_STYLE_RULES[base]) return 3;
450
+ if (useSpacing && SPACING_STATIC_RULES[base]) return 0;
451
+ const m = base.match(/^([a-z]+)-n?\d/);
452
+ if (useSpacing && m && SPACING_RULES[m[1]]) return 1;
453
+ return 2;
454
+ }
455
+ function generateCSS(classes) {
456
+ const entries = [...classes].map((key) => {
457
+ const bang = key.endsWith("!");
458
+ const base = bang ? key.slice(0, -1) : key;
459
+ const m = base.match(/^([a-z]+)-n?\d/);
460
+ const sub = rank(base) === 1 && m ? SPACING_ORDER.indexOf(m[1]) : 0;
461
+ return { key, base, bang, tier: rank(base), sub };
462
+ });
463
+ entries.sort(
464
+ (x, y) => x.tier - y.tier || x.sub - y.sub || x.base.localeCompare(y.base) || Number(x.bang) - Number(y.bang)
465
+ );
466
+ let css = `/* AUTO-GENERATED by ${PKG} \u2014 do not edit by hand. */
467
+ `;
468
+ if (COLOR_ROOT_VARS) css += COLOR_ROOT_VARS;
469
+ for (const { base, bang } of entries) {
470
+ const parsed = parseClass(base);
471
+ if (!parsed) continue;
472
+ const flag = options.important || bang ? " !important" : "";
473
+ let decls;
474
+ if (parsed.kind === "numeric") {
475
+ const all = parsed.props.map((p) => ` ${p}: ${parsed.value}${flag};`);
476
+ const companion = parsed.companion ? Object.entries(parsed.companion).map(([p, v]) => ` ${p}: ${v}${flag};`) : [];
477
+ decls = [...all, ...companion].join("\n");
478
+ } else if (parsed.kind === "static") {
479
+ decls = Object.entries(parsed.decls).map(([prop, value]) => ` ${prop}: ${value}${flag};`).join("\n");
480
+ } else {
481
+ decls = ` ${parsed.prop}: ${parsed.value}${flag};`;
482
+ }
483
+ css += `.${base}${bang ? "\\!" : ""} {
484
+ ${decls}
485
+ }
486
+ `;
487
+ }
488
+ return css;
489
+ }
490
+ function walkDir(dir, exts, out = []) {
491
+ let entries;
492
+ try {
493
+ entries = import_node_fs.default.readdirSync(dir, { withFileTypes: true });
494
+ } catch {
495
+ return out;
496
+ }
497
+ for (const entry of entries) {
498
+ if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
499
+ const full = import_node_path.default.join(dir, entry.name);
500
+ if (entry.isDirectory()) {
501
+ walkDir(full, exts, out);
502
+ } else if (exts.some((e) => entry.name.endsWith(e)) && !exclude.some((x) => full.includes(x))) {
503
+ out.push(full);
504
+ }
505
+ }
506
+ return out;
507
+ }
508
+ let root = process.cwd();
509
+ const found = /* @__PURE__ */ new Set();
510
+ let viteServer = null;
511
+ function scanFile(file) {
512
+ let content;
513
+ try {
514
+ content = import_node_fs.default.readFileSync(file, "utf-8");
515
+ } catch {
516
+ return false;
517
+ }
518
+ let changed = false;
519
+ let m;
520
+ CLASS_RE.lastIndex = 0;
521
+ while (m = CLASS_RE.exec(content)) {
522
+ const key = m[1] + (m[2] ?? "");
523
+ if (!found.has(key) && parseClass(m[1])) {
524
+ found.add(key);
525
+ changed = true;
526
+ }
527
+ }
528
+ return changed;
529
+ }
530
+ function scanAll() {
531
+ for (const file of walkDir(import_node_path.default.resolve(root, srcDir), extensions)) scanFile(file);
532
+ scanFile(import_node_path.default.resolve(root, "index.html"));
533
+ }
534
+ function handleFsEvent(file) {
535
+ if (!extensions.some((e) => file.endsWith(e))) return;
536
+ if (exclude.some((x) => file.includes(x))) return;
537
+ const changed = scanFile(file);
538
+ if (changed && viteServer) {
539
+ const mod = viteServer.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
540
+ if (mod) viteServer.moduleGraph.invalidateModule(mod);
541
+ viteServer.ws.send({ type: "full-reload" });
542
+ }
543
+ }
544
+ return {
545
+ name: PKG,
546
+ configResolved(config) {
547
+ root = config.root;
548
+ },
549
+ buildStart() {
550
+ scanAll();
551
+ },
552
+ resolveId(id) {
553
+ if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID;
554
+ },
555
+ load(id) {
556
+ if (id === RESOLVED_VIRTUAL_ID) return generateCSS(found);
557
+ },
558
+ configureServer(server) {
559
+ viteServer = server;
560
+ server.watcher.add(import_node_path.default.resolve(root, srcDir));
561
+ server.watcher.on("change", handleFsEvent);
562
+ server.watcher.on("add", handleFsEvent);
563
+ }
564
+ };
565
+ }
@@ -0,0 +1,18 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ interface CssModuleOptions {
4
+ srcDir?: string;
5
+ extensions?: string[];
6
+ spacing?: boolean;
7
+ layout?: boolean;
8
+ typography?: boolean;
9
+ cursor?: boolean;
10
+ border?: boolean;
11
+ colorsModule?: Record<string, unknown>;
12
+ primitiveClasses?: boolean;
13
+ exclude?: string[];
14
+ important?: boolean;
15
+ }
16
+ declare function cssModule(options?: CssModuleOptions): Plugin;
17
+
18
+ export { type CssModuleOptions, cssModule as default };
@@ -0,0 +1,18 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ interface CssModuleOptions {
4
+ srcDir?: string;
5
+ extensions?: string[];
6
+ spacing?: boolean;
7
+ layout?: boolean;
8
+ typography?: boolean;
9
+ cursor?: boolean;
10
+ border?: boolean;
11
+ colorsModule?: Record<string, unknown>;
12
+ primitiveClasses?: boolean;
13
+ exclude?: string[];
14
+ important?: boolean;
15
+ }
16
+ declare function cssModule(options?: CssModuleOptions): Plugin;
17
+
18
+ export { type CssModuleOptions, cssModule as default };