@@ -10,57 +10,36 @@ import {
10
10
BrandColorLightDark ,
11
11
BrandFont ,
12
12
BrandLogoExplicitResource ,
13
+ BrandLogoSingle ,
14
+ BrandLogoUnified ,
15
+ BrandNamedLogo ,
13
16
BrandNamedThemeColor ,
14
17
BrandSingle ,
18
+ BrandStringLightDark ,
15
19
BrandTypographyOptionsBase ,
16
20
BrandTypographyOptionsHeadingsSingle ,
17
21
BrandTypographySingle ,
18
22
BrandTypographyUnified ,
19
23
BrandUnified ,
24
+ LogoLightDarkSpecifier ,
25
+ LogoOptions ,
26
+ NormalizedLogoLightDarkSpecifier ,
20
27
Zod ,
21
28
} from "../../resources/types/zod/schema-types.ts" ;
22
29
import { InternalError } from "../lib/error.ts" ;
23
30
24
31
import { join , relative } from "../../deno_ral/path.ts" ;
25
32
import { warnOnce } from "../log.ts" ;
26
33
import { isCssColorName } from "../css/color-names.ts" ;
27
-
28
- // we can't programmatically convert typescript types to string arrays,
29
- // so we have to define this manually. They should match `BrandNamedThemeColor` in schema-types.ts
30
-
31
- export const defaultColorNames : BrandNamedThemeColor [ ] = [
32
- "foreground" ,
33
- "background" ,
34
- "primary" ,
35
- "secondary" ,
36
- "tertiary" ,
37
- "success" ,
38
- "info" ,
39
- "warning" ,
40
- "danger" ,
41
- "light" ,
42
- "dark" ,
43
- "link" ,
44
- ] ;
45
-
46
- const defaultLogoNames : string [ ] = [
47
- "small" ,
48
- "medium" ,
49
- "large" ,
50
- ] ;
51
-
52
- type CanonicalLogoInfo = {
53
- light : BrandLogoExplicitResource ;
54
- dark : BrandLogoExplicitResource ;
55
- } ;
34
+ import { assert } from "testing/asserts" ;
56
35
57
36
type ProcessedBrandData = {
58
37
color : Record < string , string > ;
59
38
typography : BrandTypographySingle ;
60
39
logo : {
61
- small ?: CanonicalLogoInfo ;
62
- medium ?: CanonicalLogoInfo ;
63
- large ?: CanonicalLogoInfo ;
40
+ small ?: BrandLogoExplicitResource ;
41
+ medium ?: BrandLogoExplicitResource ;
42
+ large ?: BrandLogoExplicitResource ;
64
43
images : Record < string , BrandLogoExplicitResource > ;
65
44
} ;
66
45
} ;
@@ -156,11 +135,7 @@ export class Brand {
156
135
157
136
const logo : ProcessedBrandData [ "logo" ] = { images : { } } ;
158
137
for (
159
- const size of [
160
- "small" ,
161
- "medium" ,
162
- "large" ,
163
- ] as ( "small" | "medium" | "large" ) [ ]
138
+ const size of Zod . BrandNamedLogo . options
164
139
) {
165
140
const v = this . getLogo ( size ) ;
166
141
if ( v ) {
@@ -203,7 +178,9 @@ export class Brand {
203
178
if ( this . data . color ?. palette ?. [ name ] ) {
204
179
name = this . data . color . palette [ name ] as string ;
205
180
} else if (
206
- defaultColorNames . includes ( name as BrandNamedThemeColor ) &&
181
+ Zod . BrandNamedThemeColor . options . includes (
182
+ name as BrandNamedThemeColor ,
183
+ ) &&
207
184
this . data . color ?. [ name as BrandNamedThemeColor ]
208
185
) {
209
186
name = this . data . color [ name as BrandNamedThemeColor ] ! ;
@@ -278,30 +255,12 @@ export class Brand {
278
255
} ;
279
256
}
280
257
281
- getLogo ( name : "small" | "medium" | "large" ) : CanonicalLogoInfo | undefined {
258
+ getLogo ( name : BrandNamedLogo ) : BrandLogoExplicitResource | undefined {
282
259
const entry = this . data . logo ?. [ name ] ;
283
260
if ( ! entry ) {
284
261
return undefined ;
285
262
}
286
- if ( typeof entry === "string" ) {
287
- const res = this . getLogoResource ( entry ) ;
288
- return {
289
- light : res ,
290
- dark : res ,
291
- } ;
292
- }
293
- const lightEntry = entry ?. light
294
- ? this . getLogoResource ( entry . light )
295
- : undefined ;
296
- const darkEntry = entry ?. dark
297
- ? this . getLogoResource ( entry . dark )
298
- : undefined ;
299
- if ( lightEntry && darkEntry ) {
300
- return {
301
- light : lightEntry ,
302
- dark : darkEntry ,
303
- } ;
304
- }
263
+ return this . getLogoResource ( entry ) ;
305
264
}
306
265
}
307
266
@@ -320,9 +279,66 @@ export const getFavicon = (brand: Brand): string | undefined => {
320
279
if ( ! logoInfo ) {
321
280
return undefined ;
322
281
}
323
- return logoInfo . light . path ;
282
+ return logoInfo . path ;
324
283
} ;
325
284
285
+ export async function normalizeLogoSpec (
286
+ brand : LightDarkBrand | undefined ,
287
+ spec : LogoLightDarkSpecifier ,
288
+ ) : Promise < NormalizedLogoLightDarkSpecifier > {
289
+ const resolveLogo = ( mode : "light" | "dark" , name : string ) => {
290
+ const logo = brand ?. [ mode ] ?. processedData ?. logo ;
291
+ return logo &&
292
+ ( ( Zod . BrandNamedLogo . options . includes ( name as BrandNamedLogo ) &&
293
+ logo [ name as BrandNamedLogo ] ) || logo . images [ name ] ) ;
294
+ } ;
295
+ const resolveLogoOptions = (
296
+ mode : "light" | "dark" ,
297
+ logo : LogoOptions ,
298
+ ) : LogoOptions => {
299
+ const logo2 = resolveLogo ( mode , logo . path ) ;
300
+ if ( logo2 ) {
301
+ const { path : _ , ...rest } = logo ;
302
+ return {
303
+ ...logo2 ,
304
+ ...rest ,
305
+ } ;
306
+ }
307
+ return logo ;
308
+ } ;
309
+ if ( typeof spec === "string" ) {
310
+ return {
311
+ light : resolveLogo ( "light" , spec ) || { path : spec } ,
312
+ dark : resolveLogo ( "light" , spec ) || { path : spec } ,
313
+ } ;
314
+ }
315
+ if ( "path" in spec ) {
316
+ return {
317
+ light : resolveLogoOptions ( "light" , spec ) ,
318
+ dark : resolveLogoOptions ( "dark" , spec ) ,
319
+ } ;
320
+ }
321
+ let light , dark ;
322
+ if ( spec . light ) {
323
+ if ( typeof spec . light === "string" ) {
324
+ light = resolveLogo ( "light" , spec . light ) || { path : spec . light } ;
325
+ } else {
326
+ light = resolveLogoOptions ( "light" , spec . light ) ;
327
+ }
328
+ }
329
+ if ( spec . dark ) {
330
+ if ( typeof spec . dark === "string" ) {
331
+ dark = resolveLogo ( "dark" , spec . dark ) || { path : spec . dark } ;
332
+ } else {
333
+ dark = resolveLogoOptions ( "dark" , spec . dark ) ;
334
+ }
335
+ }
336
+ return {
337
+ light,
338
+ dark,
339
+ } ;
340
+ }
341
+
326
342
function splitColorLightDark (
327
343
bcld : BrandColorLightDark ,
328
344
) : LightDarkColor {
@@ -331,42 +347,55 @@ function splitColorLightDark(
331
347
}
332
348
return bcld ;
333
349
}
334
- function colorIsUnified ( blcd : BrandColorLightDark ) {
335
- return typeof blcd === "object" && "dark" in blcd ;
336
- }
337
- export function brandIsUnified ( brand : BrandUnified ) : boolean {
350
+
351
+ const enablesDarkMode = ( x : BrandColorLightDark | BrandStringLightDark ) =>
352
+ typeof x === "object" && x ?. dark ;
353
+
354
+ export function brandHasDarkMode ( brand : BrandUnified ) : boolean {
338
355
if ( brand . color ) {
339
356
for ( const colorName of Zod . BrandNamedThemeColor . options ) {
340
357
if ( ! brand . color [ colorName ] ) {
341
358
continue ;
342
359
}
343
- if ( colorIsUnified ( brand . color ! [ colorName ] ) ) {
360
+ if ( enablesDarkMode ( brand . color ! [ colorName ] ) ) {
344
361
return true ;
345
362
}
346
363
}
347
364
}
348
365
if ( brand . typography ) {
349
366
for ( const elementName of Zod . BrandNamedTypographyElements . options ) {
350
- const element = brand . typography ! [ elementName ] ;
367
+ const element = brand . typography [ elementName ] ;
351
368
if ( ! element || typeof element === "string" ) {
352
369
continue ;
353
370
}
354
371
if (
355
372
"background-color" in element && element [ "background-color" ] &&
356
- colorIsUnified ( element [ "background-color" ] )
373
+ enablesDarkMode ( element [ "background-color" ] )
357
374
) {
358
375
return true ;
359
376
}
360
377
if (
361
378
"color" in element && element [ "color" ] &&
362
- colorIsUnified ( element [ "color" ] )
379
+ enablesDarkMode ( element [ "color" ] )
363
380
) {
364
381
return true ;
365
382
}
366
383
}
367
384
}
385
+ if ( brand . logo ) {
386
+ for ( const logoName of Zod . BrandNamedLogo . options ) {
387
+ const logo = brand . logo [ logoName ] ;
388
+ if ( ! logo || typeof logo === "string" ) {
389
+ continue ;
390
+ }
391
+ if ( enablesDarkMode ( logo ) ) {
392
+ return true ;
393
+ }
394
+ }
395
+ }
368
396
return false ;
369
397
}
398
+
370
399
function sharedTypography (
371
400
unified : BrandTypographyUnified ,
372
401
) : BrandTypographySingle {
@@ -389,6 +418,25 @@ function sharedTypography(
389
418
}
390
419
return ret ;
391
420
}
421
+
422
+ function splitLogo (
423
+ unifiedLogo : BrandLogoUnified ,
424
+ ) : { light : BrandLogoSingle ; dark : BrandLogoSingle } {
425
+ const light : BrandLogoSingle = { images : unifiedLogo . images } ,
426
+ dark : BrandLogoSingle = { images : unifiedLogo . images } ;
427
+ for ( const logoName of Zod . BrandNamedLogo . options ) {
428
+ if ( unifiedLogo [ logoName ] ) {
429
+ if ( typeof unifiedLogo [ logoName ] === "string" ) {
430
+ light [ logoName ] = dark [ logoName ] = unifiedLogo [ logoName ] ;
431
+ continue ;
432
+ }
433
+ ( { light : light [ logoName ] , dark : dark [ logoName ] } =
434
+ unifiedLogo [ logoName ] ) ;
435
+ }
436
+ }
437
+ return { light, dark } ;
438
+ }
439
+
392
440
export function splitUnifiedBrand (
393
441
unified : unknown ,
394
442
brandDir : string ,
@@ -528,18 +576,19 @@ export function splitUnifiedBrand(
528
576
linkBackgroundColor [ mode ] ,
529
577
} ,
530
578
} ;
579
+ const logos = unifiedBrand . logo && splitLogo ( unifiedBrand . logo ) ;
531
580
const lightBrand : BrandSingle = {
532
581
meta : unifiedBrand . meta ,
533
582
color : { palette : unifiedBrand . color && { ...unifiedBrand . color . palette } } ,
534
583
typography : typography && specializeTypography ( typography , "light" ) ,
535
- logo : unifiedBrand . logo ,
584
+ logo : logos && logos . light ,
536
585
defaults : unifiedBrand . defaults ,
537
586
} ;
538
587
const darkBrand : BrandSingle = {
539
588
meta : unifiedBrand . meta ,
540
589
color : { palette : unifiedBrand . color && { ...unifiedBrand . color . palette } } ,
541
590
typography : typography && specializeTypography ( typography , "dark" ) ,
542
- logo : unifiedBrand . logo ,
591
+ logo : logos && logos . dark ,
543
592
defaults : unifiedBrand . defaults ,
544
593
} ;
545
594
if ( unifiedBrand . color ) {
@@ -555,7 +604,7 @@ export function splitUnifiedBrand(
555
604
}
556
605
return {
557
606
light : new Brand ( lightBrand , brandDir , projectDir ) ,
558
- dark : brandIsUnified ( unifiedBrand )
607
+ dark : brandHasDarkMode ( unifiedBrand )
559
608
? new Brand ( darkBrand , brandDir , projectDir )
560
609
: undefined ,
561
610
} ;
0 commit comments