1
- import { readFile , mkdir , writeFile } from ' node:fs/promises' ;
2
- import { createReadStream , existsSync } from ' node:fs' ;
3
- import { join , dirname } from ' node:path' ;
4
- import tailwind from ' tailwindcss' ;
5
- import resolveConfig from ' tailwindcss/resolveConfig.js' ;
6
- import postcss from ' postcss' ;
7
- import autoprefixer from ' autoprefixer' ;
8
- import cssnano from ' cssnano' ;
9
- import Yaml from ' yaml' ;
10
- import { defaultPlugins , allPlugins } from ' ./constants.mjs' ;
1
+ import { readFile , mkdir , writeFile } from " node:fs/promises" ;
2
+ import { createReadStream , existsSync } from " node:fs" ;
3
+ import { join , dirname } from " node:path" ;
4
+ import tailwind from " tailwindcss" ;
5
+ import resolveConfig from " tailwindcss/resolveConfig.js" ;
6
+ import postcss from " postcss" ;
7
+ import autoprefixer from " autoprefixer" ;
8
+ import cssnano from " cssnano" ;
9
+ import Yaml from " yaml" ;
10
+ import { defaultPlugins , allPlugins } from " ./constants.mjs" ;
11
11
12
12
const CWD = process . cwd ( ) ;
13
- const getPresetPath = ( name ) => join ( CWD , 'systems' , name + '.yml' ) ;
13
+ const getPresetPath = ( name ) => join ( CWD , "systems" , name + ".yml" ) ;
14
+ const each = ( v ) => ( ! v ? [ ] : Object . entries ( v ) ) ;
14
15
15
16
function generateComponentParts ( name , def , separator ) {
16
- return ! def ? [ ] : Object . entries ( def ) . map ( ( [ part , classes ] ) => `.${ name } ${ separator } ${ part } {\n @apply ${ classes } ;\n}\n` ) ;
17
+ return each ( def ) . map ( ( [ part , c ] ) => [ `.${ name } ${ separator } ${ part } ` , c ] ) ;
17
18
}
18
19
19
- function generateShadowComponentParts ( name , def ) {
20
- return ! def ? [ ] : Object . entries ( def ) . map ( ( [ part , classes ] ) => `${ name } ::part(${ part } ) {\n @apply ${ classes } ;\n}\n` ) ;
20
+ function generateShadowComponentParts ( name , parts ) {
21
+ return each ( parts ) . map ( ( [ part , c ] ) => [ `${ name } ::part(${ part } )` , c ] ) ;
21
22
}
22
23
23
24
function generateShadowComponentStates ( name , def ) {
24
- return ! def ? [ ] : Object . entries ( def ) . map ( ( [ part , classes ] ) => `${ name } ::part(component):${ part } {\n @apply ${ classes } ;\n}\n` ) ;
25
+ return each ( def ) . map ( ( [ part , c ] ) => [ `${ name } ::part(component):${ part } ` , c ] ) ;
25
26
}
26
27
27
- function defineComponent ( name , def , useShadowDom ) {
28
- if ( useShadowDom ) {
29
- return [
30
- `${ name } ::part(component) {\n${ ( def . apply && ' @apply ' + def . apply + ';\n' ) || '' } }\n` ,
31
- generateShadowComponentParts ( name , def . parts ) ,
32
- generateShadowComponentStates ( name , def . states ) ,
33
- ]
34
- . flat ( )
35
- . join ( '' ) ;
36
- }
28
+ function generateShadowComponentVariants ( name , variants ) {
29
+ return each ( variants ) . map (
30
+ ( [ variant , classes ] ) =>
31
+ `.${ name } .${ name } -${ variant } ::part(component) {\n @apply ${ classes } ;\n}\n`
32
+ ) ;
33
+ }
37
34
38
- return [
39
- `.${ name } {\n${ ( def . apply && ' @apply ' + def . apply + ';\n' ) || '' } }\n` ,
40
- generateComponentParts ( name , def . parts , '__' ) ,
41
- generateComponentParts ( name , def . modifiers , '--' ) ,
42
- generateComponentParts ( name , def . variants , '-' ) ,
43
- generateComponentParts ( name , def . states , ':' ) ,
44
- ]
45
- . flat ( )
46
- . join ( '' ) ;
35
+ function generateComponent ( name , def , prefix = "" ) {
36
+ return ! def ? [ ] : [ `${ prefix } ${ name } ::part(component)` , def . apply ] ;
37
+ }
38
+
39
+ function defineComponent ( name , def , useShadowDom ) {
40
+ const all = useShadowDom
41
+ ? [
42
+ generateComponent ( name , def . apply ) ,
43
+ generateShadowComponentParts ( name , def . parts ) ,
44
+ generateShadowComponentStates ( name , def . states ) ,
45
+ generateShadowComponentVariants ( name , def . variants , "-" ) ,
46
+ ]
47
+ : [
48
+ generateComponent ( name , def . apply , "." ) ,
49
+ generateComponentParts ( name , def . parts , "__" ) ,
50
+ generateComponentParts ( name , def . modifiers , "--" ) ,
51
+ generateComponentParts ( name , def . variants , "-" ) ,
52
+ generateComponentParts ( name , def . states , ":" ) ,
53
+ ] ;
54
+
55
+ return all
56
+ . flatMap ( ( item ) => item [ 0 ] + `{\n @apply ${ item [ 1 ] } ;\n}\n` )
57
+ . join ( "" ) ;
47
58
}
48
59
49
60
function generateCssSafelist ( presets ) {
50
61
const classes = [ ] ;
51
62
52
- presets . forEach ( next => {
53
- if ( ! ( next . components && typeof next . components === ' object' ) ) return ;
63
+ presets . forEach ( ( next ) => {
64
+ if ( ! ( next . components && typeof next . components === " object" ) ) return ;
54
65
55
66
Object . entries ( next . components ) . forEach ( ( [ name , def ] ) => {
56
67
classes . push ( name ) ;
57
68
58
69
if ( def . parts ) {
59
- classes . push ( ...Object . keys ( def . parts ) . map ( key => name + '__' + key ) ) ;
70
+ classes . push ( ...Object . keys ( def . parts ) . map ( ( key ) => name + "__" + key ) ) ;
60
71
}
61
72
62
73
if ( def . modifiers ) {
63
- classes . push ( ...Object . keys ( def . modifiers ) . map ( key => name + '--' + key ) ) ;
74
+ classes . push (
75
+ ...Object . keys ( def . modifiers ) . map ( ( key ) => name + "--" + key )
76
+ ) ;
64
77
}
65
78
66
79
if ( def . variants ) {
67
- classes . push ( ...Object . keys ( def . variants ) . map ( key => name + '-' + key ) ) ;
80
+ classes . push (
81
+ ...Object . keys ( def . variants ) . map ( ( key ) => name + "-" + key )
82
+ ) ;
68
83
}
69
84
} ) ;
70
85
} ) ;
@@ -84,7 +99,7 @@ function generateCssTemplate(presets, useShadowDom) {
84
99
chain . variables = Object . assign ( { } , chain . variables , next . variables ) ;
85
100
}
86
101
87
- if ( next . components && typeof next . components === ' object' ) {
102
+ if ( next . components && typeof next . components === " object" ) {
88
103
Object . assign ( chain , next . components ) ;
89
104
}
90
105
@@ -99,8 +114,12 @@ function generateCssTemplate(presets, useShadowDom) {
99
114
return chain ;
100
115
} , { } ) ;
101
116
102
- const components = Object . entries ( chain ) . map ( ( [ name , def ] ) => defineComponent ( name , def , useShadowDom ) ) . join ( '' ) ;
103
- const allVariables = Object . entries ( variables ) . map ( ( [ key , value ] ) => `--${ key } : ${ value } ;` ) . join ( '\n' ) ;
117
+ const components = Object . entries ( chain )
118
+ . map ( ( [ name , def ] ) => defineComponent ( name , def , useShadowDom ) )
119
+ . join ( "" ) ;
120
+ const allVariables = Object . entries ( variables )
121
+ . map ( ( [ key , value ] ) => `--${ key } : ${ value } ;` )
122
+ . join ( "\n" ) ;
104
123
const css = `:root{
105
124
${ allVariables }
106
125
}
@@ -112,7 +131,7 @@ function generateCssTemplate(presets, useShadowDom) {
112
131
${ components }
113
132
}
114
133
115
- ${ styles . join ( '' ) }
134
+ ${ styles . join ( "" ) }
116
135
` ;
117
136
118
137
return css ;
@@ -130,7 +149,9 @@ export async function generatePreset(input) {
130
149
}
131
150
132
151
const allPresets = [ ...presetChain , input ] ;
133
- const pluginChain = allPresets . flatMap ( p => transformPlugins ( p . corePlugins ) ) . filter ( Boolean ) ;
152
+ const pluginChain = allPresets
153
+ . flatMap ( ( p ) => transformPlugins ( p . corePlugins ) )
154
+ . filter ( Boolean ) ;
134
155
const resolvedPlugins = [ ...new Set ( pluginChain ) ] ;
135
156
136
157
if ( resolvedPlugins . length ) {
@@ -142,34 +163,44 @@ export async function generatePreset(input) {
142
163
if ( input . autoPurge ) {
143
164
tailwindConfig . purge = {
144
165
enabled : true ,
145
- content : [ ' *.xyz' ] ,
166
+ content : [ " *.xyz" ] ,
146
167
safelist : generateCssSafelist ( allPresets ) ,
147
168
} ;
148
169
}
149
170
150
171
const json = JSON . stringify ( tailwindConfig , null , 2 ) ;
151
- const cssTemplate = generateCssTemplate ( allPresets , ( input . shadowDom || input [ 'shadow-dom' ] ) ) ;
152
- const plugins = [ tailwind ( tailwindConfig ) , autoprefixer ( ) , input . minify && cssnano ( ) ] . filter ( Boolean ) ;
172
+ const cssTemplate = generateCssTemplate (
173
+ allPresets ,
174
+ input . shadowDom || input [ "shadow-dom" ]
175
+ ) ;
176
+ const plugins = [
177
+ tailwind ( tailwindConfig ) ,
178
+ autoprefixer ( ) ,
179
+ input . minify && cssnano ( ) ,
180
+ ] . filter ( Boolean ) ;
153
181
const processor = postcss ( ...plugins ) ;
154
182
155
183
try {
156
- const output = await processor . process ( cssTemplate , { from : '/web-design-system.css' , to : '/index.css' } ) ;
184
+ const output = await processor . process ( cssTemplate , {
185
+ from : "/web-design-system.css" ,
186
+ to : "/index.css" ,
187
+ } ) ;
157
188
const { css } = output ;
158
189
159
190
return { error : null , css, json } ;
160
191
} catch ( error ) {
161
- return { error, css : '' , json } ;
192
+ return { error, css : "" , json } ;
162
193
}
163
194
}
164
195
165
196
export async function readPreset ( name ) {
166
197
const path = getPresetPath ( name ) ;
167
198
168
199
if ( ! existsSync ( path ) ) {
169
- return '' ;
200
+ return "" ;
170
201
}
171
202
172
- return await readFile ( path , ' utf-8' ) ;
203
+ return await readFile ( path , " utf-8" ) ;
173
204
}
174
205
175
206
/**
@@ -188,7 +219,7 @@ export async function loadPreset(name) {
188
219
export async function loadPresetChain ( nameOrPreset , presets = [ ] ) {
189
220
let preset = nameOrPreset ;
190
221
191
- if ( typeof nameOrPreset === ' string' ) {
222
+ if ( typeof nameOrPreset === " string" ) {
192
223
preset = await loadPreset ( nameOrPreset ) ;
193
224
}
194
225
@@ -197,7 +228,10 @@ export async function loadPresetChain(nameOrPreset, presets = []) {
197
228
}
198
229
199
230
if ( preset . extends ) {
200
- const extensions = typeof preset . extends === 'string' ? [ preset . extends ] : preset . extends || [ ] ;
231
+ const extensions =
232
+ typeof preset . extends === "string"
233
+ ? [ preset . extends ]
234
+ : preset . extends || [ ] ;
201
235
202
236
for ( const extension of extensions . reverse ( ) ) {
203
237
const next = await loadPreset ( extension ) ;
@@ -215,19 +249,19 @@ export async function loadPresetChain(nameOrPreset, presets = []) {
215
249
export async function savePreset ( name , preset ) {
216
250
const path = getPresetPath ( name ) ;
217
251
await ensureFolder ( dirname ( path ) ) ;
218
- await writeFile ( path , preset , ' utf-8' ) ;
252
+ await writeFile ( path , preset , " utf-8" ) ;
219
253
}
220
254
221
255
export async function savePresetAssets ( name , preset ) {
222
256
const { json, css } = preset ;
223
- const basePath = join ( CWD , ' presets' , name ) ;
257
+ const basePath = join ( CWD , " presets" , name ) ;
224
258
await ensureFolder ( dirname ( basePath ) ) ;
225
- await writeFile ( basePath + ' .mjs' , ' export default ' + json ) ;
226
- await writeFile ( basePath + ' .css' , css ) ;
259
+ await writeFile ( basePath + " .mjs" , " export default " + json ) ;
260
+ await writeFile ( basePath + " .css" , css ) ;
227
261
}
228
262
229
263
export function loadPresetAsset ( name ) {
230
- const path = join ( CWD , ' presets' , name ) ;
264
+ const path = join ( CWD , " presets" , name ) ;
231
265
232
266
if ( existsSync ( path ) ) {
233
267
return createReadStream ( path ) ;
@@ -240,15 +274,15 @@ export function loadPresetAsset(name) {
240
274
* @returns {string[] } plugins after transforming the keywords
241
275
*/
242
276
export function transformPlugins ( plugins ) {
243
- if ( plugins === ' all' ) {
277
+ if ( plugins === " all" ) {
244
278
return allPlugins ;
245
279
}
246
280
247
- if ( plugins === ' none' ) {
281
+ if ( plugins === " none" ) {
248
282
return [ ] ;
249
283
}
250
284
251
- if ( plugins === ' default' ) {
285
+ if ( plugins === " default" ) {
252
286
plugins = defaultPlugins ;
253
287
}
254
288
@@ -257,7 +291,7 @@ export function transformPlugins(plugins) {
257
291
}
258
292
259
293
return plugins . flatMap ( ( next ) => {
260
- if ( next . endsWith ( '*' ) ) {
294
+ if ( next . endsWith ( "*" ) ) {
261
295
const stem = next . slice ( 0 , - 1 ) ;
262
296
return allPlugins . filter ( ( p ) => p . startsWith ( stem ) ) ;
263
297
}
0 commit comments