|
| 1 | +import fs from 'node:fs/promises'; |
| 2 | +import path from 'node:path'; |
| 3 | + |
| 4 | +import { APIv2 } from 'google-font-metadata'; |
| 5 | + |
| 6 | +import { CustomizationDefaultFont } from '@gitbook/api'; |
| 7 | + |
| 8 | +import type { FontDefinitions } from '../src/types'; |
| 9 | + |
| 10 | +const googleFontsMap: { [fontName in CustomizationDefaultFont]: string } = { |
| 11 | + [CustomizationDefaultFont.Inter]: 'inter', |
| 12 | + [CustomizationDefaultFont.FiraSans]: 'fira-sans-extra-condensed', |
| 13 | + [CustomizationDefaultFont.IBMPlexSerif]: 'ibm-plex-serif', |
| 14 | + [CustomizationDefaultFont.Lato]: 'lato', |
| 15 | + [CustomizationDefaultFont.Merriweather]: 'merriweather', |
| 16 | + [CustomizationDefaultFont.NotoSans]: 'noto-sans', |
| 17 | + [CustomizationDefaultFont.OpenSans]: 'open-sans', |
| 18 | + [CustomizationDefaultFont.Overpass]: 'overpass', |
| 19 | + [CustomizationDefaultFont.Poppins]: 'poppins', |
| 20 | + [CustomizationDefaultFont.Raleway]: 'raleway', |
| 21 | + [CustomizationDefaultFont.Roboto]: 'roboto', |
| 22 | + [CustomizationDefaultFont.RobotoSlab]: 'roboto-slab', |
| 23 | + [CustomizationDefaultFont.SourceSansPro]: 'source-sans-3', |
| 24 | + [CustomizationDefaultFont.Ubuntu]: 'ubuntu', |
| 25 | + [CustomizationDefaultFont.ABCFavorit]: 'inter', |
| 26 | +}; |
| 27 | + |
| 28 | +/** |
| 29 | + * Scripts to generate the list of all icons. |
| 30 | + */ |
| 31 | +async function main() { |
| 32 | + // @ts-expect-error - we build the object |
| 33 | + const output: FontDefinitions = {}; |
| 34 | + |
| 35 | + for (const font of Object.values(CustomizationDefaultFont)) { |
| 36 | + const googleFontName = googleFontsMap[font]; |
| 37 | + const fontMetadata = APIv2[googleFontName.toLowerCase()]; |
| 38 | + if (!fontMetadata) { |
| 39 | + throw new Error(`Font ${googleFontName} not found`); |
| 40 | + } |
| 41 | + |
| 42 | + output[font] = { |
| 43 | + font: googleFontName, |
| 44 | + unicodeRange: fontMetadata.unicodeRange, |
| 45 | + variants: { |
| 46 | + '400': {}, |
| 47 | + '700': {}, |
| 48 | + }, |
| 49 | + }; |
| 50 | + |
| 51 | + Object.keys(output[font].variants).forEach((weight) => { |
| 52 | + const variants = fontMetadata.variants[weight]; |
| 53 | + const normalVariant = variants.normal; |
| 54 | + if (!normalVariant) { |
| 55 | + throw new Error(`Font ${googleFontName} has no normal variant`); |
| 56 | + } |
| 57 | + |
| 58 | + output[font].variants[weight] = {}; |
| 59 | + Object.entries(normalVariant).forEach(([script, url]) => { |
| 60 | + output[font].variants[weight][script] = url.url.woff; |
| 61 | + }); |
| 62 | + }); |
| 63 | + } |
| 64 | + |
| 65 | + await writeDataFile('fonts', JSON.stringify(output, null, 2)); |
| 66 | +} |
| 67 | + |
| 68 | +/** |
| 69 | + * We write both in dist and src as the build process might have happen already |
| 70 | + * and tsc doesn't copy the files. |
| 71 | + */ |
| 72 | +async function writeDataFile(name, content) { |
| 73 | + const srcData = path.resolve(__dirname, '../src/data'); |
| 74 | + const distData = path.resolve(__dirname, '../dist/data'); |
| 75 | + |
| 76 | + // Ensure the directories exists |
| 77 | + await Promise.all([ |
| 78 | + fs.mkdir(srcData, { recursive: true }), |
| 79 | + fs.mkdir(distData, { recursive: true }), |
| 80 | + ]); |
| 81 | + |
| 82 | + await Promise.all([ |
| 83 | + fs.writeFile(path.resolve(srcData, `${name}.json`), content), |
| 84 | + fs.writeFile(path.resolve(distData, `${name}.json`), content), |
| 85 | + ]); |
| 86 | +} |
| 87 | + |
| 88 | +main().catch((error) => { |
| 89 | + console.error(`Error generating icons list: ${error}`); |
| 90 | + process.exit(1); |
| 91 | +}); |
0 commit comments