@@ -8,25 +8,33 @@ export function createFontsState(editor: Editor) {
88 // TODO: Do some code cleanup to remove the need for this empty store
99 const { subscribe } = writable ( { } ) ;
1010
11- function createURL ( font : string ) : URL {
11+ function createURL ( font : string , weight : string ) : URL {
1212 const url = new URL ( "https://fonts.googleapis.com/css2" ) ;
1313 url . searchParams . set ( "display" , "swap" ) ;
14- url . searchParams . set ( "family" , font ) ;
14+ url . searchParams . set ( "family" , ` ${ font } :wght@ ${ weight } ` ) ;
1515 url . searchParams . set ( "text" , font ) ;
16+
1617 return url ;
1718 }
1819
1920 async function fontNames ( ) : Promise < { name : string ; url : URL | undefined } [ ] > {
20- return ( await fontList ) . map ( ( font ) => ( { name : font . family , url : createURL ( font . family ) } ) ) ;
21+ const pickPreviewWeight = ( variants : string [ ] ) => {
22+ const weights = variants . map ( ( variant ) => Number ( variant . match ( / .* \( ( \d + ) \) / ) ?. [ 1 ] || "NaN" ) ) ;
23+ const weightGoal = 400 ;
24+ const sorted = weights . map ( ( weight ) => [ weight , Math . abs ( weightGoal - weight - 1 ) ] ) ;
25+ sorted . sort ( ( [ _ , a ] , [ __ , b ] ) => a - b ) ;
26+ return sorted [ 0 ] [ 0 ] . toString ( ) ;
27+ } ;
28+ return ( await loadFontList ( ) ) . map ( ( font ) => ( { name : font . family , url : createURL ( font . family , pickPreviewWeight ( font . variants ) ) } ) ) ;
2129 }
2230
2331 async function getFontStyles ( fontFamily : string ) : Promise < { name : string ; url : URL | undefined } [ ] > {
24- const font = ( await fontList ) . find ( ( value ) => value . family === fontFamily ) ;
32+ const font = ( await loadFontList ( ) ) . find ( ( value ) => value . family === fontFamily ) ;
2533 return font ?. variants . map ( ( variant ) => ( { name : variant , url : undefined } ) ) || [ ] ;
2634 }
2735
2836 async function getFontFileUrl ( fontFamily : string , fontStyle : string ) : Promise < string | undefined > {
29- const font = ( await fontList ) . find ( ( value ) => value . family === fontFamily ) ;
37+ const font = ( await loadFontList ( ) ) . find ( ( value ) => value . family === fontFamily ) ;
3038 const fontFileUrl = font ?. files . get ( fontStyle ) ;
3139 return fontFileUrl ?. replace ( "http://" , "https://" ) ;
3240 }
@@ -47,33 +55,41 @@ export function createFontsState(editor: Editor) {
4755 return `${ weightName } ${ isItalic ? " Italic" : "" } (${ weight } )` ;
4856 }
4957
58+ let fontList : Promise < { family : string ; variants : string [ ] ; files : Map < string , string > } [ ] > | undefined ;
59+
60+ async function loadFontList ( ) : Promise < { family : string ; variants : string [ ] ; files : Map < string , string > } [ ] > {
61+ if ( fontList ) return fontList ;
62+
63+ fontList = new Promise < { family : string ; variants : string [ ] ; files : Map < string , string > } [ ] > ( ( resolve ) => {
64+ fetch ( fontListAPI )
65+ . then ( ( response ) => response . json ( ) )
66+ . then ( ( fontListResponse ) => {
67+ const fontListData = fontListResponse . items as { family : string ; variants : string [ ] ; files : Record < string , string > } [ ] ;
68+ const result = fontListData . map ( ( font ) => {
69+ const { family } = font ;
70+ const variants = font . variants . map ( formatFontStyleName ) ;
71+ const files = new Map ( font . variants . map ( ( x ) => [ formatFontStyleName ( x ) , font . files [ x ] ] ) ) ;
72+ return { family, variants, files } ;
73+ } ) ;
74+
75+ resolve ( result ) ;
76+ } ) ;
77+ } ) ;
78+
79+ return fontList ;
80+ }
81+
5082 // Subscribe to process backend events
5183 editor . subscriptions . subscribeJsMessage ( TriggerFontLoad , async ( triggerFontLoad ) => {
5284 const url = await getFontFileUrl ( triggerFontLoad . font . fontFamily , triggerFontLoad . font . fontStyle ) ;
5385 if ( url ) {
5486 const response = await ( await fetch ( url ) ) . arrayBuffer ( ) ;
55- editor . handle . onFontLoad ( triggerFontLoad . font . fontFamily , triggerFontLoad . font . fontStyle , url , new Uint8Array ( response ) , triggerFontLoad . isDefault ) ;
87+ editor . handle . onFontLoad ( triggerFontLoad . font . fontFamily , triggerFontLoad . font . fontStyle , url , new Uint8Array ( response ) ) ;
5688 } else {
5789 editor . handle . errorDialog ( "Failed to load font" , `The font ${ triggerFontLoad . font . fontFamily } with style ${ triggerFontLoad . font . fontStyle } does not exist` ) ;
5890 }
5991 } ) ;
6092
61- const fontList = new Promise < { family : string ; variants : string [ ] ; files : Map < string , string > } [ ] > ( ( resolve ) => {
62- fetch ( fontListAPI )
63- . then ( ( response ) => response . json ( ) )
64- . then ( ( fontListResponse ) => {
65- const fontListData = fontListResponse . items as { family : string ; variants : string [ ] ; files : Record < string , string > } [ ] ;
66- const result = fontListData . map ( ( font ) => {
67- const { family } = font ;
68- const variants = font . variants . map ( formatFontStyleName ) ;
69- const files = new Map ( font . variants . map ( ( x ) => [ formatFontStyleName ( x ) , font . files [ x ] ] ) ) ;
70- return { family, variants, files } ;
71- } ) ;
72-
73- resolve ( result ) ;
74- } ) ;
75- } ) ;
76-
7793 return {
7894 subscribe,
7995 fontNames,
0 commit comments