Skip to content

Commit b55b462

Browse files
authored
feat(core): add allLayers option to output all layer names (#5057)
1 parent d53461f commit b55b462

File tree

6 files changed

+96
-8
lines changed

6 files changed

+96
-8
lines changed

docs/config/index.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@ Specifies the name of the CSS layer the internal layer should be output to (can
8888
If `undefined` is return, the internal layer name wil be used as the CSS layer name.
8989
If `null` is return, the internal layer will not be output to a CSS layer.
9090

91+
#### allLayers
92+
93+
- **Type:** `boolean`
94+
95+
Force output all css layers, even if they are not used.
96+
97+
For example:
98+
99+
```css
100+
@layer theme, preflights, [unused-layer], default;
101+
```
102+
91103
### sortLayers
92104

93105
- **Type:** `(layers: string[]) => string[]`

docs/config/layers.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ outputToCssLayers: {
101101
}
102102
```
103103

104+
## Output All CSS Layers
105+
106+
UnoCSS outputs all used CSS layers by default. If you want to force output all defined CSS layers, you can set the `allLayers` option:
107+
108+
<!-- eslint-skip -->
109+
110+
```ts
111+
outputToCssLayers: {
112+
allLayers: true,
113+
}
114+
```
115+
116+
It will output all defined CSS layers, even if they are not used.
117+
118+
```css
119+
@layer theme, preflights, unused-layer, default;
120+
121+
/* generated CSS */
122+
```
123+
104124
## Layers using variants
105125

106126
Layers can be created using variants.

packages-engine/core/src/generator.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,8 @@ class UnoGeneratorInternal<Theme extends object = object> {
292292
)
293293
})()
294294

295-
const layers = this.config.sortLayers(Array
296-
.from(layerSet)
297-
.sort((a, b) => ((this.config.layers[a] ?? 0) - (this.config.layers[b] ?? 0)) || a.localeCompare(b)))
298-
295+
const sortLayers = (layers: string[]) => this.config.sortLayers(layers.sort((a, b) => ((this.config.layers[a] ?? 0) - (this.config.layers[b] ?? 0)) || a.localeCompare(b)))
296+
const layers = sortLayers(Array.from(layerSet))
299297
const layerCache: Record<string, string> = {}
300298
const outputCssLayers = this.config.outputToCssLayers
301299
const getLayerAlias = (layer: string) => {
@@ -395,10 +393,17 @@ class UnoGeneratorInternal<Theme extends object = object> {
395393

396394
const getLayers = (includes = layers, excludes?: string[]) => {
397395
const layers = includes.filter(i => !excludes?.includes(i))
398-
return [
399-
outputCssLayers && layers.length > 0 ? `@layer ${layers.map(getLayerAlias).filter(notNull).join(', ')};` : undefined,
400-
...layers.map(i => getLayer(i) || ''),
401-
].filter(Boolean).join(nl)
396+
const css = layers.map(getLayer).filter(Boolean)
397+
398+
if (outputCssLayers) {
399+
let layerNames = layers
400+
if (typeof outputCssLayers === 'object' && outputCssLayers.allLayers) {
401+
layerNames = sortLayers(Object.keys(this.config.layers))
402+
}
403+
if (layerNames.length > 0)
404+
css.unshift(`@layer ${layerNames.map(getLayerAlias).filter(notNull).join(', ')};`)
405+
}
406+
return css.join(nl)
402407
}
403408

404409
const setLayer = async (layer: string, callback: (content: string) => Promise<string>) => {

packages-engine/core/src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,13 @@ export interface OutputCssLayersOptions {
560560
* Return `null` to specify that the layer should not be output to any css layer.
561561
*/
562562
cssLayerName?: (internalLayer: string) => string | undefined | null
563+
564+
/**
565+
* Force output all css layers, even if they are not used.
566+
*
567+
* @example `@layer theme, preflights, [unused-layer], default;`
568+
*/
569+
allLayers?: boolean
563570
}
564571

565572
export type AutoCompleteTemplate = string

packages-engine/core/test/__snapshots__/use-css-layer.test.ts.snap

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@ exports[`use-css-layer > change layer name 1`] = `
1414
}"
1515
`;
1616

17+
exports[`use-css-layer > output all layers 1`] = `
18+
"@layer a, imports, preflights, shortcuts, default, custom;
19+
/* layer: a */
20+
@layer a{
21+
.a{name:foo;}
22+
}
23+
/* layer: preflights */
24+
@layer preflights{
25+
body { background: red; }
26+
}
27+
/* layer: default */
28+
@layer default{
29+
.c{name:baz;}
30+
}
31+
/* layer: custom */
32+
@layer custom{
33+
.b{name:bar;}
34+
}"
35+
`;
36+
1737
exports[`use-css-layer > static 1`] = `
1838
"@layer shortcuts, a, b, c, d, default, s;
1939
/* layer: shortcuts */

packages-engine/core/test/use-css-layer.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,28 @@ describe('use-css-layer', () => {
4141
const { css } = await uno.generate('w-1 h-1 custom-shortcut', { preflights: false })
4242
expect(css).toMatchSnapshot()
4343
})
44+
45+
it('output all layers', async () => {
46+
const uno = await createGenerator({
47+
rules: [
48+
['a', { name: 'foo' }, { layer: 'a' }],
49+
['b', { name: 'bar' }, { layer: 'custom' }],
50+
['c', { name: 'baz' }],
51+
],
52+
layers: {
53+
a: -300,
54+
custom: 100,
55+
},
56+
outputToCssLayers: {
57+
allLayers: true,
58+
},
59+
preflights: [
60+
{
61+
getCSS: () => `body { background: red; }`,
62+
},
63+
],
64+
})
65+
const { css } = await uno.generate('a b c')
66+
expect(css).toMatchSnapshot()
67+
})
4468
})

0 commit comments

Comments
 (0)