Skip to content

Commit

Permalink
chore: expose local and remote font modules
Browse files Browse the repository at this point in the history
  • Loading branch information
userquin committed Apr 20, 2024
1 parent ca5a114 commit ae509cb
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 37 deletions.
2 changes: 2 additions & 0 deletions packages/preset-web-fonts/build.config.ts
Expand Up @@ -3,6 +3,8 @@ import { defineBuildConfig } from 'unbuild'
export default defineBuildConfig({
entries: [
'src/index',
'src/local-font',
'src/remote-font',
],
clean: true,
declaration: true,
Expand Down
16 changes: 16 additions & 0 deletions packages/preset-web-fonts/package.json
Expand Up @@ -27,11 +27,27 @@
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"./local-font": {
"types": "./dist/local-font.d.mts",
"default": "./dist/local-font.mjs"
},
"./remote-font": {
"types": "./dist/remote-font.d.mts",
"default": "./dist/remote-font.mjs"
}
},
"main": "dist/index.mjs",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"./dist/*",
"./*"
]
}
},
"files": [
"*.css",
"dist"
Expand Down
21 changes: 8 additions & 13 deletions packages/preset-web-fonts/src/local-font.ts
Expand Up @@ -2,26 +2,29 @@
* Inspired by:
* https://github.com/feat-agency/vite-plugin-webfont-dl/blob/master/src/downloader.ts
*/
import process from 'node:process'
import { resolve } from 'node:path'
import { lstat, mkdir, readFile, writeFile } from 'node:fs/promises'
import { Buffer } from 'node:buffer'
import { $fetch } from 'ofetch'
import { resolveDownloadDir } from './util'

const fontUrlRegex = /[-a-z0-9@:%_+.~#?&/=]+\.(?:woff2?|eot|ttf|otf|svg)/gi

const defaultFontCssFilename = 'fonts.css'

// eslint-disable-next-line node/prefer-global/process
const isNode = typeof process !== 'undefined' && process.stdout && !process.versions.deno

interface UseLocalFontOptions {
downloadDir: string
}

export { resolveDownloadDir }

export async function useLocalFont(css: string, { downloadDir }: UseLocalFontOptions) {
if (!isNode)
return

const { resolve } = await import('node:path')
const { writeFile, mkdir } = await import('node:fs/promises')

await mkdir(downloadDir, { recursive: true })

// Download the fonts locally and update the font.css file
Expand All @@ -37,17 +40,12 @@ export async function useLocalFont(css: string, { downloadDir }: UseLocalFontOpt
}

async function fileExists(path: string) {
const { stat } = await import('node:fs/promises')
const isFile = (await stat(path).catch(() => undefined))?.isFile()
return isFile
return await lstat(path).then(({ isFile }) => isFile()).catch(() => false)
}

async function saveFont(url: string, path: string) {
if (await fileExists(path))
return
const { writeFile } = await import('node:fs/promises')
const { Buffer } = await import('node:buffer')

const response = await $fetch(url, { headers: { responseType: 'arraybuffer' } }) as ArrayBuffer
const content = new Uint8Array(response)
await writeFile(path, Buffer.from(content))
Expand All @@ -57,9 +55,6 @@ export async function readFontCSS(downloadDir: string) {
if (!isNode)
return ''

const { resolve } = await import('node:path')
const { readFile } = await import('node:fs/promises')

const fontCssPath = resolve(downloadDir, defaultFontCssFilename)
if (!await fileExists(fontCssPath))
return '/* [preset-web-font] This code will be replaced with the local CSS once it is downloaded */'
Expand Down
13 changes: 7 additions & 6 deletions packages/preset-web-fonts/src/preset.ts
Expand Up @@ -6,9 +6,6 @@ import { GoogleFontsProvider } from './providers/google'
import { FontshareProvider } from './providers/fontshare'
import { NoneProvider } from './providers/none'
import type { Provider, ResolvedWebFontMeta, WebFontMeta, WebFontsOptions, WebFontsProviders } from './types'
import { getRemoteFontsCSS } from './remote-font'
import { resolveDownloadDir } from './util'
import { readFontCSS } from './local-font'

const builtinProviders = {
google: GoogleFontsProvider,
Expand Down Expand Up @@ -49,7 +46,7 @@ export function createWebFontPreset(fetcher: (url: string) => Promise<any>) {
themeKey = 'fontFamily',
customFetch = fetcher,
downloadLocally = false,
downloadDir = 'public',
downloadDir,
} = options

const fontObject = Object.fromEntries(
Expand All @@ -63,10 +60,14 @@ export function createWebFontPreset(fetcher: (url: string) => Promise<any>) {
{
async getCSS() {
if (downloadLocally) {
const { readFontCSS, resolveDownloadDir } = await import('./local-font')
const resolvedDownloadDir = await resolveDownloadDir(downloadDir)
return await readFontCSS(resolvedDownloadDir)
return readFontCSS(resolvedDownloadDir)
}
else {
const { getRemoteFontsCSS } = await import('./remote-font')
return getRemoteFontsCSS(fontObject, { inlineImports, customFetch })
}
else { return getRemoteFontsCSS(fontObject, { inlineImports, customFetch }) }
},
layer: inlineImports ? undefined : LAYER_IMPORTS,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/preset-web-fonts/src/types.ts
Expand Up @@ -64,7 +64,7 @@ export interface WebFontsOptions {
/**
* Where to download the fonts
*
* @default 'process.cwd()/public/fonts'
* @default 'process.cwd()/public/unocss-fonts'
*/
downloadDir?: string | (() => Promise<string>)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/preset-web-fonts/src/util.ts
Expand Up @@ -12,5 +12,5 @@ export async function resolveDownloadDir(downloadDir?: string | (() => Promise<s
return await downloadDir()
else if (typeof downloadDir === 'string')
return resolve(cwd(), downloadDir)
return `${cwd()}/public/fonts`
return `${cwd()}/public/unocss-fonts`
}
5 changes: 5 additions & 0 deletions packages/vite/build.config.ts
Expand Up @@ -9,5 +9,10 @@ export default defineBuildConfig({
declaration: true,
externals: [
'vite',
'ofetch',
'destr',
'ufo',
'@unocss/preset-web-fonts/local-font',
'@unocss/preset-web-fonts/remote-font',
],
})
2 changes: 1 addition & 1 deletion packages/vite/src/index.ts
@@ -1,6 +1,6 @@
import process from 'node:process'
import type { Plugin } from 'vite'
import type { Preset, UnocssPluginContext, UserConfigDefaults } from '@unocss/core'
import type { UnocssPluginContext, UserConfigDefaults } from '@unocss/core'
import UnocssInspector from '@unocss/inspector'
import { createContext } from './integration'
import { ChunkModeBuildPlugin } from './modes/chunk-build'
Expand Down
30 changes: 15 additions & 15 deletions packages/vite/src/web-fonts.ts
@@ -1,27 +1,26 @@
import type { Plugin } from 'vite'
import { type PreflightContext, type Preset, type UnocssPluginContext, resolvePreset } from '@unocss/core'
import { useLocalFont } from '../../preset-web-fonts/src/local-font'
import { resolveDownloadDir } from '../../preset-web-fonts/src/util'
import { getRemoteFontsCSS } from '../../preset-web-fonts/src/remote-font'

// eslint-disable-next-line node/prefer-global/process
const isNode = typeof process !== 'undefined' && process.stdout && !process.versions.deno
import type { Preset, UnocssPluginContext } from '@unocss/core'

export function createWebFontPlugins(ctx: UnocssPluginContext): Plugin[] {
return [
{
name: `unocss:web-fonts-local:dev`,
enforce: 'pre',
apply: 'serve',
async configureServer(_server) {
if (!isNode)
return

const webFontPreset = lookupPreset(ctx, '@unocss/preset-web-fonts')

async configResolved(config) {
const webFontPreset = await lookupPreset(ctx, '@unocss/preset-web-fonts')
if (!webFontPreset || !webFontPreset.options?.downloadLocally)
return

if (webFontPreset) {
webFontPreset.options ??= {}
if (typeof webFontPreset.options.downloadDir === 'undefined')
webFontPreset.options.downloadDir = `${config.publicDir}/unocss-fonts`
}

const [{ resolveDownloadDir, useLocalFont }, { getRemoteFontsCSS }] = await Promise.all([
import('@unocss/preset-web-fonts/local-font'),
import('@unocss/preset-web-fonts/remote-font'),
])
const { $fetch } = await import('ofetch')
const fontCSS = await getRemoteFontsCSS(webFontPreset.options.fontObject, { inlineImports: true, customFetch: $fetch })
const downloadDir = await resolveDownloadDir(webFontPreset.options.downloadDir)
Expand All @@ -31,7 +30,8 @@ export function createWebFontPlugins(ctx: UnocssPluginContext): Plugin[] {
]
}

function lookupPreset<P extends Preset<any>>(ctx: UnocssPluginContext, presetName: P['name']) {
async function lookupPreset<P extends Preset<any>>(ctx: UnocssPluginContext, presetName: P['name']) {
await ctx.ready
const preset: P | undefined = ctx.uno.config?.presets?.find(p => p.name === presetName) as any
return preset
}
2 changes: 2 additions & 0 deletions tsconfig.json
Expand Up @@ -28,6 +28,8 @@
"@unocss/preset-typography": ["./packages/preset-typography/src/index.ts"],
"@unocss/preset-uno": ["./packages/preset-uno/src/index.ts"],
"@unocss/preset-web-fonts": ["./packages/preset-web-fonts/src/index.ts"],
"@unocss/preset-web-fonts/local-font": ["./packages/preset-web-fonts/src/local-font.ts"],
"@unocss/preset-web-fonts/remote-font": ["./packages/preset-web-fonts/src/remote-font.ts"],
"@unocss/preset-wind": ["./packages/preset-wind/src/index.ts"],
"@unocss/rule-utils": ["./packages/rule-utils/src/index.ts"],
"@unocss/shared-common": ["./packages/shared-common/src/index.ts"],
Expand Down

0 comments on commit ae509cb

Please sign in to comment.