esm-styles 0.2.3 → 0.2.4

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 (2) hide show
  1. package/dist/lib/index.js +95 -17
  2. package/package.json +1 -1
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as utils from './utils/index.js';
2
2
  import { toCssValue } from './utils/to-css-value.js';
3
- function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layers: {} }, options = {}, currentMedia = []) {
3
+ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layers: {}, containers: {} }, options = {}, currentMedia = [], currentContainers = []) {
4
4
  const props = {};
5
5
  for (const key in obj) {
6
6
  const value = obj[key];
@@ -16,7 +16,7 @@ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layer
16
16
  else if (typeof value === 'object' && value !== null) {
17
17
  if (key.startsWith('@media ')) {
18
18
  // Recursively walk value, collecting rules for this media block
19
- const nested = flatWalk(value, selectorPath, { rules: [], media: {}, layers: {} }, options, [...currentMedia, key]);
19
+ const nested = flatWalk(value, selectorPath, { rules: [], media: {}, layers: {}, containers: {} }, options, [...currentMedia, key], currentContainers);
20
20
  const mediaKey = [...currentMedia, key].join(' && ');
21
21
  if (!result.media[mediaKey])
22
22
  result.media[mediaKey] = [];
@@ -27,11 +27,42 @@ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layer
27
27
  result.media[nestedMediaKey] = [];
28
28
  result.media[nestedMediaKey].push(...nested.media[nestedMediaKey]);
29
29
  }
30
+ // Merge nested containers
31
+ for (const nestedContainerKey in nested.containers) {
32
+ if (!result.containers[nestedContainerKey])
33
+ result.containers[nestedContainerKey] = [];
34
+ result.containers[nestedContainerKey].push(...nested.containers[nestedContainerKey]);
35
+ }
36
+ }
37
+ else if (key.startsWith('@container')) {
38
+ // Recursively walk value, collecting rules for this container block
39
+ const nested = flatWalk(value, selectorPath, { rules: [], media: {}, layers: {}, containers: {} }, options, currentMedia, [...currentContainers, key]);
40
+ const containerKey = [...currentContainers, key].join(' && ');
41
+ if (!result.containers[containerKey])
42
+ result.containers[containerKey] = [];
43
+ result.containers[containerKey].push(...nested.rules);
44
+ // Also merge any nested containers
45
+ for (const nestedContainerKey in nested.containers) {
46
+ if (!result.containers[nestedContainerKey])
47
+ result.containers[nestedContainerKey] = [];
48
+ result.containers[nestedContainerKey].push(...nested.containers[nestedContainerKey]);
49
+ }
50
+ // Merge nested media
51
+ for (const nestedMediaKey in nested.media) {
52
+ if (!result.media[nestedMediaKey])
53
+ result.media[nestedMediaKey] = [];
54
+ result.media[nestedMediaKey].push(...nested.media[nestedMediaKey]);
55
+ }
30
56
  }
31
57
  else if (key.startsWith('@layer ')) {
32
58
  if (!result.layers[key])
33
- result.layers[key] = { rules: [], media: {}, layers: {} };
34
- flatWalk(value, selectorPath, result.layers[key], options, currentMedia);
59
+ result.layers[key] = {
60
+ rules: [],
61
+ media: {},
62
+ layers: {},
63
+ containers: {},
64
+ };
65
+ flatWalk(value, selectorPath, result.layers[key], options, currentMedia, currentContainers);
35
66
  }
36
67
  else if (key.startsWith('@')) {
37
68
  // Other special keys (shorthands, etc.)
@@ -39,10 +70,7 @@ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layer
39
70
  let handled = false;
40
71
  if (options.mediaQueries && options.mediaQueries[shorthand]) {
41
72
  const mediaKey = `@media ${options.mediaQueries[shorthand]}`;
42
- flatWalk(value, selectorPath, result, options, [
43
- ...currentMedia,
44
- mediaKey,
45
- ]);
73
+ flatWalk(value, selectorPath, result, options, [...currentMedia, mediaKey], currentContainers);
46
74
  handled = true;
47
75
  }
48
76
  if (options.selectorShorthands &&
@@ -50,20 +78,17 @@ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layer
50
78
  const root = options.globalRootSelector || ':root';
51
79
  for (const entry of options.selectorShorthands[shorthand]) {
52
80
  if (entry.selector && !entry.mediaQuery) {
53
- flatWalk(value, [[root + entry.selector], ...selectorPath], result, options, currentMedia);
81
+ flatWalk(value, [[root + entry.selector], ...selectorPath], result, options, currentMedia, currentContainers);
54
82
  handled = true;
55
83
  }
56
84
  if (entry.selector && entry.mediaQuery) {
57
85
  const mediaKey = `@media ${entry.mediaQuery}`;
58
- flatWalk(value, [[root + entry.selector], ...selectorPath], result, options, [...currentMedia, mediaKey]);
86
+ flatWalk(value, [[root + entry.selector], ...selectorPath], result, options, [...currentMedia, mediaKey], currentContainers);
59
87
  handled = true;
60
88
  }
61
89
  if (!entry.selector && entry.mediaQuery) {
62
90
  const mediaKey = `@media ${entry.mediaQuery}`;
63
- flatWalk(value, selectorPath, result, options, [
64
- ...currentMedia,
65
- mediaKey,
66
- ]);
91
+ flatWalk(value, selectorPath, result, options, [...currentMedia, mediaKey], currentContainers);
67
92
  handled = true;
68
93
  }
69
94
  }
@@ -74,14 +99,14 @@ function flatWalk(obj, selectorPath = [], result = { rules: [], media: {}, layer
74
99
  }
75
100
  else {
76
101
  const parts = key.split(',').map((k) => k.trim());
77
- flatWalk(value, [...selectorPath, parts], result, options, currentMedia);
102
+ flatWalk(value, [...selectorPath, parts], result, options, currentMedia, currentContainers);
78
103
  }
79
104
  }
80
105
  }
81
106
  else {
82
107
  // Always treat as selector segment if not a special key
83
108
  const parts = key.split(',').map((k) => k.trim());
84
- flatWalk(value, [...selectorPath, parts], result, options, currentMedia);
109
+ flatWalk(value, [...selectorPath, parts], result, options, currentMedia, currentContainers);
85
110
  }
86
111
  }
87
112
  }
@@ -184,6 +209,58 @@ function renderFlatMedia(media) {
184
209
  }
185
210
  return css;
186
211
  }
212
+ function renderFlatContainers(containers) {
213
+ let css = '';
214
+ for (const key in containers) {
215
+ // If the key contains '&&', recursively nest the container blocks
216
+ const containerParts = key.split(' && ');
217
+ if (containerParts.length > 1) {
218
+ css += containerParts.reduceRight((inner, part) => `${part} {\n${inner}\n}`, renderFlatContainers({ ['']: containers[key] }));
219
+ }
220
+ else if (key === '') {
221
+ // Render rules directly, no block
222
+ // Group rules by their declarations (stringified)
223
+ const groups = {};
224
+ for (const rule of containers[key]) {
225
+ const declKey = JSON.stringify(rule.declarations);
226
+ if (!groups[declKey])
227
+ groups[declKey] = [];
228
+ groups[declKey].push(rule.selector);
229
+ }
230
+ for (const declKey in groups) {
231
+ const selectors = groups[declKey].join(', ');
232
+ const declarations = JSON.parse(declKey);
233
+ css += `${selectors} {\n`;
234
+ for (const k in declarations) {
235
+ css += ` ${k}: ${declarations[k]};\n`;
236
+ }
237
+ css += '}\n';
238
+ }
239
+ }
240
+ else {
241
+ css += `${key} {\n`;
242
+ // Group rules by their declarations (stringified)
243
+ const groups = {};
244
+ for (const rule of containers[key]) {
245
+ const declKey = JSON.stringify(rule.declarations);
246
+ if (!groups[declKey])
247
+ groups[declKey] = [];
248
+ groups[declKey].push(rule.selector);
249
+ }
250
+ for (const declKey in groups) {
251
+ const selectors = groups[declKey].join(', ');
252
+ const declarations = JSON.parse(declKey);
253
+ css += `${selectors} {\n`;
254
+ for (const k in declarations) {
255
+ css += ` ${k}: ${declarations[k]};\n`;
256
+ }
257
+ css += '}\n';
258
+ }
259
+ css += '}\n';
260
+ }
261
+ }
262
+ return css;
263
+ }
187
264
  function mergeMedia(target, source) {
188
265
  for (const key in source) {
189
266
  if (!target[key])
@@ -192,7 +269,7 @@ function mergeMedia(target, source) {
192
269
  }
193
270
  }
194
271
  export function getCss(styles, options = {}) {
195
- const result = flatWalk(styles, [], { rules: [], media: {}, layers: {} }, options);
272
+ const result = flatWalk(styles, [], { rules: [], media: {}, layers: {}, containers: {} }, options);
196
273
  if (typeof console !== 'undefined') {
197
274
  // console.log(
198
275
  // '[esm-styles] flatWalk result:',
@@ -202,6 +279,7 @@ export function getCss(styles, options = {}) {
202
279
  let css = '';
203
280
  css += renderRules(result.rules);
204
281
  css += renderFlatMedia(result.media);
282
+ css += renderFlatContainers(result.containers);
205
283
  css += renderLayers(result.layers);
206
284
  return utils.prettifyCssString(css);
207
285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esm-styles",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "A library for working with ESM styles",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",