@monoes/monodesign 1.2.18 → 1.2.22

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.
Files changed (104) hide show
  1. package/README.md +3 -3
  2. package/cli/engine/design-system-checks.mjs +381 -0
  3. package/cli/engine/design-system-parse.mjs +433 -0
  4. package/cli/engine/design-system.mjs +20 -736
  5. package/cli/engine/detect-antipatterns-browser.js +12 -1
  6. package/cli/engine/engines/regex/detect-text-matchers.mjs +371 -0
  7. package/cli/engine/engines/regex/detect-text-run.mjs +186 -0
  8. package/cli/engine/engines/regex/detect-text.mjs +11 -523
  9. package/cli/engine/engines/static-html/css-cascade-color.mjs +219 -0
  10. package/cli/engine/engines/static-html/css-cascade-static-data.mjs +138 -0
  11. package/cli/engine/engines/static-html/css-cascade-static-dom.mjs +132 -0
  12. package/cli/engine/engines/static-html/css-cascade-static-parse.mjs +393 -0
  13. package/cli/engine/engines/static-html/css-cascade.mjs +24 -837
  14. package/cli/engine/registry/antipatterns-provider.mjs +60 -0
  15. package/cli/engine/registry/antipatterns-quality.mjs +218 -0
  16. package/cli/engine/registry/antipatterns-slop.mjs +226 -0
  17. package/cli/engine/registry/antipatterns.mjs +7 -494
  18. package/cli/engine/rules/checks-background.mjs +155 -0
  19. package/cli/engine/rules/checks-css-values.mjs +137 -0
  20. package/cli/engine/rules/checks-dom-effects.mjs +243 -0
  21. package/cli/engine/rules/checks-dom.mjs +148 -0
  22. package/cli/engine/rules/checks-element.mjs +286 -0
  23. package/cli/engine/rules/checks-html.mjs +204 -0
  24. package/cli/engine/rules/checks-overflow.mjs +263 -0
  25. package/cli/engine/rules/checks-page.mjs +465 -0
  26. package/cli/engine/rules/checks-pure.mjs +453 -0
  27. package/cli/engine/rules/checks-quality.mjs +447 -0
  28. package/cli/engine/rules/checks-stylesheet.mjs +324 -0
  29. package/cli/engine/rules/checks.mjs +98 -2939
  30. package/cli/lib/monodesign-config-consent.mjs +93 -0
  31. package/cli/lib/monodesign-config-core.mjs +37 -0
  32. package/cli/lib/monodesign-config-detection.mjs +133 -0
  33. package/cli/lib/monodesign-config-filter.mjs +198 -0
  34. package/cli/lib/monodesign-config-ignore-value.mjs +212 -0
  35. package/cli/lib/monodesign-config.mjs +21 -623
  36. package/package.json +2 -2
  37. package/skill/scripts/context-fields.mjs +65 -0
  38. package/skill/scripts/context-resolve.mjs +425 -0
  39. package/skill/scripts/context-update.mjs +151 -0
  40. package/skill/scripts/context-utils.mjs +68 -0
  41. package/skill/scripts/context-workspace.mjs +245 -0
  42. package/skill/scripts/context.mjs +17 -891
  43. package/skill/scripts/hook-admin-config.mjs +152 -0
  44. package/skill/scripts/hook-admin-ignore.mjs +131 -0
  45. package/skill/scripts/hook-admin-manifest.mjs +292 -0
  46. package/skill/scripts/hook-admin.mjs +8 -541
  47. package/skill/scripts/hook-before-edit-shell.mjs +184 -0
  48. package/skill/scripts/hook-before-edit.mjs +9 -165
  49. package/skill/scripts/hook-lib-cache.mjs +145 -0
  50. package/skill/scripts/hook-lib-config.mjs +292 -0
  51. package/skill/scripts/hook-lib-detector.mjs +72 -0
  52. package/skill/scripts/hook-lib-events.mjs +182 -0
  53. package/skill/scripts/hook-lib-findings.mjs +201 -0
  54. package/skill/scripts/hook-lib-ignore.mjs +205 -0
  55. package/skill/scripts/hook-lib-render.mjs +273 -0
  56. package/skill/scripts/hook-lib-run.mjs +281 -0
  57. package/skill/scripts/hook-lib-scan-targets.mjs +128 -0
  58. package/skill/scripts/hook-lib.mjs +71 -1747
  59. package/skill/scripts/lib/design-parser-colors.mjs +182 -0
  60. package/skill/scripts/lib/design-parser-extract.mjs +333 -0
  61. package/skill/scripts/lib/design-parser-sections.mjs +214 -0
  62. package/skill/scripts/lib/design-parser-yaml.mjs +135 -0
  63. package/skill/scripts/lib/design-parser.mjs +10 -783
  64. package/skill/scripts/live/manual-apply-chunk.mjs +151 -0
  65. package/skill/scripts/live/manual-apply-compact.mjs +122 -0
  66. package/skill/scripts/live/manual-apply-evidence.mjs +115 -0
  67. package/skill/scripts/live/manual-apply-log.mjs +179 -0
  68. package/skill/scripts/live/manual-apply-transaction.mjs +122 -0
  69. package/skill/scripts/live/manual-apply.mjs +65 -640
  70. package/skill/scripts/live/svelte-component-accept.mjs +248 -0
  71. package/skill/scripts/live/svelte-component-css.mjs +230 -0
  72. package/skill/scripts/live/svelte-component-markup.mjs +104 -0
  73. package/skill/scripts/live/svelte-component-scaffold.mjs +118 -0
  74. package/skill/scripts/live/svelte-component-session.mjs +158 -0
  75. package/skill/scripts/live/svelte-component.mjs +32 -792
  76. package/skill/scripts/live-accept-mutate.mjs +152 -0
  77. package/skill/scripts/live-accept-parse.mjs +370 -0
  78. package/skill/scripts/live-accept-scrub.mjs +59 -0
  79. package/skill/scripts/live-accept-search.mjs +58 -0
  80. package/skill/scripts/live-accept.mjs +15 -631
  81. package/skill/scripts/live-commit-manual-edits-paths.mjs +27 -0
  82. package/skill/scripts/live-commit-manual-edits-repair.mjs +166 -0
  83. package/skill/scripts/live-commit-manual-edits-rollback.mjs +231 -0
  84. package/skill/scripts/live-commit-manual-edits-utils.mjs +167 -0
  85. package/skill/scripts/live-commit-manual-edits-verify.mjs +356 -0
  86. package/skill/scripts/live-commit-manual-edits.mjs +24 -881
  87. package/skill/scripts/live-copy-edit-agent.mjs +16 -551
  88. package/skill/scripts/live-copy-edit-compact.mjs +137 -0
  89. package/skill/scripts/live-copy-edit-post-apply.mjs +175 -0
  90. package/skill/scripts/live-copy-edit-runners.mjs +297 -0
  91. package/skill/scripts/live-inject-csp.mjs +132 -0
  92. package/skill/scripts/live-inject-files.mjs +229 -0
  93. package/skill/scripts/live-inject-tag.mjs +114 -0
  94. package/skill/scripts/live-inject.mjs +13 -440
  95. package/skill/scripts/live-server-poll.mjs +232 -0
  96. package/skill/scripts/live-server-routes.mjs +449 -0
  97. package/skill/scripts/live-server-state.mjs +361 -0
  98. package/skill/scripts/live-server.mjs +10 -946
  99. package/skill/scripts/live-wrap-css.mjs +132 -0
  100. package/skill/scripts/live-wrap-manual-edit.mjs +153 -0
  101. package/skill/scripts/live-wrap-search.mjs +247 -0
  102. package/skill/scripts/live-wrap.mjs +21 -484
  103. package/skill/scripts/palette-seeds.mjs +401 -0
  104. package/skill/scripts/palette.mjs +1 -395
@@ -0,0 +1,393 @@
1
+ // Static-HTML CSS cascade engine: value/declaration parsing helpers. Split
2
+ // out of css-cascade.mjs (file-size sweep — pure move, no behaviour change).
3
+
4
+ import { parseAnyColor, resolveLengthPx, resolveVarRefs } from '../../rules/checks.mjs';
5
+ import { STATIC_INHERITED_PROPS, STATIC_DEFAULT_STYLE, STATIC_PROP_MAP, STATIC_NAMED_COLORS } from './css-cascade-static-data.mjs';
6
+
7
+ function splitCssList(value) {
8
+ const parts = [];
9
+ let depth = 0, quote = '', start = 0;
10
+ for (let i = 0; i < value.length; i++) {
11
+ const ch = value[i];
12
+ if (quote) {
13
+ if (ch === quote && value[i - 1] !== '\\') quote = '';
14
+ continue;
15
+ }
16
+ if (ch === '"' || ch === "'") { quote = ch; continue; }
17
+ if (ch === '(' || ch === '[') depth++;
18
+ else if (ch === ')' || ch === ']') depth = Math.max(0, depth - 1);
19
+ else if (ch === ',' && depth === 0) {
20
+ parts.push(value.slice(start, i).trim());
21
+ start = i + 1;
22
+ }
23
+ }
24
+ const tail = value.slice(start).trim();
25
+ if (tail) parts.push(tail);
26
+ return parts;
27
+ }
28
+
29
+ function splitCssTokens(value) {
30
+ const tokens = [];
31
+ let depth = 0, quote = '', current = '';
32
+ for (let i = 0; i < value.length; i++) {
33
+ const ch = value[i];
34
+ if (quote) {
35
+ current += ch;
36
+ if (ch === quote && value[i - 1] !== '\\') quote = '';
37
+ continue;
38
+ }
39
+ if (ch === '"' || ch === "'") { quote = ch; current += ch; continue; }
40
+ if (ch === '(') { depth++; current += ch; continue; }
41
+ if (ch === ')') { depth = Math.max(0, depth - 1); current += ch; continue; }
42
+ if (/\s/.test(ch) && depth === 0) {
43
+ if (current) { tokens.push(current); current = ''; }
44
+ continue;
45
+ }
46
+ current += ch;
47
+ }
48
+ if (current) tokens.push(current);
49
+ return tokens;
50
+ }
51
+
52
+ function cssPropToCamel(prop) {
53
+ if (!prop) return prop;
54
+ const mapped = STATIC_PROP_MAP[prop];
55
+ if (mapped) return mapped;
56
+ return prop.replace(/-([a-z])/g, (_m, ch) => ch.toUpperCase());
57
+ }
58
+
59
+ function staticColorToCss(c) {
60
+ if (!c) return '';
61
+ if (c.a != null && c.a < 1) return `rgba(${c.r}, ${c.g}, ${c.b}, ${Number(c.a.toFixed(3))})`;
62
+ return `rgb(${c.r}, ${c.g}, ${c.b})`;
63
+ }
64
+
65
+ function parseStaticColor(value) {
66
+ const parsed = parseAnyColor(value);
67
+ if (parsed) return parsed;
68
+ const named = STATIC_NAMED_COLORS[String(value || '').trim().toLowerCase()];
69
+ return named ? { ...named } : null;
70
+ }
71
+
72
+ function extractStaticColor(value) {
73
+ if (!value) return '';
74
+ const raw = String(value).trim();
75
+ if (/^var\(/i.test(raw)) return raw;
76
+ const colorLike = raw.match(/(?:rgba?\([^)]+\)|oklch\([^)]+\)|oklab\([^)]+\)|lch\([^)]+\)|lab\([^)]+\)|hsla?\([^)]+\)|hwb\([^)]+\)|#[0-9a-f]{3,8}\b|\b(?:black|white|gray|grey|silver|red|green|blue|transparent)\b)/i);
77
+ if (!colorLike) return '';
78
+ return colorLike[0];
79
+ }
80
+
81
+ function normalizeStaticCssValue(prop, value, customProps, parentStyle, currentStyle = null) {
82
+ let resolved = resolveVarRefs(String(value || '').trim(), customProps);
83
+ if (resolved === 'inherit') return parentStyle?.[prop] || STATIC_DEFAULT_STYLE[prop] || '';
84
+ const isModernBorderColor = /^border[A-Z][a-z]+Color$/.test(prop) && /^(?:oklch|oklab|lch|lab|hsl|hwb)\(/i.test(resolved);
85
+ if (!isModernBorderColor && (/color$/i.test(prop) || prop === 'color' || prop === 'backgroundColor')) {
86
+ const parsed = parseStaticColor(resolved);
87
+ if (parsed) resolved = staticColorToCss(parsed);
88
+ }
89
+ if (prop === 'fontSize') {
90
+ const base = parseFloat(parentStyle?.fontSize) || 16;
91
+ const px = resolveLengthPx(resolved, base);
92
+ if (px != null) resolved = `${px}px`;
93
+ }
94
+ if (prop === 'letterSpacing') {
95
+ const base = parseFloat(currentStyle?.fontSize || parentStyle?.fontSize) || 16;
96
+ const px = resolveLengthPx(resolved, base);
97
+ if (px != null) resolved = `${px}px`;
98
+ }
99
+ if (prop === 'lineHeight' && resolved !== 'normal') {
100
+ const base = parseFloat(currentStyle?.fontSize || parentStyle?.fontSize) || 16;
101
+ const px = resolveLengthPx(resolved, base);
102
+ if (px != null) resolved = `${px}px`;
103
+ }
104
+ return resolved;
105
+ }
106
+
107
+ function expandStaticBoxValues(tokens) {
108
+ if (tokens.length === 0) return ['0px', '0px', '0px', '0px'];
109
+ if (tokens.length === 1) return [tokens[0], tokens[0], tokens[0], tokens[0]];
110
+ if (tokens.length === 2) return [tokens[0], tokens[1], tokens[0], tokens[1]];
111
+ if (tokens.length === 3) return [tokens[0], tokens[1], tokens[2], tokens[1]];
112
+ return [tokens[0], tokens[1], tokens[2], tokens[3]];
113
+ }
114
+
115
+ function parseStaticBorder(value) {
116
+ const tokens = splitCssTokens(value);
117
+ let width = '', color = '';
118
+ for (const token of tokens) {
119
+ if (!width && /^-?[\d.]+(?:px|rem|em|%)$/.test(token)) width = token;
120
+ if (!color) color = extractStaticColor(token);
121
+ }
122
+ return { width, color };
123
+ }
124
+
125
+ function parseStaticFont(value) {
126
+ const out = [];
127
+ const slashParts = value.match(/(?:^|\s)([\d.]+(?:px|rem|em|%))(?:\/([^\s]+))?/);
128
+ if (/\bitalic\b/i.test(value)) out.push(['fontStyle', 'italic']);
129
+ const weight = value.match(/\b([1-9]00|bold|normal|lighter|bolder)\b/i);
130
+ if (weight) out.push(['fontWeight', weight[1]]);
131
+ if (slashParts) {
132
+ out.push(['fontSize', slashParts[1]]);
133
+ if (slashParts[2]) out.push(['lineHeight', slashParts[2]]);
134
+ const familyStart = value.indexOf(slashParts[0]) + slashParts[0].length;
135
+ const family = value.slice(familyStart).trim();
136
+ if (family) out.push(['fontFamily', family]);
137
+ }
138
+ return out;
139
+ }
140
+
141
+ function parseStaticTransition(value) {
142
+ const props = [];
143
+ const timings = [];
144
+ for (const item of splitCssList(value)) {
145
+ const tokens = splitCssTokens(item);
146
+ const timing = tokens.find(token => /^(?:ease|linear|step-|cubic-bezier\()/i.test(token));
147
+ if (timing) timings.push(timing);
148
+ const prop = tokens.find(token => /^[a-z-]+$/i.test(token) && !/^(?:ease|linear|infinite|alternate|forwards|backwards|both|normal|none)$/.test(token) && !/s$/.test(token));
149
+ if (prop) props.push(prop);
150
+ }
151
+ return {
152
+ property: props.join(', '),
153
+ timing: timings.join(', '),
154
+ };
155
+ }
156
+
157
+ function parseStaticAnimation(value) {
158
+ const names = [];
159
+ const timings = [];
160
+ for (const item of splitCssList(value)) {
161
+ const tokens = splitCssTokens(item);
162
+ const timing = tokens.find(token => /^(?:ease|linear|step-|cubic-bezier\()/i.test(token));
163
+ if (timing) timings.push(timing);
164
+ const name = tokens.find(token =>
165
+ /^[a-z_-][\w-]*$/i.test(token) &&
166
+ !/^(?:ease|linear|infinite|alternate|forwards|backwards|both|normal|none|running|paused)$/.test(token)
167
+ );
168
+ if (name) names.push(name);
169
+ }
170
+ return {
171
+ name: names.join(', '),
172
+ timing: timings.join(', '),
173
+ };
174
+ }
175
+
176
+ function expandStaticDeclaration(prop, value) {
177
+ const p = prop.toLowerCase();
178
+ const v = String(value || '').trim();
179
+ if (!v) return [];
180
+ if (p.startsWith('--')) return [[p, v]];
181
+ if (p === 'background') {
182
+ const out = [];
183
+ const hasImage = /gradient|url\(/i.test(v);
184
+ if (hasImage) out.push(['backgroundImage', v]);
185
+ const beforeImage = hasImage ? v.split(/(?:repeating-)?(?:linear|radial|conic)-gradient\(|url\(/i)[0] : v;
186
+ const color = extractStaticColor(hasImage ? beforeImage : v);
187
+ if (color) out.push(['backgroundColor', color]);
188
+ return out;
189
+ }
190
+ if (p === 'border') {
191
+ const parsed = parseStaticBorder(v);
192
+ const out = [];
193
+ for (const side of ['Top', 'Right', 'Bottom', 'Left']) {
194
+ if (parsed.width) out.push([`border${side}Width`, parsed.width]);
195
+ if (parsed.color) out.push([`border${side}Color`, parsed.color]);
196
+ }
197
+ return out;
198
+ }
199
+ if (p === 'outline') {
200
+ // `outline` shorthand: width | style | color, in any order. Reuse the
201
+ // border parser for width + color, then sniff a style keyword from the
202
+ // tokens (solid|dashed|...). `outline: 0` (single-token zero) zeros
203
+ // the width and effectively hides the outline.
204
+ const tokens = splitCssTokens(v);
205
+ const parsed = parseStaticBorder(v);
206
+ const styleToken = tokens.find(t =>
207
+ /^(none|hidden|solid|dashed|dotted|double|groove|ridge|inset|outset)$/i.test(t)
208
+ );
209
+ const out = [];
210
+ if (parsed.width) out.push(['outlineWidth', parsed.width]);
211
+ if (parsed.color) out.push(['outlineColor', parsed.color]);
212
+ if (styleToken) out.push(['outlineStyle', styleToken.toLowerCase()]);
213
+ // `outline: 0` with no other tokens: explicit zero width.
214
+ if (!parsed.width && /^0(?:px|rem|em|%)?$/.test(v.trim())) {
215
+ out.push(['outlineWidth', '0px']);
216
+ }
217
+ return out;
218
+ }
219
+ const sideMatch = p.match(/^border-(top|right|bottom|left)$/);
220
+ if (sideMatch) {
221
+ const parsed = parseStaticBorder(v);
222
+ const side = sideMatch[1][0].toUpperCase() + sideMatch[1].slice(1);
223
+ return [
224
+ ...(parsed.width ? [[`border${side}Width`, parsed.width]] : []),
225
+ ...(parsed.color ? [[`border${side}Color`, parsed.color]] : []),
226
+ ];
227
+ }
228
+ if (p === 'border-width') {
229
+ const vals = expandStaticBoxValues(splitCssTokens(v));
230
+ return [
231
+ ['borderTopWidth', vals[0]],
232
+ ['borderRightWidth', vals[1]],
233
+ ['borderBottomWidth', vals[2]],
234
+ ['borderLeftWidth', vals[3]],
235
+ ];
236
+ }
237
+ if (p === 'border-color') {
238
+ const vals = expandStaticBoxValues(splitCssTokens(v));
239
+ return [
240
+ ['borderTopColor', vals[0]],
241
+ ['borderRightColor', vals[1]],
242
+ ['borderBottomColor', vals[2]],
243
+ ['borderLeftColor', vals[3]],
244
+ ];
245
+ }
246
+ if (p === 'padding') {
247
+ const vals = expandStaticBoxValues(splitCssTokens(v));
248
+ return [
249
+ ['paddingTop', vals[0]],
250
+ ['paddingRight', vals[1]],
251
+ ['paddingBottom', vals[2]],
252
+ ['paddingLeft', vals[3]],
253
+ ];
254
+ }
255
+ if (p === 'margin') {
256
+ const vals = expandStaticBoxValues(splitCssTokens(v));
257
+ return [
258
+ ['marginTop', vals[0]],
259
+ ['marginRight', vals[1]],
260
+ ['marginBottom', vals[2]],
261
+ ['marginLeft', vals[3]],
262
+ ];
263
+ }
264
+ if (p === 'font') return parseStaticFont(v);
265
+ if (p === 'transition') {
266
+ const parsed = parseStaticTransition(v);
267
+ return [
268
+ ...(parsed.property ? [['transitionProperty', parsed.property]] : []),
269
+ ...(parsed.timing ? [['transitionTimingFunction', parsed.timing]] : []),
270
+ ];
271
+ }
272
+ if (p === 'animation') {
273
+ const parsed = parseStaticAnimation(v);
274
+ return [
275
+ ...(parsed.name ? [['animationName', parsed.name]] : []),
276
+ ...(parsed.timing ? [['animationTimingFunction', parsed.timing]] : []),
277
+ ];
278
+ }
279
+ const mapped = cssPropToCamel(p);
280
+ if (STATIC_DEFAULT_STYLE[mapped] != null || STATIC_INHERITED_PROPS.has(mapped)) {
281
+ return [[mapped, v]];
282
+ }
283
+ return [];
284
+ }
285
+
286
+ function compareStaticPriority(a, b) {
287
+ if (!a) return true;
288
+ if (!!b.important !== !!a.important) return !!b.important;
289
+ if (!!b.inline !== !!a.inline) return !!b.inline;
290
+ for (let i = 0; i < 3; i++) {
291
+ if ((b.specificity[i] || 0) !== (a.specificity[i] || 0)) {
292
+ return (b.specificity[i] || 0) > (a.specificity[i] || 0);
293
+ }
294
+ }
295
+ return b.order >= a.order;
296
+ }
297
+
298
+ function staticSpecificity(selector) {
299
+ const noWhere = selector.replace(/:where\([^)]*\)/g, '');
300
+ const ids = (noWhere.match(/#[\w-]+/g) || []).length;
301
+ const classes = (noWhere.match(/\.[\w-]+|\[[^\]]+\]|:(?!:)[\w-]+(?:\([^)]*\))?/g) || []).length;
302
+ const stripped = noWhere
303
+ .replace(/#[\w-]+/g, ' ')
304
+ .replace(/\.[\w-]+|\[[^\]]+\]|:{1,2}[\w-]+(?:\([^)]*\))?/g, ' ')
305
+ .replace(/[*>+~(),]/g, ' ');
306
+ const types = (stripped.match(/\b[a-zA-Z][\w-]*\b/g) || []).length;
307
+ return [ids, classes, types];
308
+ }
309
+
310
+ function applyStaticDeclaration(specified, node, prop, value, meta) {
311
+ let map = specified.get(node);
312
+ if (!map) { map = new Map(); specified.set(node, map); }
313
+ for (const [expandedProp, expandedValue] of expandStaticDeclaration(prop, value)) {
314
+ const existing = map.get(expandedProp);
315
+ const next = { ...meta, prop: expandedProp, value: expandedValue };
316
+ if (compareStaticPriority(existing, next)) map.set(expandedProp, next);
317
+ }
318
+ }
319
+
320
+ function parseStaticStyleAttribute(styleText, orderBase = 0) {
321
+ const decls = [];
322
+ for (const part of String(styleText || '').split(';')) {
323
+ const idx = part.indexOf(':');
324
+ if (idx <= 0) continue;
325
+ const prop = part.slice(0, idx).trim();
326
+ let value = part.slice(idx + 1).trim();
327
+ const important = /!important\s*$/i.test(value);
328
+ value = value.replace(/\s*!important\s*$/i, '').trim();
329
+ decls.push({ prop, value, important, order: orderBase + decls.length });
330
+ }
331
+ return decls;
332
+ }
333
+
334
+ function collectStaticCssRules(cssText, csstree) {
335
+ const rules = [];
336
+ let ast;
337
+ try {
338
+ ast = csstree.parse(cssText, { positions: false, parseValue: true, parseCustomProperty: false });
339
+ } catch {
340
+ return rules;
341
+ }
342
+ let order = 0;
343
+ const walkList = (list, atRuleStack = []) => {
344
+ list?.forEach?.(node => {
345
+ if (node.type === 'Rule' && node.block) {
346
+ if (atRuleStack.some(name => /keyframes$/i.test(name))) return;
347
+ const selectorText = csstree.generate(node.prelude).trim();
348
+ const declarations = [];
349
+ node.block.children?.forEach?.(child => {
350
+ if (child.type !== 'Declaration') return;
351
+ declarations.push({
352
+ prop: child.property,
353
+ value: csstree.generate(child.value).trim(),
354
+ important: !!child.important,
355
+ });
356
+ });
357
+ for (const selector of splitCssList(selectorText)) {
358
+ if (selector) rules.push({ selector, declarations, specificity: staticSpecificity(selector), order: order++ });
359
+ }
360
+ return;
361
+ }
362
+ if (node.type === 'Atrule' && node.block) {
363
+ const name = String(node.name || '').toLowerCase();
364
+ if (name === 'media' || name === 'supports' || name === 'layer') {
365
+ walkList(node.block.children, [...atRuleStack, name]);
366
+ }
367
+ }
368
+ });
369
+ };
370
+ walkList(ast.children);
371
+ return rules;
372
+ }
373
+
374
+ export {
375
+ splitCssList,
376
+ splitCssTokens,
377
+ cssPropToCamel,
378
+ staticColorToCss,
379
+ parseStaticColor,
380
+ extractStaticColor,
381
+ normalizeStaticCssValue,
382
+ expandStaticBoxValues,
383
+ parseStaticBorder,
384
+ parseStaticFont,
385
+ parseStaticTransition,
386
+ parseStaticAnimation,
387
+ expandStaticDeclaration,
388
+ compareStaticPriority,
389
+ staticSpecificity,
390
+ applyStaticDeclaration,
391
+ parseStaticStyleAttribute,
392
+ collectStaticCssRules,
393
+ };