import type { Plugin } from 'vite' /** The choices of VITE_FONT. */ export const FONTS = ['cdn', 'bundled', 'none'] as const export type Font = (typeof FONTS)[number] const FONT_MODULE = 'virtual:font' /** * Provides the fonts of the toolkit's fonts.ts as VITE_FONT selects: cdn adds the Google Fonts links for Roboto and * Roboto Mono to index.html, bundled imports @fontsource/roboto through the virtual:font module, none adds nothing; a * font not provided falls back to the system fonts of its stack. The toolkit's renderApp imports virtual:font. */ export function font(choice: Font): Plugin { const resolved = `\0${FONT_MODULE}` return { name: 'font', resolveId(id) { return id === FONT_MODULE ? resolved : undefined }, load(id) { if (id !== resolved) { return undefined } return choice === 'bundled' ? ['300', '400', '500', '700'].map((weight) => `import '@fontsource/roboto/${weight}.css'`).join('\n') : '' }, transformIndexHtml() { if (choice !== 'cdn') { return [] } return [ { tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } }, { tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true } }, { tag: 'link', attrs: { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Roboto+Mono:wght@300;400;500;700&display=swap' } }, ] }, } } /** VITE_FONT of env, the variables Vite's loadEnv answers, cdn when it is not set; another value throws. */ export function fontChoice(env: Record): Font { const choice = env.VITE_FONT ?? 'cdn' if (!FONTS.includes(choice as Font)) { throw new Error(`VITE_FONT=${choice} is not one of ${FONTS.join(', ')}.`) } return choice as Font } /** * The resolve options of an application that uses the toolkit's web code through a link: the toolkit's imports of * React, MUI and Emotion are resolved from the application's own node_modules, so the page has one copy of each. */ export const TOOLKIT_RESOLVE = { dedupe: ['react', 'react-dom', '@mui/material', '@mui/icons-material', '@mui/system', '@emotion/react', '@emotion/styled'], }