77 */
88
99import {
10- Brand as BrandJson ,
10+ BrandColorLightDark ,
1111 BrandFont ,
1212 BrandLogoExplicitResource ,
1313 BrandNamedThemeColor ,
14- BrandTypography ,
14+ BrandSingle ,
1515 BrandTypographyOptionsBase ,
16- BrandTypographyOptionsHeadings ,
16+ BrandTypographyOptionsHeadingsSingle ,
17+ BrandTypographySingle ,
18+ BrandTypographyUnified ,
19+ BrandUnified ,
1720 Zod ,
1821} from "../../resources/types/zod/schema-types.ts" ;
1922import { InternalError } from "../lib/error.ts" ;
@@ -53,7 +56,7 @@ type CanonicalLogoInfo = {
5356
5457type ProcessedBrandData = {
5558 color : Record < string , string > ;
56- typography : BrandTypography ;
59+ typography : BrandTypographySingle ;
5760 logo : {
5861 small ?: CanonicalLogoInfo ;
5962 medium ?: CanonicalLogoInfo ;
@@ -63,7 +66,7 @@ type ProcessedBrandData = {
6366} ;
6467
6568export class Brand {
66- data : BrandJson ;
69+ data : BrandSingle ;
6770 brandDir : string ;
6871 projectDir : string ;
6972 processedData : ProcessedBrandData ;
@@ -73,13 +76,13 @@ export class Brand {
7376 brandDir : string ,
7477 projectDir : string ,
7578 ) {
76- this . data = Zod . Brand . parse ( brand ) ;
79+ this . data = Zod . BrandSingle . parse ( brand ) ;
7780 this . brandDir = brandDir ;
7881 this . projectDir = projectDir ;
7982 this . processedData = this . processData ( this . data ) ;
8083 }
8184
82- processData ( data : BrandJson ) : ProcessedBrandData {
85+ processData ( data : BrandSingle ) : ProcessedBrandData {
8386 const color : Record < string , string > = { } ;
8487 for ( const colorName of Object . keys ( data . color ?. palette ?? { } ) ) {
8588 color [ colorName ] = this . getColor ( colorName ) ;
@@ -91,7 +94,7 @@ export class Brand {
9194 color [ colorName ] = this . getColor ( colorName ) ;
9295 }
9396
94- const typography : BrandTypography = { } ;
97+ const typography : BrandTypographySingle = { } ;
9598 const base = this . getFont ( "base" ) ;
9699 if ( base ) {
97100 typography . base = base ;
@@ -221,7 +224,10 @@ export class Brand {
221224
222225 getFont (
223226 name : string ,
224- ) : BrandTypographyOptionsBase | BrandTypographyOptionsHeadings | undefined {
227+ ) :
228+ | BrandTypographyOptionsBase
229+ | BrandTypographyOptionsHeadingsSingle
230+ | undefined {
225231 if ( ! this . data . typography ) {
226232 return undefined ;
227233 }
@@ -304,10 +310,253 @@ export type LightDarkBrand = {
304310 dark ?: Brand ;
305311} ;
306312
313+ export type LightDarkColor = {
314+ light ?: string ;
315+ dark ?: string ;
316+ } ;
317+
307318export const getFavicon = ( brand : Brand ) : string | undefined => {
308319 const logoInfo = brand . getLogo ( "small" ) ;
309320 if ( ! logoInfo ) {
310321 return undefined ;
311322 }
312323 return logoInfo . light . path ;
313324} ;
325+
326+ function splitColorLightDark (
327+ bcld : BrandColorLightDark ,
328+ ) : LightDarkColor {
329+ if ( typeof bcld === "string" ) {
330+ return { light : bcld , dark : bcld } ;
331+ }
332+ return bcld ;
333+ }
334+ function colorIsUnified ( blcd : BrandColorLightDark ) {
335+ return typeof blcd === "object" && "dark" in blcd ;
336+ }
337+ export function brandIsUnified ( brand : BrandUnified ) : boolean {
338+ if ( brand . color ) {
339+ for ( const colorName of Zod . BrandNamedThemeColor . options ) {
340+ if ( ! brand . color [ colorName ] ) {
341+ continue ;
342+ }
343+ if ( colorIsUnified ( brand . color ! [ colorName ] ) ) {
344+ return true ;
345+ }
346+ }
347+ }
348+ if ( brand . typography ) {
349+ for ( const elementName of Zod . BrandNamedTypographyElements . options ) {
350+ const element = brand . typography ! [ elementName ] ;
351+ if ( ! element || typeof element === "string" ) {
352+ continue ;
353+ }
354+ if (
355+ "background-color" in element && element [ "background-color" ] &&
356+ colorIsUnified ( element [ "background-color" ] )
357+ ) {
358+ return true ;
359+ }
360+ if (
361+ "color" in element && element [ "color" ] &&
362+ colorIsUnified ( element [ "color" ] )
363+ ) {
364+ return true ;
365+ }
366+ }
367+ }
368+ return false ;
369+ }
370+ function sharedTypography (
371+ unified : BrandTypographyUnified ,
372+ ) : BrandTypographySingle {
373+ const ret : BrandTypographySingle = {
374+ fonts : unified . fonts ,
375+ } ;
376+ for ( const elementName of Zod . BrandNamedTypographyElements . options ) {
377+ if ( ! unified [ elementName ] ) {
378+ continue ;
379+ }
380+ if ( typeof unified [ elementName ] === "string" ) {
381+ ret [ elementName ] = unified [ elementName ] ;
382+ continue ;
383+ }
384+ ret [ elementName ] = Object . fromEntries (
385+ Object . entries ( unified [ elementName ] ) . filter (
386+ ( [ key , _ ] ) => ! [ "color" , "background-color" ] . includes ( key ) ,
387+ ) ,
388+ ) ;
389+ }
390+ return ret ;
391+ }
392+ export function splitUnifiedBrand (
393+ unified : unknown ,
394+ brandDir : string ,
395+ projectDir : string ,
396+ ) : LightDarkBrand {
397+ const unifiedBrand : BrandUnified = Zod . BrandUnified . parse ( unified ) ;
398+ let typography : BrandTypographySingle | undefined = undefined ;
399+ let headingsColor : LightDarkColor | undefined = undefined ;
400+ let monospaceColor : LightDarkColor | undefined = undefined ;
401+ let monospaceBackgroundColor : LightDarkColor | undefined = undefined ;
402+ let monospaceInlineColor : LightDarkColor | undefined = undefined ;
403+ let monospaceInlineBackgroundColor : LightDarkColor | undefined = undefined ;
404+ let monospaceBlockColor : LightDarkColor | undefined = undefined ;
405+ let monospaceBlockBackgroundColor : LightDarkColor | undefined = undefined ;
406+ let linkColor : LightDarkColor | undefined = undefined ;
407+ let linkBackgroundColor : LightDarkColor | undefined = undefined ;
408+ if ( unifiedBrand . typography ) {
409+ typography = sharedTypography ( unifiedBrand . typography ) ;
410+ if (
411+ unifiedBrand . typography . headings &&
412+ typeof unifiedBrand . typography . headings !== "string" &&
413+ unifiedBrand . typography . headings . color
414+ ) {
415+ headingsColor = splitColorLightDark (
416+ unifiedBrand . typography . headings . color ,
417+ ) ;
418+ }
419+ if (
420+ unifiedBrand . typography . monospace &&
421+ typeof unifiedBrand . typography . monospace !== "string"
422+ ) {
423+ if ( unifiedBrand . typography . monospace . color ) {
424+ monospaceColor = splitColorLightDark (
425+ unifiedBrand . typography . monospace . color ,
426+ ) ;
427+ }
428+ if ( unifiedBrand . typography . monospace [ "background-color" ] ) {
429+ monospaceBackgroundColor = splitColorLightDark (
430+ unifiedBrand . typography . monospace [ "background-color" ] ,
431+ ) ;
432+ }
433+ }
434+ if (
435+ unifiedBrand . typography [ "monospace-inline" ] &&
436+ typeof unifiedBrand . typography [ "monospace-inline" ] !== "string"
437+ ) {
438+ if ( unifiedBrand . typography [ "monospace-inline" ] . color ) {
439+ monospaceInlineColor = splitColorLightDark (
440+ unifiedBrand . typography [ "monospace-inline" ] . color ,
441+ ) ;
442+ }
443+ if ( unifiedBrand . typography [ "monospace-inline" ] [ "background-color" ] ) {
444+ monospaceInlineBackgroundColor = splitColorLightDark (
445+ unifiedBrand . typography [ "monospace-inline" ] [ "background-color" ] ,
446+ ) ;
447+ }
448+ }
449+ if (
450+ unifiedBrand . typography [ "monospace-block" ] &&
451+ typeof unifiedBrand . typography [ "monospace-block" ] !== "string"
452+ ) {
453+ if ( unifiedBrand . typography [ "monospace-block" ] . color ) {
454+ monospaceBlockColor = splitColorLightDark (
455+ unifiedBrand . typography [ "monospace-block" ] . color ,
456+ ) ;
457+ }
458+ if ( unifiedBrand . typography [ "monospace-block" ] [ "background-color" ] ) {
459+ monospaceBlockBackgroundColor = splitColorLightDark (
460+ unifiedBrand . typography [ "monospace-block" ] [ "background-color" ] ,
461+ ) ;
462+ }
463+ }
464+ if (
465+ unifiedBrand . typography . link &&
466+ typeof unifiedBrand . typography . link !== "string"
467+ ) {
468+ if ( unifiedBrand . typography . link . color ) {
469+ linkColor = splitColorLightDark (
470+ unifiedBrand . typography . link . color ,
471+ ) ;
472+ }
473+ if ( unifiedBrand . typography . link [ "background-color" ] ) {
474+ linkBackgroundColor = splitColorLightDark (
475+ unifiedBrand . typography . link [ "background-color" ] ,
476+ ) ;
477+ }
478+ }
479+ }
480+ const specializeTypography = (
481+ typography : BrandTypographySingle ,
482+ mode : "light" | "dark" ,
483+ ) =>
484+ typography && {
485+ fonts : typography . fonts && [ ...typography . fonts ] ,
486+ base : ! typography . base || typeof typography . base === "string"
487+ ? typography . base
488+ : { ...typography . base } ,
489+ headings : ! typography . headings || typeof typography . headings === "string"
490+ ? typography . headings
491+ : {
492+ ...typography . headings ,
493+ color : headingsColor && headingsColor [ mode ] ,
494+ } ,
495+ monospace :
496+ ! typography . monospace || typeof typography . monospace === "string"
497+ ? typography . monospace
498+ : {
499+ ...typography . monospace ,
500+ color : monospaceColor && monospaceColor [ mode ] ,
501+ "background-color" : monospaceBackgroundColor &&
502+ monospaceBackgroundColor [ mode ] ,
503+ } ,
504+ "monospace-inline" : ! typography [ "monospace-inline" ] ||
505+ typeof typography [ "monospace-inline" ] === "string"
506+ ? typography [ "monospace-inline" ]
507+ : {
508+ ...typography [ "monospace-inline" ] ,
509+ color : monospaceInlineColor && monospaceInlineColor [ mode ] ,
510+ "background-color" : monospaceInlineBackgroundColor &&
511+ monospaceInlineBackgroundColor [ mode ] ,
512+ } ,
513+ "monospace-block" : ! typography [ "monospace-block" ] ||
514+ typeof typography [ "monospace-block" ] === "string"
515+ ? typography [ "monospace-block" ]
516+ : {
517+ ...typography [ "monospace-block" ] ,
518+ color : monospaceBlockColor && monospaceBlockColor [ mode ] ,
519+ "background-color" : monospaceBlockBackgroundColor &&
520+ monospaceBlockBackgroundColor [ mode ] ,
521+ } ,
522+ link : ! typography . link || typeof typography . link === "string"
523+ ? typography . link
524+ : {
525+ ...typography . link ,
526+ color : linkColor && linkColor [ mode ] ,
527+ "background-color" : linkBackgroundColor &&
528+ linkBackgroundColor [ mode ] ,
529+ } ,
530+ } ;
531+ const lightBrand : BrandSingle = {
532+ meta : unifiedBrand . meta ,
533+ color : { palette : unifiedBrand . color && { ...unifiedBrand . color . palette } } ,
534+ typography : typography && specializeTypography ( typography , "light" ) ,
535+ logo : unifiedBrand . logo ,
536+ defaults : unifiedBrand . defaults ,
537+ } ;
538+ const darkBrand : BrandSingle = {
539+ meta : unifiedBrand . meta ,
540+ color : { palette : unifiedBrand . color && { ...unifiedBrand . color . palette } } ,
541+ typography : typography && specializeTypography ( typography , "dark" ) ,
542+ logo : unifiedBrand . logo ,
543+ defaults : unifiedBrand . defaults ,
544+ } ;
545+ if ( unifiedBrand . color ) {
546+ for ( const colorName of Zod . BrandNamedThemeColor . options ) {
547+ if ( ! unifiedBrand . color [ colorName ] ) {
548+ continue ;
549+ }
550+ ( {
551+ light : lightBrand . color ! [ colorName ] ,
552+ dark : darkBrand . color ! [ colorName ] ,
553+ } = splitColorLightDark ( unifiedBrand . color ! [ colorName ] ) ) ;
554+ }
555+ }
556+ return {
557+ light : new Brand ( lightBrand , brandDir , projectDir ) ,
558+ dark : brandIsUnified ( unifiedBrand )
559+ ? new Brand ( darkBrand , brandDir , projectDir )
560+ : undefined ,
561+ } ;
562+ }
0 commit comments