57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
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<string, string>): 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'],
|
|
}
|