@@ -184,11 +184,24 @@ const brandColorBundle = (
184
184
"/* color variables from _brand.yml */" ,
185
185
'// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml color" }' ,
186
186
] ;
187
+ const colorCssVariables : string [ ] = [
188
+ "/* color CSS variables from _brand.yml */" ,
189
+ '// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml color" }' ,
190
+ ":root {" ,
191
+ ] ;
192
+
193
+ // Create `brand-` prefixed Sass and CSS variables from color.palette
187
194
for ( const colorKey of Object . keys ( brand . data ?. color ?. palette ?? { } ) ) {
195
+ const colorVar = colorKey . replace ( / [ ^ a - z A - Z 0 - 9 _ - ] + / , "-" ) ;
188
196
colorVariables . push (
189
- `$${ colorKey } : ${ brand . getColor ( colorKey ) } !default;` ,
197
+ `$brand- ${ colorVar } : ${ brand . getColor ( colorKey ) } !default;` ,
190
198
) ;
199
+ colorCssVariables . push (
200
+ ` --brand-${ colorVar } : ${ brand . getColor ( colorKey ) } ;` ,
201
+ )
191
202
}
203
+
204
+ // Map theme colors directly to Sass variables
192
205
for ( const colorKey of Object . keys ( brand . data . color ?? { } ) ) {
193
206
if ( colorKey === "palette" ) {
194
207
continue ;
@@ -197,6 +210,7 @@ const brandColorBundle = (
197
210
`$${ colorKey } : ${ brand . getColor ( colorKey ) } !default;` ,
198
211
) ;
199
212
}
213
+
200
214
// format-specific name mapping
201
215
for ( const [ key , value ] of Object . entries ( nameMap ) ) {
202
216
const resolvedValue = brand . getColor ( value ) ;
@@ -208,6 +222,7 @@ const brandColorBundle = (
208
222
}
209
223
// const colorEntries = Object.keys(brand.color);
210
224
colorVariables . push ( '// quarto-scss-analysis-annotation { "action": "pop" }' ) ;
225
+ colorCssVariables . push ( "}" , '// quarto-scss-analysis-annotation { "action": "pop" }' ) ;
211
226
const colorBundle : SassBundleLayers = {
212
227
key,
213
228
// dependency: "bootstrap",
@@ -216,12 +231,91 @@ const brandColorBundle = (
216
231
uses : "" ,
217
232
functions : "" ,
218
233
mixins : "" ,
219
- rules : "" ,
234
+ rules : colorCssVariables . join ( "\n" ) ,
220
235
} ,
221
236
} ;
222
237
return colorBundle ;
223
238
} ;
224
239
240
+ const brandBootstrapBundle = (
241
+ brand : Brand ,
242
+ key : string
243
+ ) : SassBundleLayers => {
244
+ // Bootstrap Variables from brand.defaults.bootstrap
245
+ const brandBootstrap = ( brand ?. data ?. defaults ?. bootstrap as unknown as Record <
246
+ string ,
247
+ Record < string , string | boolean | number | null >
248
+ > ) ;
249
+
250
+ const bsVariables : string [ ] = [
251
+ "/* Bootstrap variables from _brand.yml */" ,
252
+ '// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml defaults.bootstrap" }' ,
253
+ ] ;
254
+ for ( const bsVar of Object . keys ( brandBootstrap ) ) {
255
+ if ( bsVar === "version" ) {
256
+ continue ;
257
+ }
258
+ bsVariables . push (
259
+ `$${ bsVar } : ${ brandBootstrap [ bsVar ] } !default;` ,
260
+ ) ;
261
+ }
262
+ bsVariables . push ( '// quarto-scss-analysis-annotation { "action": "pop" }' ) ;
263
+
264
+ // Bootstrap Colors from color.palette
265
+ let bootstrapColorVariables : string [ ] = [ ] ;
266
+ if ( Number ( brandBootstrap ?. version ?? 5 ) === 5 ) {
267
+ // https://getbootstrap.com/docs/5.3/customize/color/#color-sass-maps
268
+ bootstrapColorVariables = [
269
+ "blue" ,
270
+ "indigo" ,
271
+ "purple" ,
272
+ "pink" ,
273
+ "red" ,
274
+ "orange" ,
275
+ "yellow" ,
276
+ "green" ,
277
+ "teal" ,
278
+ "cyan" ,
279
+ "black" ,
280
+ "white" ,
281
+ "gray" ,
282
+ "gray-dark"
283
+ ]
284
+ }
285
+
286
+ const bsColors : string [ ] = [
287
+ "/* Bootstrap color variables from _brand.yml */" ,
288
+ '// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml color.palette" }' ,
289
+ ] ;
290
+
291
+ if ( bootstrapColorVariables . length > 0 ) {
292
+ for ( const colorKey of Object . keys ( brand . data ?. color ?. palette ?? { } ) ) {
293
+ if ( ! bootstrapColorVariables . includes ( colorKey ) ) {
294
+ continue ;
295
+ }
296
+
297
+ bsColors . push (
298
+ `$${ colorKey } : ${ brand . getColor ( colorKey ) } !default;` ,
299
+ ) ;
300
+ }
301
+ }
302
+
303
+ bsColors . push ( '// quarto-scss-analysis-annotation { "action": "pop" }' ) ;
304
+
305
+ const bsBundle : SassBundleLayers = {
306
+ key,
307
+ // dependency: "bootstrap",
308
+ quarto : {
309
+ defaults : bsColors . join ( "\n" ) + "\n" + bsVariables . join ( "\n" ) ,
310
+ uses : "" ,
311
+ functions : "" ,
312
+ mixins : "" ,
313
+ rules : "" ,
314
+ } ,
315
+ } ;
316
+ return bsBundle ;
317
+ } ;
318
+
225
319
const brandTypographyBundle = (
226
320
brand : Brand ,
227
321
key : string ,
@@ -450,7 +544,7 @@ const brandTypographyBundle = (
450
544
return typographyBundle ;
451
545
} ;
452
546
453
- export async function brandBootstrapSassBundleLayers (
547
+ export async function brandSassBundleLayers (
454
548
fileName : string | undefined ,
455
549
project : ProjectContext ,
456
550
key : string ,
@@ -470,12 +564,33 @@ export async function brandBootstrapSassBundleLayers(
470
564
return sassBundles ;
471
565
}
472
566
567
+ export async function brandBootstrapSassBundleLayers (
568
+ fileName : string | undefined ,
569
+ project : ProjectContext ,
570
+ key : string ,
571
+ nameMap : Record < string , string > = { } ,
572
+ ) : Promise < SassBundleLayers [ ] > {
573
+ const brand = await project . resolveBrand ( fileName ) ;
574
+ const sassBundles = await brandSassBundleLayers ( fileName , project , key , nameMap ) ;
575
+
576
+ if ( brand ?. data ?. defaults ?. bootstrap ) {
577
+ const bsBundle = brandBootstrapBundle ( brand , key ) ;
578
+ if ( bsBundle ) {
579
+ // Add bsBundle to the beginning of the array so that defaults appear
580
+ // *after* the rest of the brand variables.
581
+ sassBundles . unshift ( bsBundle ) ;
582
+ }
583
+ }
584
+
585
+ return sassBundles ;
586
+ }
587
+
473
588
export async function brandRevealSassBundleLayers (
474
589
input : string | undefined ,
475
590
_format : Format ,
476
591
project : ProjectContext ,
477
592
) : Promise < SassBundleLayers [ ] > {
478
- return brandBootstrapSassBundleLayers (
593
+ return brandSassBundleLayers (
479
594
input ,
480
595
project ,
481
596
"reveal-theme" ,
0 commit comments