'use strict'; const node_url = require('node:url'); const node_path = require('node:path'); const kit = require('@nuxt/kit'); const pathe = require('pathe'); const ufo = require('ufo'); const fontaine = require('fontaine'); const MagicString = require('magic-string'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString); const NitroTransformPlugin = (options) => ({ name: "nuxt-fontaine-transform-nitro", transform(code, source) { if (!code.includes("__INLINED_CSS__")) return; const s = new MagicString__default(code); s.replace("__INLINED_CSS__", `\` ${options.cssContext.value.replace(/\s+/g, " ")}\``); return { code: s.toString(), map: options.sourcemap ? s.generateMap({ source, includeContent: true }) : void 0 }; } }); const module$1 = kit.defineNuxtModule({ meta: { configKey: "fontMetrics", name: "@nuxtjs/fontaine", compatibility: { nuxt: ">=3.0.0-rc.6 || ^4.0.0" } }, defaults: (nuxt) => ({ inject: true, inline: nuxt.options.ssr, fallbacks: ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans"], fonts: [] }), async setup(options, nuxt) { if (nuxt.options._prepare) return; if (nuxt.options.fontMetrics?.fallbacks) { options.fallbacks = nuxt.options.fontMetrics?.fallbacks; } const logger = kit.useLogger("@nuxtjs/fontaine"); const css = (async () => { let css2 = ""; for (const font of options.fonts) { const { family, src, fallbackName, fallbacks, root: fontRoot } = typeof font === "string" ? { family: font } : font; let metrics = await fontaine.getMetricsForFamily(family); if (!metrics && src && !ufo.hasProtocol(src)) { const file = pathe.resolve( nuxt.options.srcDir, fontRoot ?? options.root ?? nuxt.options.dir.public, src ); metrics = await fontaine.readMetrics(node_url.pathToFileURL(file)); } if (!metrics) { logger.warn("Could not find metrics for font", family); continue; } for (const font2 of fallbacks || options.fallbacks) { css2 += fontaine.generateFontFace(metrics, { name: fallbackName || fontaine.generateFallbackName(family), font: font2, metrics: await fontaine.getMetricsForFamily(font2) }); } } return css2; })(); const cssContext = { value: "" }; if (options.inject) { const resolvePath = (id) => { if (ufo.hasProtocol(id)) return id; if (node_path.isAbsolute(id)) return node_url.pathToFileURL(pathe.resolve(nuxt.options.srcDir, nuxt.options.dir.public, ufo.withoutLeadingSlash(id))); return node_url.pathToFileURL(kit.resolveAlias(id)); }; const transformOptions = { fallbacks: options.fallbacks, resolvePath, css: cssContext, skipFontFaceGeneration: (fallbackName) => { return options.inline && options.fonts.some((font) => { const previouslyGeneratedFallbackName = typeof font === "string" ? fontaine.generateFallbackName(font) : font.fallbackName || fontaine.generateFallbackName(font.family); return previouslyGeneratedFallbackName === fallbackName; }); }, sourcemap: !!nuxt.options.sourcemap.client }; kit.addVitePlugin(fontaine.FontaineTransform.vite(transformOptions), { server: false }); kit.addWebpackPlugin(fontaine.FontaineTransform.webpack(transformOptions), { server: false }); nuxt.hook("nitro:config", async (config) => { const plugins = await config.rollupConfig.plugins; if (!plugins || !Array.isArray(plugins)) return; plugins.push( NitroTransformPlugin({ sourcemap: true, cssContext }) ); }); } if (options.inline) { kit.addPluginTemplate({ filename: "font-fallback-inlining-plugin.server.ts", getContents: async () => [ `import { defineNuxtPlugin, useHead } from '#imports'`, `const css = \`${(await css).replace(/\s+/g, " ")}\``, `export default defineNuxtPlugin(() => { useHead({ style: [{ innerHTML: css ${!nuxt.options.dev && options.inject ? "+ __INLINED_CSS__ " : ""}}] }) })` ].join("\n"), mode: "server" }); } else { kit.addTemplate({ filename: "font-fallbacks.css", write: true, getContents: () => css }); nuxt.options.css.push("#build/font-fallbacks.css"); } } }); module.exports = module$1;