@maizzle/framework
Version:
Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.
92 lines (91 loc) • 3.28 kB
JavaScript
import { RenderContextKey } from "./renderContext.js";
import { inject } from "vue";
//#region src/composables/useFont.ts
const FAMILY_CATEGORIES = {
"Roboto": "sans",
"Open Sans": "sans",
"Inter": "sans",
"Lato": "sans",
"Montserrat": "sans",
"Merriweather": "serif",
"Playfair Display": "serif",
"Lora": "serif",
"PT Serif": "serif",
"Noto Serif": "serif",
"Oswald": "display",
"Bebas Neue": "display",
"Anton": "display",
"Lobster": "display",
"Pacifico": "display",
"Dancing Script": "handwriting",
"Caveat": "handwriting",
"Shadows Into Light": "handwriting",
"Satisfy": "handwriting",
"Great Vibes": "handwriting",
"Roboto Mono": "mono",
"Source Code Pro": "mono",
"JetBrains Mono": "mono",
"Fira Code": "mono",
"Inconsolata": "mono"
};
const DEFAULT_FALLBACKS = {
sans: "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif",
serif: "ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif",
mono: "ui-monospace, Menlo, Consolas, monospace",
display: "Impact, \"Arial Black\", system-ui, sans-serif",
handwriting: "\"Segoe Script\", \"Brush Script MT\", cursive"
};
const PROVIDER_BASE_URL = {
google: "https://fonts.googleapis.com/css2",
bunny: "https://fonts.bunny.net/css2"
};
function slugify(family) {
return family.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
}
function buildProviderUrl(opts) {
const familyParam = opts.family.trim().replace(/\s+/g, "+");
const weights = [...opts.weights].sort((a, b) => a - b);
const hasItalic = opts.styles.includes("italic");
const hasNormal = opts.styles.includes("normal");
const axis = hasItalic ? `:ital,wght@${weights.flatMap((w) => [...hasNormal ? [`0,${w}`] : [], `1,${w}`]).join(";")}` : `:wght@${weights.join(";")}`;
return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`;
}
/**
* Register a font for the current email template.
*
* Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`
* (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`
* and merges `--font-{slug}` declarations into the template's existing
* `@import "tailwindcss"` style block so a `font-{slug}` utility class
* is generated. If no Tailwind import is found, falls back to a `:root`
* declaration so the CSS variable is still available.
*
* Usage in SFC <script setup>:
* ```ts
* useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })
* ```
*/
function useFont(options) {
const ctx = inject(RenderContextKey);
if (!ctx) return;
ctx.fonts = ctx.fonts ?? [];
if (ctx.fonts.some((f) => f.family === options.family)) return;
const url = options.url ?? buildProviderUrl({
family: options.family,
provider: options.provider ?? "google",
weights: options.weights ?? [400],
display: options.display ?? "swap",
styles: options.styles ?? ["normal"]
});
const fallback = options.fallback ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? "sans"];
const declaration = `${/\s/.test(options.family) ? `"${options.family}"` : options.family}, ${fallback}`;
ctx.fonts.push({
family: options.family,
slug: slugify(options.family),
declaration,
url
});
}
//#endregion
export { useFont };
//# sourceMappingURL=useFont.js.map