@pro-laico/payload-fonts 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +22 -0
- package/README.md +19 -0
- package/dist/access/authd.d.ts +19 -0
- package/dist/access/authd.d.ts.map +1 -0
- package/dist/access/authd.js +18 -0
- package/dist/access/authd.js.map +1 -0
- package/dist/collections/font.d.ts +29 -0
- package/dist/collections/font.d.ts.map +1 -0
- package/dist/collections/font.js +327 -0
- package/dist/collections/font.js.map +1 -0
- package/dist/collections/fontOptimized.d.ts +20 -0
- package/dist/collections/fontOptimized.d.ts.map +1 -0
- package/dist/collections/fontOptimized.js +111 -0
- package/dist/collections/fontOptimized.js.map +1 -0
- package/dist/collections/fontOriginal.d.ts +25 -0
- package/dist/collections/fontOriginal.d.ts.map +1 -0
- package/dist/collections/fontOriginal.js +49 -0
- package/dist/collections/fontOriginal.js.map +1 -0
- package/dist/components/DevFonts.d.ts +52 -0
- package/dist/components/DevFonts.d.ts.map +1 -0
- package/dist/components/DevFonts.js +75 -0
- package/dist/components/DevFonts.js.map +1 -0
- package/dist/components/admin/FontOriginalUpload.d.ts +15 -0
- package/dist/components/admin/FontOriginalUpload.d.ts.map +1 -0
- package/dist/components/admin/FontOriginalUpload.js +22 -0
- package/dist/components/admin/FontOriginalUpload.js.map +1 -0
- package/dist/components/admin/FontOriginalUpload.scss +9 -0
- package/dist/endpoints/exportFonts.d.ts +49 -0
- package/dist/endpoints/exportFonts.d.ts.map +1 -0
- package/dist/endpoints/exportFonts.js +162 -0
- package/dist/endpoints/exportFonts.js.map +1 -0
- package/dist/extractFonts.d.ts +20 -0
- package/dist/extractFonts.d.ts.map +1 -0
- package/dist/extractFonts.js +18 -0
- package/dist/extractFonts.js.map +1 -0
- package/dist/fields/font.d.ts +14 -0
- package/dist/fields/font.d.ts.map +1 -0
- package/dist/fields/font.js +37 -0
- package/dist/fields/font.js.map +1 -0
- package/dist/globals/fontSet.d.ts +15 -0
- package/dist/globals/fontSet.d.ts.map +1 -0
- package/dist/globals/fontSet.js +25 -0
- package/dist/globals/fontSet.js.map +1 -0
- package/dist/hooks/optimizeFont.d.ts +56 -0
- package/dist/hooks/optimizeFont.d.ts.map +1 -0
- package/dist/hooks/optimizeFont.js +185 -0
- package/dist/hooks/optimizeFont.js.map +1 -0
- package/dist/hooks/optimizeFromOriginals.d.ts +43 -0
- package/dist/hooks/optimizeFromOriginals.d.ts.map +1 -0
- package/dist/hooks/optimizeFromOriginals.js +313 -0
- package/dist/hooks/optimizeFromOriginals.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/activeFonts.d.ts +64 -0
- package/dist/lib/activeFonts.d.ts.map +1 -0
- package/dist/lib/activeFonts.js +139 -0
- package/dist/lib/activeFonts.js.map +1 -0
- package/dist/lib/families.d.ts +38 -0
- package/dist/lib/families.d.ts.map +1 -0
- package/dist/lib/families.js +44 -0
- package/dist/lib/families.js.map +1 -0
- package/dist/lib/mergeConfig.d.ts +28 -0
- package/dist/lib/mergeConfig.d.ts.map +1 -0
- package/dist/lib/mergeConfig.js +73 -0
- package/dist/lib/mergeConfig.js.map +1 -0
- package/dist/lib/refs.d.ts +8 -0
- package/dist/lib/refs.d.ts.map +1 -0
- package/dist/lib/refs.js +11 -0
- package/dist/lib/refs.js.map +1 -0
- package/dist/lib/uploadBytes.d.ts +26 -0
- package/dist/lib/uploadBytes.d.ts.map +1 -0
- package/dist/lib/uploadBytes.js +98 -0
- package/dist/lib/uploadBytes.js.map +1 -0
- package/dist/plugin.d.ts +57 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +93 -0
- package/dist/plugin.js.map +1 -0
- package/dist/scripts/cli.d.ts +3 -0
- package/dist/scripts/cli.d.ts.map +1 -0
- package/dist/scripts/cli.js +13 -0
- package/dist/scripts/cli.js.map +1 -0
- package/dist/scripts/downloadFonts.d.ts +37 -0
- package/dist/scripts/downloadFonts.d.ts.map +1 -0
- package/dist/scripts/downloadFonts.js +216 -0
- package/dist/scripts/downloadFonts.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type RunDownloadFontsOptions = {
|
|
2
|
+
/** Directory for downloaded font files. Default `./public/fonts` or `PAYLOAD_FONTS_OUTPUT_DIR`. */
|
|
3
|
+
fontsOutputDir?: string;
|
|
4
|
+
/** Generated `next/font/local` module path. Default `./src/app/definition.ts` or `PAYLOAD_FONTS_DEFINITION_FILE`. */
|
|
5
|
+
definitionFile?: string;
|
|
6
|
+
/** Dotenv file to load before reading env. Default `./.env.local` then `./.env` (Next
|
|
7
|
+
* convention, `.env.local` wins), or `PAYLOAD_FONTS_ENV_FILE` to load exactly one file. */
|
|
8
|
+
envFile?: string;
|
|
9
|
+
/**
|
|
10
|
+
* `src` path passed to `localFont()` in the generated file (relative to the definition file's
|
|
11
|
+
* directory). Default `../../public/fonts` or `PAYLOAD_FONTS_SRC_PREFIX`. If you change
|
|
12
|
+
* `fontsOutputDir`, set this accordingly.
|
|
13
|
+
*/
|
|
14
|
+
localFontSrcPrefix?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Prefix for the CSS custom properties emitted by the generated `localFont()` calls. The slot
|
|
17
|
+
* name is appended capitalised (e.g. `--font-setSans`). Default `--font-set` or
|
|
18
|
+
* `PAYLOAD_FONTS_CSS_VAR_PREFIX`. Change it only if your stylesheet references different names.
|
|
19
|
+
*/
|
|
20
|
+
cssVariablePrefix?: string;
|
|
21
|
+
/** Base URL of the running Payload instance to fetch from. Default `FONT_DOWNLOAD_URL`. */
|
|
22
|
+
siteUrl?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Path of the plugin's fonts export endpoint, resolved against the site URL. Default
|
|
25
|
+
* `/api/fonts/export` or `PAYLOAD_FONTS_ENDPOINT`.
|
|
26
|
+
*/
|
|
27
|
+
endpointPath?: string;
|
|
28
|
+
/**
|
|
29
|
+
* When true, failures also print the full underlying error object (stack, cause, …). Defaults
|
|
30
|
+
* to false (or `PAYLOAD_FONTS_VERBOSE`), so a routine local failure shows only the short
|
|
31
|
+
* message. Enable with the `--verbose` / `-v` CLI flag or `PAYLOAD_FONTS_VERBOSE=true` when you
|
|
32
|
+
* need to debug the error itself.
|
|
33
|
+
*/
|
|
34
|
+
verbose?: boolean;
|
|
35
|
+
};
|
|
36
|
+
export declare function runDownloadFonts(overrides?: RunDownloadFontsOptions): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=downloadFonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloadFonts.d.ts","sourceRoot":"","sources":["../../src/scripts/downloadFonts.ts"],"names":[],"mappings":"AAkCA,MAAM,MAAM,uBAAuB,GAAG;IACpC,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qHAAqH;IACrH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;gGAC4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAiBD,wBAAsB,gBAAgB,CAAC,SAAS,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwMzF"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
import { familyExportName, familyVarSuffix } from "../lib/families.js";
|
|
5
|
+
const colors = {
|
|
6
|
+
blue: (t)=>`\x1b[34m${t}\x1b[0m`,
|
|
7
|
+
green: (t)=>`\x1b[32m${t}\x1b[0m`,
|
|
8
|
+
red: (t)=>`\x1b[31m${t}\x1b[0m`,
|
|
9
|
+
orange: (t)=>`\x1b[33m${t}\x1b[0m`
|
|
10
|
+
};
|
|
11
|
+
/** Connection-refused / unreachable host — the DESIGNED `predev` state (server not up yet), never
|
|
12
|
+
* an error. Node buries the code under `cause` (often an AggregateError), so walk the chain. */ const DOWN_CODES = /ECONNREFUSED|ENOTFOUND|EHOSTUNREACH/;
|
|
13
|
+
const isServerDown = (err)=>{
|
|
14
|
+
if (!err || typeof err !== 'object') return false;
|
|
15
|
+
const { code, message, cause, errors } = err;
|
|
16
|
+
if (DOWN_CODES.test(code ?? '') || DOWN_CODES.test(message ?? '')) return true;
|
|
17
|
+
return isServerDown(cause) || Array.isArray(errors) && errors.some(isServerDown);
|
|
18
|
+
};
|
|
19
|
+
function resolveOptions(overrides) {
|
|
20
|
+
// An explicit env file (option or PAYLOAD_FONTS_ENV_FILE) is loaded alone; otherwise follow the
|
|
21
|
+
// Next convention — `.env.local` first so its values win over `.env` (dotenv keeps the first).
|
|
22
|
+
const explicitEnvFile = overrides?.envFile ?? process.env.PAYLOAD_FONTS_ENV_FILE;
|
|
23
|
+
return {
|
|
24
|
+
fontsOutputDir: overrides?.fontsOutputDir ?? process.env.PAYLOAD_FONTS_OUTPUT_DIR ?? './public/fonts',
|
|
25
|
+
definitionFile: overrides?.definitionFile ?? process.env.PAYLOAD_FONTS_DEFINITION_FILE ?? './src/app/definition.ts',
|
|
26
|
+
envFiles: explicitEnvFile ? [
|
|
27
|
+
explicitEnvFile
|
|
28
|
+
] : [
|
|
29
|
+
'./.env.local',
|
|
30
|
+
'./.env'
|
|
31
|
+
],
|
|
32
|
+
localFontSrcPrefix: overrides?.localFontSrcPrefix ?? process.env.PAYLOAD_FONTS_SRC_PREFIX ?? '../../public/fonts',
|
|
33
|
+
cssVariablePrefix: overrides?.cssVariablePrefix ?? process.env.PAYLOAD_FONTS_CSS_VAR_PREFIX ?? '--font-set',
|
|
34
|
+
endpointPath: overrides?.endpointPath ?? process.env.PAYLOAD_FONTS_ENDPOINT ?? '/api/fonts/export',
|
|
35
|
+
verbose: overrides?.verbose ?? process.env.PAYLOAD_FONTS_VERBOSE === 'true'
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export async function runDownloadFonts(overrides) {
|
|
39
|
+
const opts = resolveOptions(overrides);
|
|
40
|
+
dotenv.config({
|
|
41
|
+
path: opts.envFiles,
|
|
42
|
+
quiet: true
|
|
43
|
+
});
|
|
44
|
+
const FONT_FILES_DIR = opts.fontsOutputDir;
|
|
45
|
+
const FONT_DEFINITION_FILE = opts.definitionFile;
|
|
46
|
+
const localPrefix = opts.localFontSrcPrefix.replace(/\/$/, '');
|
|
47
|
+
function generateFontDefinitions(familyFiles) {
|
|
48
|
+
// One `localFont()` per family with files, each with an array of weighted `src` entries — so
|
|
49
|
+
// multiple weights collapse into a single CSS variable for that family. The export name +
|
|
50
|
+
// variable are derived from the family key by the shared convention (`sans` → `fontSans` /
|
|
51
|
+
// `<prefix>Sans`).
|
|
52
|
+
const configs = Object.entries(familyFiles).filter(([, files])=>files.length > 0).map(([family, files])=>({
|
|
53
|
+
name: familyExportName(family),
|
|
54
|
+
files,
|
|
55
|
+
variable: `${opts.cssVariablePrefix}${familyVarSuffix(family)}`
|
|
56
|
+
}));
|
|
57
|
+
const declarations = configs.map((c)=>{
|
|
58
|
+
const src = c.files.map((f)=>`{ path: '${f.path}', weight: '${f.weight}', style: '${f.style}' }`).join(', ');
|
|
59
|
+
return `const ${c.name} = localFont({ src: [${src}], variable: '${c.variable}' })`;
|
|
60
|
+
}).join('\n');
|
|
61
|
+
const exports = configs.map((c)=>c.name).join(', ');
|
|
62
|
+
fs.mkdirSync(path.dirname(FONT_DEFINITION_FILE), {
|
|
63
|
+
recursive: true
|
|
64
|
+
});
|
|
65
|
+
// No-fonts stub omits the `localFont` import entirely so the generated file
|
|
66
|
+
// passes any consumer's unused-import lint (eslint or Biome) as-is.
|
|
67
|
+
fs.writeFileSync(FONT_DEFINITION_FILE, configs.length === 0 ? `// DO NOT EDIT MANUALLY. THIS FILE IS AUTOMATICALLY GENERATED.
|
|
68
|
+
|
|
69
|
+
// No fonts available
|
|
70
|
+
|
|
71
|
+
const fonts = {}
|
|
72
|
+
export default fonts
|
|
73
|
+
` : `// DO NOT EDIT MANUALLY. THIS FILE IS AUTOMATICALLY GENERATED.
|
|
74
|
+
import localFont from 'next/font/local'
|
|
75
|
+
|
|
76
|
+
${declarations}
|
|
77
|
+
|
|
78
|
+
const fonts = { ${exports} }
|
|
79
|
+
export default fonts
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Reset the generated module to an empty-but-valid stub. Called on EVERY error / skip path so a
|
|
84
|
+
* failed or partial run never leaves a `definition.ts` that imports font files which aren't on
|
|
85
|
+
* disk — a gitignored `public/fonts/` on a fresh checkout, or a dir wiped mid-run — which would
|
|
86
|
+
* break `next build` with "Can't resolve". It ALWAYS overwrites: a stale definition surviving a
|
|
87
|
+
* failure is the bug we're fixing (the atomic version only wrote this stub when the file was
|
|
88
|
+
* absent), so a definition is never preserved on error.
|
|
89
|
+
*/ function writeEmptyDefinitions() {
|
|
90
|
+
generateFontDefinitions({});
|
|
91
|
+
}
|
|
92
|
+
function wipeFontFiles() {
|
|
93
|
+
if (!fs.existsSync(FONT_FILES_DIR)) fs.mkdirSync(FONT_FILES_DIR, {
|
|
94
|
+
recursive: true
|
|
95
|
+
});
|
|
96
|
+
// Only unlink files — a stray subdirectory would make unlinkSync throw EISDIR.
|
|
97
|
+
for (const file of fs.readdirSync(FONT_FILES_DIR)){
|
|
98
|
+
const filePath = path.join(FONT_FILES_DIR, file);
|
|
99
|
+
if (fs.statSync(filePath).isFile()) fs.unlinkSync(filePath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Report a failure and reset the definition to empty, so the build still compiles. */ function warnAndEmpty(message, error) {
|
|
103
|
+
console.warn(colors.red(message));
|
|
104
|
+
if (error) {
|
|
105
|
+
if (opts.verbose) console.warn(error);
|
|
106
|
+
else console.warn(colors.orange('Re-run with --verbose (or set PAYLOAD_FONTS_VERBOSE=true) to see the full error.'));
|
|
107
|
+
}
|
|
108
|
+
console.warn(colors.orange('Font download failed — wrote an empty definition so the build can proceed.'));
|
|
109
|
+
writeEmptyDefinitions();
|
|
110
|
+
}
|
|
111
|
+
// Any failure anywhere in the run resets the definition to empty (via warnAndEmpty on the
|
|
112
|
+
// handled paths, and the catch below for anything unexpected).
|
|
113
|
+
try {
|
|
114
|
+
console.log(colors.blue('Starting Font Download...\n'));
|
|
115
|
+
const siteUrl = overrides?.siteUrl ?? process.env.FONT_DOWNLOAD_URL;
|
|
116
|
+
const secret = process.env.PAYLOAD_SECRET;
|
|
117
|
+
if (!siteUrl || !secret) {
|
|
118
|
+
const searched = ` (searched ${opts.envFiles.join(', ')})`;
|
|
119
|
+
if (!siteUrl) console.warn(colors.red(`Missing required environment variable: FONT_DOWNLOAD_URL${searched}`));
|
|
120
|
+
if (!secret) console.warn(colors.red(`Missing required environment variable: PAYLOAD_SECRET${searched}`));
|
|
121
|
+
console.warn(colors.orange('Font download skipped — wrote an empty definition so the build can proceed.'));
|
|
122
|
+
writeEmptyDefinitions();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!/^https?:\/\//i.test(siteUrl) || !URL.canParse(siteUrl)) {
|
|
126
|
+
warnAndEmpty(`FONT_DOWNLOAD_URL is not a valid http(s) URL: "${siteUrl}" — expected e.g. http://localhost:3000`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Fetch the active fonts from the plugin's export endpoint, authenticating with the project's
|
|
130
|
+
// PAYLOAD_SECRET.
|
|
131
|
+
const endpoint = new URL(opts.endpointPath, siteUrl).toString();
|
|
132
|
+
let manifest;
|
|
133
|
+
try {
|
|
134
|
+
const res = await fetch(endpoint, {
|
|
135
|
+
headers: {
|
|
136
|
+
Authorization: `Bearer ${secret}`
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
const hint = res.status === 401 || res.status === 403 ? " — your local PAYLOAD_SECRET doesn't match the server's" : res.status === 404 ? ' — is the fonts plugin registered on that app? (or set PAYLOAD_FONTS_ENDPOINT)' : '';
|
|
141
|
+
warnAndEmpty(`Font export endpoint returned HTTP ${res.status} ${res.statusText}${hint}`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
manifest = await res.json();
|
|
145
|
+
} catch (err) {
|
|
146
|
+
if (isServerDown(err)) {
|
|
147
|
+
// The DESIGNED predev state: `predev` runs before the dev server exists. Not an error.
|
|
148
|
+
console.log(`[payload-fonts] no running Payload at ${endpoint} — wrote the empty dev stub (DevFonts serves fonts at runtime in dev).`);
|
|
149
|
+
writeEmptyDefinitions();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
warnAndEmpty(`Could not reach the font export endpoint at ${endpoint}`, err);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const fonts = manifest?.fonts ?? {};
|
|
156
|
+
wipeFontFiles();
|
|
157
|
+
// Discover the active families from the response keys (the plugin's `families` option drives them).
|
|
158
|
+
const families = Object.keys(fonts);
|
|
159
|
+
const familyFiles = {};
|
|
160
|
+
let count = 0;
|
|
161
|
+
for (const family of families){
|
|
162
|
+
const bucket = [];
|
|
163
|
+
familyFiles[family] = bucket;
|
|
164
|
+
const files = fonts[family];
|
|
165
|
+
if (!files) continue;
|
|
166
|
+
for(let i = 0; i < files.length; i++){
|
|
167
|
+
const font = files[i];
|
|
168
|
+
if (!font?.data) continue;
|
|
169
|
+
try {
|
|
170
|
+
const ext = font.extension || font.filename.split('.').pop()?.toLowerCase() || 'woff2';
|
|
171
|
+
const weight = font.weight || '400';
|
|
172
|
+
const isItalic = font.style === 'italic';
|
|
173
|
+
// A slnt-axis italic declares `oblique <angle>` so the browser drives the axis; a true
|
|
174
|
+
// italic (explicit file or ital axis) declares plain `italic`.
|
|
175
|
+
const style = isItalic && font.obliqueAngle ? `oblique ${font.obliqueAngle}deg` : font.style || 'normal';
|
|
176
|
+
// A variable font's weight is a "min max" range; collapse the space for a filename-safe
|
|
177
|
+
// slug (sans-100-900). The emitted `weight` below keeps the range.
|
|
178
|
+
const weightSlug = weight.replace(/\s+/g, '-');
|
|
179
|
+
// Distinct filename per weight/style; append the index if two files share one.
|
|
180
|
+
const base = `${family}-${weightSlug}${isItalic ? '-italic' : ''}`;
|
|
181
|
+
const fileName = bucket.some((f)=>f.path.endsWith(`/${base}.${ext}`)) ? `${base}-${i}` : base;
|
|
182
|
+
fs.writeFileSync(path.join(FONT_FILES_DIR, `${fileName}.${ext}`), Buffer.from(font.data, 'base64'));
|
|
183
|
+
bucket.push({
|
|
184
|
+
path: `${localPrefix}/${fileName}.${ext}`,
|
|
185
|
+
weight,
|
|
186
|
+
style
|
|
187
|
+
});
|
|
188
|
+
count++;
|
|
189
|
+
} catch (err) {
|
|
190
|
+
console.warn(colors.red(`Failed to write ${family} font (weight ${font.weight ?? '?'})`));
|
|
191
|
+
if (opts.verbose) console.warn(err);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (bucket.length) console.log(`${colors.green('✓')} Downloaded ${family} font (${bucket.length} weight${bucket.length === 1 ? '' : 's'})`);
|
|
195
|
+
}
|
|
196
|
+
generateFontDefinitions(familyFiles);
|
|
197
|
+
if (count === 0) {
|
|
198
|
+
console.log(colors.orange('\nNo active fonts returned — generated an empty definition.'));
|
|
199
|
+
// Newer servers say WHY each family came back empty (older ones omit `diagnostics`).
|
|
200
|
+
for (const [family, d] of Object.entries(manifest?.diagnostics ?? {})){
|
|
201
|
+
if (!d) continue;
|
|
202
|
+
const name = d.typeface ? `'${d.typeface}'` : 'a typeface';
|
|
203
|
+
if (!d.selected) console.log(colors.orange(` ${family}: no typeface selected in the fontSet global`));
|
|
204
|
+
else if (d.optimizedFiles === 0) console.log(colors.orange(` ${family}: ${name} selected but has 0 optimized files — did the subsetter run on the server? (Next.js: serverExternalPackages: ['subset-font', 'harfbuzzjs', 'fontkit'])`));
|
|
205
|
+
else if (d.readFailures > 0) console.log(colors.orange(` ${family}: ${name} selected but ${d.readFailures}/${d.optimizedFiles} optimized files could not be read from storage`));
|
|
206
|
+
}
|
|
207
|
+
console.log('');
|
|
208
|
+
} else console.log(colors.green(`\n✓ Font definitions generated (${count} font file${count === 1 ? '' : 's'})\n`));
|
|
209
|
+
} catch (err) {
|
|
210
|
+
// Any unexpected failure → empty definition, so a broken run never leaves a stale one that
|
|
211
|
+
// imports font files that aren't on disk (the bug this guards against).
|
|
212
|
+
warnAndEmpty('Unexpected error during font download', err);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
//# sourceMappingURL=downloadFonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/scripts/downloadFonts.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport dotenv from 'dotenv'\n\nimport type { ExportFontsResponse } from '../endpoints/exportFonts'\nimport { familyExportName, familyVarSuffix } from '../lib/families'\n\nconst colors = {\n blue: (t: string) => `\\x1b[34m${t}\\x1b[0m`,\n green: (t: string) => `\\x1b[32m${t}\\x1b[0m`,\n red: (t: string) => `\\x1b[31m${t}\\x1b[0m`,\n orange: (t: string) => `\\x1b[33m${t}\\x1b[0m`,\n}\n\n/** Connection-refused / unreachable host — the DESIGNED `predev` state (server not up yet), never\n * an error. Node buries the code under `cause` (often an AggregateError), so walk the chain. */\nconst DOWN_CODES = /ECONNREFUSED|ENOTFOUND|EHOSTUNREACH/\nconst isServerDown = (err: unknown): boolean => {\n if (!err || typeof err !== 'object') return false\n const { code, message, cause, errors } = err as { code?: string; message?: string; cause?: unknown; errors?: unknown[] }\n if (DOWN_CODES.test(code ?? '') || DOWN_CODES.test(message ?? '')) return true\n return isServerDown(cause) || (Array.isArray(errors) && errors.some(isServerDown))\n}\n\n// A family key. `sans`/`serif`/`mono`/`display` by default, but the plugin's `families` option can\n// replace or extend them — so this CLI never hardcodes the list; it discovers the active families\n// from the keys of the export response and derives each family's `next/font` export name + CSS\n// variable from the same shared convention (`sans` → `fontSans` / `--font-setSans`).\ntype Family = string\n\n/** A written weight file, ready to emit into a generated `localFont` `src` array. */\ntype WeightFile = { path: string; weight: string; style: string }\n\nexport type RunDownloadFontsOptions = {\n /** Directory for downloaded font files. Default `./public/fonts` or `PAYLOAD_FONTS_OUTPUT_DIR`. */\n fontsOutputDir?: string\n /** Generated `next/font/local` module path. Default `./src/app/definition.ts` or `PAYLOAD_FONTS_DEFINITION_FILE`. */\n definitionFile?: string\n /** Dotenv file to load before reading env. Default `./.env.local` then `./.env` (Next\n * convention, `.env.local` wins), or `PAYLOAD_FONTS_ENV_FILE` to load exactly one file. */\n envFile?: string\n /**\n * `src` path passed to `localFont()` in the generated file (relative to the definition file's\n * directory). Default `../../public/fonts` or `PAYLOAD_FONTS_SRC_PREFIX`. If you change\n * `fontsOutputDir`, set this accordingly.\n */\n localFontSrcPrefix?: string\n /**\n * Prefix for the CSS custom properties emitted by the generated `localFont()` calls. The slot\n * name is appended capitalised (e.g. `--font-setSans`). Default `--font-set` or\n * `PAYLOAD_FONTS_CSS_VAR_PREFIX`. Change it only if your stylesheet references different names.\n */\n cssVariablePrefix?: string\n /** Base URL of the running Payload instance to fetch from. Default `FONT_DOWNLOAD_URL`. */\n siteUrl?: string\n /**\n * Path of the plugin's fonts export endpoint, resolved against the site URL. Default\n * `/api/fonts/export` or `PAYLOAD_FONTS_ENDPOINT`.\n */\n endpointPath?: string\n /**\n * When true, failures also print the full underlying error object (stack, cause, …). Defaults\n * to false (or `PAYLOAD_FONTS_VERBOSE`), so a routine local failure shows only the short\n * message. Enable with the `--verbose` / `-v` CLI flag or `PAYLOAD_FONTS_VERBOSE=true` when you\n * need to debug the error itself.\n */\n verbose?: boolean\n}\n\nfunction resolveOptions(overrides?: RunDownloadFontsOptions) {\n // An explicit env file (option or PAYLOAD_FONTS_ENV_FILE) is loaded alone; otherwise follow the\n // Next convention — `.env.local` first so its values win over `.env` (dotenv keeps the first).\n const explicitEnvFile = overrides?.envFile ?? process.env.PAYLOAD_FONTS_ENV_FILE\n return {\n fontsOutputDir: overrides?.fontsOutputDir ?? process.env.PAYLOAD_FONTS_OUTPUT_DIR ?? './public/fonts',\n definitionFile: overrides?.definitionFile ?? process.env.PAYLOAD_FONTS_DEFINITION_FILE ?? './src/app/definition.ts',\n envFiles: explicitEnvFile ? [explicitEnvFile] : ['./.env.local', './.env'],\n localFontSrcPrefix: overrides?.localFontSrcPrefix ?? process.env.PAYLOAD_FONTS_SRC_PREFIX ?? '../../public/fonts',\n cssVariablePrefix: overrides?.cssVariablePrefix ?? process.env.PAYLOAD_FONTS_CSS_VAR_PREFIX ?? '--font-set',\n endpointPath: overrides?.endpointPath ?? process.env.PAYLOAD_FONTS_ENDPOINT ?? '/api/fonts/export',\n verbose: overrides?.verbose ?? process.env.PAYLOAD_FONTS_VERBOSE === 'true',\n }\n}\n\nexport async function runDownloadFonts(overrides?: RunDownloadFontsOptions): Promise<void> {\n const opts = resolveOptions(overrides)\n dotenv.config({ path: opts.envFiles, quiet: true })\n\n const FONT_FILES_DIR = opts.fontsOutputDir\n const FONT_DEFINITION_FILE = opts.definitionFile\n const localPrefix = opts.localFontSrcPrefix.replace(/\\/$/, '')\n\n function generateFontDefinitions(familyFiles: Record<Family, WeightFile[]>): void {\n // One `localFont()` per family with files, each with an array of weighted `src` entries — so\n // multiple weights collapse into a single CSS variable for that family. The export name +\n // variable are derived from the family key by the shared convention (`sans` → `fontSans` /\n // `<prefix>Sans`).\n const configs = Object.entries(familyFiles)\n .filter(([, files]) => files.length > 0)\n .map(([family, files]) => ({ name: familyExportName(family), files, variable: `${opts.cssVariablePrefix}${familyVarSuffix(family)}` }))\n\n const declarations = configs\n .map((c) => {\n const src = c.files.map((f) => `{ path: '${f.path}', weight: '${f.weight}', style: '${f.style}' }`).join(', ')\n return `const ${c.name} = localFont({ src: [${src}], variable: '${c.variable}' })`\n })\n .join('\\n')\n const exports = configs.map((c) => c.name).join(', ')\n\n fs.mkdirSync(path.dirname(FONT_DEFINITION_FILE), { recursive: true })\n\n // No-fonts stub omits the `localFont` import entirely so the generated file\n // passes any consumer's unused-import lint (eslint or Biome) as-is.\n fs.writeFileSync(\n FONT_DEFINITION_FILE,\n configs.length === 0\n ? `// DO NOT EDIT MANUALLY. THIS FILE IS AUTOMATICALLY GENERATED.\n\n// No fonts available\n\nconst fonts = {}\nexport default fonts\n`\n : `// DO NOT EDIT MANUALLY. THIS FILE IS AUTOMATICALLY GENERATED.\nimport localFont from 'next/font/local'\n\n${declarations}\n\nconst fonts = { ${exports} }\nexport default fonts\n`,\n )\n }\n\n /**\n * Reset the generated module to an empty-but-valid stub. Called on EVERY error / skip path so a\n * failed or partial run never leaves a `definition.ts` that imports font files which aren't on\n * disk — a gitignored `public/fonts/` on a fresh checkout, or a dir wiped mid-run — which would\n * break `next build` with \"Can't resolve\". It ALWAYS overwrites: a stale definition surviving a\n * failure is the bug we're fixing (the atomic version only wrote this stub when the file was\n * absent), so a definition is never preserved on error.\n */\n function writeEmptyDefinitions(): void {\n generateFontDefinitions({})\n }\n\n function wipeFontFiles(): void {\n if (!fs.existsSync(FONT_FILES_DIR)) fs.mkdirSync(FONT_FILES_DIR, { recursive: true })\n // Only unlink files — a stray subdirectory would make unlinkSync throw EISDIR.\n for (const file of fs.readdirSync(FONT_FILES_DIR)) {\n const filePath = path.join(FONT_FILES_DIR, file)\n if (fs.statSync(filePath).isFile()) fs.unlinkSync(filePath)\n }\n }\n\n /** Report a failure and reset the definition to empty, so the build still compiles. */\n function warnAndEmpty(message: string, error?: unknown): void {\n console.warn(colors.red(message))\n if (error) {\n if (opts.verbose) console.warn(error)\n else console.warn(colors.orange('Re-run with --verbose (or set PAYLOAD_FONTS_VERBOSE=true) to see the full error.'))\n }\n console.warn(colors.orange('Font download failed — wrote an empty definition so the build can proceed.'))\n writeEmptyDefinitions()\n }\n\n // Any failure anywhere in the run resets the definition to empty (via warnAndEmpty on the\n // handled paths, and the catch below for anything unexpected).\n try {\n console.log(colors.blue('Starting Font Download...\\n'))\n\n const siteUrl = overrides?.siteUrl ?? process.env.FONT_DOWNLOAD_URL\n const secret = process.env.PAYLOAD_SECRET\n if (!siteUrl || !secret) {\n const searched = ` (searched ${opts.envFiles.join(', ')})`\n if (!siteUrl) console.warn(colors.red(`Missing required environment variable: FONT_DOWNLOAD_URL${searched}`))\n if (!secret) console.warn(colors.red(`Missing required environment variable: PAYLOAD_SECRET${searched}`))\n console.warn(colors.orange('Font download skipped — wrote an empty definition so the build can proceed.'))\n writeEmptyDefinitions()\n return\n }\n if (!/^https?:\\/\\//i.test(siteUrl) || !URL.canParse(siteUrl)) {\n warnAndEmpty(`FONT_DOWNLOAD_URL is not a valid http(s) URL: \"${siteUrl}\" — expected e.g. http://localhost:3000`)\n return\n }\n\n // Fetch the active fonts from the plugin's export endpoint, authenticating with the project's\n // PAYLOAD_SECRET.\n const endpoint = new URL(opts.endpointPath, siteUrl).toString()\n let manifest: ExportFontsResponse\n try {\n const res = await fetch(endpoint, { headers: { Authorization: `Bearer ${secret}` } })\n if (!res.ok) {\n const hint =\n res.status === 401 || res.status === 403\n ? \" — your local PAYLOAD_SECRET doesn't match the server's\"\n : res.status === 404\n ? ' — is the fonts plugin registered on that app? (or set PAYLOAD_FONTS_ENDPOINT)'\n : ''\n warnAndEmpty(`Font export endpoint returned HTTP ${res.status} ${res.statusText}${hint}`)\n return\n }\n manifest = (await res.json()) as ExportFontsResponse\n } catch (err) {\n if (isServerDown(err)) {\n // The DESIGNED predev state: `predev` runs before the dev server exists. Not an error.\n console.log(`[payload-fonts] no running Payload at ${endpoint} — wrote the empty dev stub (DevFonts serves fonts at runtime in dev).`)\n writeEmptyDefinitions()\n return\n }\n warnAndEmpty(`Could not reach the font export endpoint at ${endpoint}`, err)\n return\n }\n\n const fonts = manifest?.fonts ?? {}\n\n wipeFontFiles()\n\n // Discover the active families from the response keys (the plugin's `families` option drives them).\n const families: Family[] = Object.keys(fonts)\n const familyFiles: Record<Family, WeightFile[]> = {}\n let count = 0\n for (const family of families) {\n const bucket: WeightFile[] = []\n familyFiles[family] = bucket\n const files = fonts[family]\n if (!files) continue\n for (let i = 0; i < files.length; i++) {\n const font = files[i]\n if (!font?.data) continue\n try {\n const ext = font.extension || font.filename.split('.').pop()?.toLowerCase() || 'woff2'\n const weight = font.weight || '400'\n const isItalic = font.style === 'italic'\n // A slnt-axis italic declares `oblique <angle>` so the browser drives the axis; a true\n // italic (explicit file or ital axis) declares plain `italic`.\n const style = isItalic && font.obliqueAngle ? `oblique ${font.obliqueAngle}deg` : font.style || 'normal'\n // A variable font's weight is a \"min max\" range; collapse the space for a filename-safe\n // slug (sans-100-900). The emitted `weight` below keeps the range.\n const weightSlug = weight.replace(/\\s+/g, '-')\n // Distinct filename per weight/style; append the index if two files share one.\n const base = `${family}-${weightSlug}${isItalic ? '-italic' : ''}`\n const fileName = bucket.some((f) => f.path.endsWith(`/${base}.${ext}`)) ? `${base}-${i}` : base\n fs.writeFileSync(path.join(FONT_FILES_DIR, `${fileName}.${ext}`), Buffer.from(font.data, 'base64'))\n bucket.push({ path: `${localPrefix}/${fileName}.${ext}`, weight, style })\n count++\n } catch (err) {\n console.warn(colors.red(`Failed to write ${family} font (weight ${font.weight ?? '?'})`))\n if (opts.verbose) console.warn(err)\n }\n }\n if (bucket.length)\n console.log(`${colors.green('✓')} Downloaded ${family} font (${bucket.length} weight${bucket.length === 1 ? '' : 's'})`)\n }\n\n generateFontDefinitions(familyFiles)\n\n if (count === 0) {\n console.log(colors.orange('\\nNo active fonts returned — generated an empty definition.'))\n // Newer servers say WHY each family came back empty (older ones omit `diagnostics`).\n for (const [family, d] of Object.entries(manifest?.diagnostics ?? {})) {\n if (!d) continue\n const name = d.typeface ? `'${d.typeface}'` : 'a typeface'\n if (!d.selected) console.log(colors.orange(` ${family}: no typeface selected in the fontSet global`))\n else if (d.optimizedFiles === 0)\n console.log(\n colors.orange(\n ` ${family}: ${name} selected but has 0 optimized files — did the subsetter run on the server? (Next.js: serverExternalPackages: ['subset-font', 'harfbuzzjs', 'fontkit'])`,\n ),\n )\n else if (d.readFailures > 0)\n console.log(\n colors.orange(\n ` ${family}: ${name} selected but ${d.readFailures}/${d.optimizedFiles} optimized files could not be read from storage`,\n ),\n )\n }\n console.log('')\n } else console.log(colors.green(`\\n✓ Font definitions generated (${count} font file${count === 1 ? '' : 's'})\\n`))\n } catch (err) {\n // Any unexpected failure → empty definition, so a broken run never leaves a stale one that\n // imports font files that aren't on disk (the bug this guards against).\n warnAndEmpty('Unexpected error during font download', err)\n }\n}\n"],"names":["fs","path","dotenv","familyExportName","familyVarSuffix","colors","blue","t","green","red","orange","DOWN_CODES","isServerDown","err","code","message","cause","errors","test","Array","isArray","some","resolveOptions","overrides","explicitEnvFile","envFile","process","env","PAYLOAD_FONTS_ENV_FILE","fontsOutputDir","PAYLOAD_FONTS_OUTPUT_DIR","definitionFile","PAYLOAD_FONTS_DEFINITION_FILE","envFiles","localFontSrcPrefix","PAYLOAD_FONTS_SRC_PREFIX","cssVariablePrefix","PAYLOAD_FONTS_CSS_VAR_PREFIX","endpointPath","PAYLOAD_FONTS_ENDPOINT","verbose","PAYLOAD_FONTS_VERBOSE","runDownloadFonts","opts","config","quiet","FONT_FILES_DIR","FONT_DEFINITION_FILE","localPrefix","replace","generateFontDefinitions","familyFiles","configs","Object","entries","filter","files","length","map","family","name","variable","declarations","c","src","f","weight","style","join","exports","mkdirSync","dirname","recursive","writeFileSync","writeEmptyDefinitions","wipeFontFiles","existsSync","file","readdirSync","filePath","statSync","isFile","unlinkSync","warnAndEmpty","error","console","warn","log","siteUrl","FONT_DOWNLOAD_URL","secret","PAYLOAD_SECRET","searched","URL","canParse","endpoint","toString","manifest","res","fetch","headers","Authorization","ok","hint","status","statusText","json","fonts","families","keys","count","bucket","i","font","data","ext","extension","filename","split","pop","toLowerCase","isItalic","obliqueAngle","weightSlug","base","fileName","endsWith","Buffer","from","push","d","diagnostics","typeface","selected","optimizedFiles","readFailures"],"mappings":"AAAA,OAAOA,QAAQ,UAAS;AACxB,OAAOC,UAAU,YAAW;AAE5B,OAAOC,YAAY,SAAQ;AAG3B,SAASC,gBAAgB,EAAEC,eAAe,QAAQ,qBAAiB;AAEnE,MAAMC,SAAS;IACbC,MAAM,CAACC,IAAc,CAAC,QAAQ,EAAEA,EAAE,OAAO,CAAC;IAC1CC,OAAO,CAACD,IAAc,CAAC,QAAQ,EAAEA,EAAE,OAAO,CAAC;IAC3CE,KAAK,CAACF,IAAc,CAAC,QAAQ,EAAEA,EAAE,OAAO,CAAC;IACzCG,QAAQ,CAACH,IAAc,CAAC,QAAQ,EAAEA,EAAE,OAAO,CAAC;AAC9C;AAEA;+FAC+F,GAC/F,MAAMI,aAAa;AACnB,MAAMC,eAAe,CAACC;IACpB,IAAI,CAACA,OAAO,OAAOA,QAAQ,UAAU,OAAO;IAC5C,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGJ;IACzC,IAAIF,WAAWO,IAAI,CAACJ,QAAQ,OAAOH,WAAWO,IAAI,CAACH,WAAW,KAAK,OAAO;IAC1E,OAAOH,aAAaI,UAAWG,MAAMC,OAAO,CAACH,WAAWA,OAAOI,IAAI,CAACT;AACtE;AA+CA,SAASU,eAAeC,SAAmC;IACzD,gGAAgG;IAChG,+FAA+F;IAC/F,MAAMC,kBAAkBD,WAAWE,WAAWC,QAAQC,GAAG,CAACC,sBAAsB;IAChF,OAAO;QACLC,gBAAgBN,WAAWM,kBAAkBH,QAAQC,GAAG,CAACG,wBAAwB,IAAI;QACrFC,gBAAgBR,WAAWQ,kBAAkBL,QAAQC,GAAG,CAACK,6BAA6B,IAAI;QAC1FC,UAAUT,kBAAkB;YAACA;SAAgB,GAAG;YAAC;YAAgB;SAAS;QAC1EU,oBAAoBX,WAAWW,sBAAsBR,QAAQC,GAAG,CAACQ,wBAAwB,IAAI;QAC7FC,mBAAmBb,WAAWa,qBAAqBV,QAAQC,GAAG,CAACU,4BAA4B,IAAI;QAC/FC,cAAcf,WAAWe,gBAAgBZ,QAAQC,GAAG,CAACY,sBAAsB,IAAI;QAC/EC,SAASjB,WAAWiB,WAAWd,QAAQC,GAAG,CAACc,qBAAqB,KAAK;IACvE;AACF;AAEA,OAAO,eAAeC,iBAAiBnB,SAAmC;IACxE,MAAMoB,OAAOrB,eAAeC;IAC5BrB,OAAO0C,MAAM,CAAC;QAAE3C,MAAM0C,KAAKV,QAAQ;QAAEY,OAAO;IAAK;IAEjD,MAAMC,iBAAiBH,KAAKd,cAAc;IAC1C,MAAMkB,uBAAuBJ,KAAKZ,cAAc;IAChD,MAAMiB,cAAcL,KAAKT,kBAAkB,CAACe,OAAO,CAAC,OAAO;IAE3D,SAASC,wBAAwBC,WAAyC;QACxE,6FAA6F;QAC7F,0FAA0F;QAC1F,2FAA2F;QAC3F,mBAAmB;QACnB,MAAMC,UAAUC,OAAOC,OAAO,CAACH,aAC5BI,MAAM,CAAC,CAAC,GAAGC,MAAM,GAAKA,MAAMC,MAAM,GAAG,GACrCC,GAAG,CAAC,CAAC,CAACC,QAAQH,MAAM,GAAM,CAAA;gBAAEI,MAAMzD,iBAAiBwD;gBAASH;gBAAOK,UAAU,GAAGlB,KAAKP,iBAAiB,GAAGhC,gBAAgBuD,SAAS;YAAC,CAAA;QAEtI,MAAMG,eAAeV,QAClBM,GAAG,CAAC,CAACK;YACJ,MAAMC,MAAMD,EAAEP,KAAK,CAACE,GAAG,CAAC,CAACO,IAAM,CAAC,SAAS,EAAEA,EAAEhE,IAAI,CAAC,YAAY,EAAEgE,EAAEC,MAAM,CAAC,WAAW,EAAED,EAAEE,KAAK,CAAC,GAAG,CAAC,EAAEC,IAAI,CAAC;YACzG,OAAO,CAAC,MAAM,EAAEL,EAAEH,IAAI,CAAC,qBAAqB,EAAEI,IAAI,cAAc,EAAED,EAAEF,QAAQ,CAAC,IAAI,CAAC;QACpF,GACCO,IAAI,CAAC;QACR,MAAMC,UAAUjB,QAAQM,GAAG,CAAC,CAACK,IAAMA,EAAEH,IAAI,EAAEQ,IAAI,CAAC;QAEhDpE,GAAGsE,SAAS,CAACrE,KAAKsE,OAAO,CAACxB,uBAAuB;YAAEyB,WAAW;QAAK;QAEnE,4EAA4E;QAC5E,oEAAoE;QACpExE,GAAGyE,aAAa,CACd1B,sBACAK,QAAQK,MAAM,KAAK,IACf,CAAC;;;;;;AAMX,CAAC,GACS,CAAC;;;AAGX,EAAEK,aAAa;;gBAEC,EAAEO,QAAQ;;AAE1B,CAAC;IAEC;IAEA;;;;;;;GAOC,GACD,SAASK;QACPxB,wBAAwB,CAAC;IAC3B;IAEA,SAASyB;QACP,IAAI,CAAC3E,GAAG4E,UAAU,CAAC9B,iBAAiB9C,GAAGsE,SAAS,CAACxB,gBAAgB;YAAE0B,WAAW;QAAK;QACnF,+EAA+E;QAC/E,KAAK,MAAMK,QAAQ7E,GAAG8E,WAAW,CAAChC,gBAAiB;YACjD,MAAMiC,WAAW9E,KAAKmE,IAAI,CAACtB,gBAAgB+B;YAC3C,IAAI7E,GAAGgF,QAAQ,CAACD,UAAUE,MAAM,IAAIjF,GAAGkF,UAAU,CAACH;QACpD;IACF;IAEA,qFAAqF,GACrF,SAASI,aAAapE,OAAe,EAAEqE,KAAe;QACpDC,QAAQC,IAAI,CAACjF,OAAOI,GAAG,CAACM;QACxB,IAAIqE,OAAO;YACT,IAAIzC,KAAKH,OAAO,EAAE6C,QAAQC,IAAI,CAACF;iBAC1BC,QAAQC,IAAI,CAACjF,OAAOK,MAAM,CAAC;QAClC;QACA2E,QAAQC,IAAI,CAACjF,OAAOK,MAAM,CAAC;QAC3BgE;IACF;IAEA,0FAA0F;IAC1F,+DAA+D;IAC/D,IAAI;QACFW,QAAQE,GAAG,CAAClF,OAAOC,IAAI,CAAC;QAExB,MAAMkF,UAAUjE,WAAWiE,WAAW9D,QAAQC,GAAG,CAAC8D,iBAAiB;QACnE,MAAMC,SAAShE,QAAQC,GAAG,CAACgE,cAAc;QACzC,IAAI,CAACH,WAAW,CAACE,QAAQ;YACvB,MAAME,WAAW,CAAC,WAAW,EAAEjD,KAAKV,QAAQ,CAACmC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,IAAI,CAACoB,SAASH,QAAQC,IAAI,CAACjF,OAAOI,GAAG,CAAC,CAAC,wDAAwD,EAAEmF,UAAU;YAC3G,IAAI,CAACF,QAAQL,QAAQC,IAAI,CAACjF,OAAOI,GAAG,CAAC,CAAC,qDAAqD,EAAEmF,UAAU;YACvGP,QAAQC,IAAI,CAACjF,OAAOK,MAAM,CAAC;YAC3BgE;YACA;QACF;QACA,IAAI,CAAC,gBAAgBxD,IAAI,CAACsE,YAAY,CAACK,IAAIC,QAAQ,CAACN,UAAU;YAC5DL,aAAa,CAAC,+CAA+C,EAAEK,QAAQ,uCAAuC,CAAC;YAC/G;QACF;QAEA,8FAA8F;QAC9F,kBAAkB;QAClB,MAAMO,WAAW,IAAIF,IAAIlD,KAAKL,YAAY,EAAEkD,SAASQ,QAAQ;QAC7D,IAAIC;QACJ,IAAI;YACF,MAAMC,MAAM,MAAMC,MAAMJ,UAAU;gBAAEK,SAAS;oBAAEC,eAAe,CAAC,OAAO,EAAEX,QAAQ;gBAAC;YAAE;YACnF,IAAI,CAACQ,IAAII,EAAE,EAAE;gBACX,MAAMC,OACJL,IAAIM,MAAM,KAAK,OAAON,IAAIM,MAAM,KAAK,MACjC,4DACAN,IAAIM,MAAM,KAAK,MACb,mFACA;gBACRrB,aAAa,CAAC,mCAAmC,EAAEe,IAAIM,MAAM,CAAC,CAAC,EAAEN,IAAIO,UAAU,GAAGF,MAAM;gBACxF;YACF;YACAN,WAAY,MAAMC,IAAIQ,IAAI;QAC5B,EAAE,OAAO7F,KAAK;YACZ,IAAID,aAAaC,MAAM;gBACrB,uFAAuF;gBACvFwE,QAAQE,GAAG,CAAC,CAAC,sCAAsC,EAAEQ,SAAS,sEAAsE,CAAC;gBACrIrB;gBACA;YACF;YACAS,aAAa,CAAC,4CAA4C,EAAEY,UAAU,EAAElF;YACxE;QACF;QAEA,MAAM8F,QAAQV,UAAUU,SAAS,CAAC;QAElChC;QAEA,oGAAoG;QACpG,MAAMiC,WAAqBvD,OAAOwD,IAAI,CAACF;QACvC,MAAMxD,cAA4C,CAAC;QACnD,IAAI2D,QAAQ;QACZ,KAAK,MAAMnD,UAAUiD,SAAU;YAC7B,MAAMG,SAAuB,EAAE;YAC/B5D,WAAW,CAACQ,OAAO,GAAGoD;YACtB,MAAMvD,QAAQmD,KAAK,CAAChD,OAAO;YAC3B,IAAI,CAACH,OAAO;YACZ,IAAK,IAAIwD,IAAI,GAAGA,IAAIxD,MAAMC,MAAM,EAAEuD,IAAK;gBACrC,MAAMC,OAAOzD,KAAK,CAACwD,EAAE;gBACrB,IAAI,CAACC,MAAMC,MAAM;gBACjB,IAAI;oBACF,MAAMC,MAAMF,KAAKG,SAAS,IAAIH,KAAKI,QAAQ,CAACC,KAAK,CAAC,KAAKC,GAAG,IAAIC,iBAAiB;oBAC/E,MAAMtD,SAAS+C,KAAK/C,MAAM,IAAI;oBAC9B,MAAMuD,WAAWR,KAAK9C,KAAK,KAAK;oBAChC,uFAAuF;oBACvF,+DAA+D;oBAC/D,MAAMA,QAAQsD,YAAYR,KAAKS,YAAY,GAAG,CAAC,QAAQ,EAAET,KAAKS,YAAY,CAAC,GAAG,CAAC,GAAGT,KAAK9C,KAAK,IAAI;oBAChG,wFAAwF;oBACxF,mEAAmE;oBACnE,MAAMwD,aAAazD,OAAOjB,OAAO,CAAC,QAAQ;oBAC1C,+EAA+E;oBAC/E,MAAM2E,OAAO,GAAGjE,OAAO,CAAC,EAAEgE,aAAaF,WAAW,YAAY,IAAI;oBAClE,MAAMI,WAAWd,OAAO1F,IAAI,CAAC,CAAC4C,IAAMA,EAAEhE,IAAI,CAAC6H,QAAQ,CAAC,CAAC,CAAC,EAAEF,KAAK,CAAC,EAAET,KAAK,KAAK,GAAGS,KAAK,CAAC,EAAEZ,GAAG,GAAGY;oBAC3F5H,GAAGyE,aAAa,CAACxE,KAAKmE,IAAI,CAACtB,gBAAgB,GAAG+E,SAAS,CAAC,EAAEV,KAAK,GAAGY,OAAOC,IAAI,CAACf,KAAKC,IAAI,EAAE;oBACzFH,OAAOkB,IAAI,CAAC;wBAAEhI,MAAM,GAAG+C,YAAY,CAAC,EAAE6E,SAAS,CAAC,EAAEV,KAAK;wBAAEjD;wBAAQC;oBAAM;oBACvE2C;gBACF,EAAE,OAAOjG,KAAK;oBACZwE,QAAQC,IAAI,CAACjF,OAAOI,GAAG,CAAC,CAAC,gBAAgB,EAAEkD,OAAO,cAAc,EAAEsD,KAAK/C,MAAM,IAAI,IAAI,CAAC,CAAC;oBACvF,IAAIvB,KAAKH,OAAO,EAAE6C,QAAQC,IAAI,CAACzE;gBACjC;YACF;YACA,IAAIkG,OAAOtD,MAAM,EACf4B,QAAQE,GAAG,CAAC,GAAGlF,OAAOG,KAAK,CAAC,KAAK,YAAY,EAAEmD,OAAO,OAAO,EAAEoD,OAAOtD,MAAM,CAAC,OAAO,EAAEsD,OAAOtD,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;QAC3H;QAEAP,wBAAwBC;QAExB,IAAI2D,UAAU,GAAG;YACfzB,QAAQE,GAAG,CAAClF,OAAOK,MAAM,CAAC;YAC1B,qFAAqF;YACrF,KAAK,MAAM,CAACiD,QAAQuE,EAAE,IAAI7E,OAAOC,OAAO,CAAC2C,UAAUkC,eAAe,CAAC,GAAI;gBACrE,IAAI,CAACD,GAAG;gBACR,MAAMtE,OAAOsE,EAAEE,QAAQ,GAAG,CAAC,CAAC,EAAEF,EAAEE,QAAQ,CAAC,CAAC,CAAC,GAAG;gBAC9C,IAAI,CAACF,EAAEG,QAAQ,EAAEhD,QAAQE,GAAG,CAAClF,OAAOK,MAAM,CAAC,CAAC,EAAE,EAAEiD,OAAO,4CAA4C,CAAC;qBAC/F,IAAIuE,EAAEI,cAAc,KAAK,GAC5BjD,QAAQE,GAAG,CACTlF,OAAOK,MAAM,CACX,CAAC,EAAE,EAAEiD,OAAO,EAAE,EAAEC,KAAK,sJAAsJ,CAAC;qBAG7K,IAAIsE,EAAEK,YAAY,GAAG,GACxBlD,QAAQE,GAAG,CACTlF,OAAOK,MAAM,CACX,CAAC,EAAE,EAAEiD,OAAO,EAAE,EAAEC,KAAK,cAAc,EAAEsE,EAAEK,YAAY,CAAC,CAAC,EAAEL,EAAEI,cAAc,CAAC,+CAA+C,CAAC;YAGhI;YACAjD,QAAQE,GAAG,CAAC;QACd,OAAOF,QAAQE,GAAG,CAAClF,OAAOG,KAAK,CAAC,CAAC,gCAAgC,EAAEsG,MAAM,UAAU,EAAEA,UAAU,IAAI,KAAK,IAAI,GAAG,CAAC;IAClH,EAAE,OAAOjG,KAAK;QACZ,2FAA2F;QAC3F,wEAAwE;QACxEsE,aAAa,yCAAyCtE;IACxD;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pro-laico/payload-fonts",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Custom fonts for Payload CMS: a Font typeface collection that subsets uploaded files to served WOFF2s, an optional fontSet global, an export endpoint + CLI that writes the active fonts to disk for next/font/local, and declarative seeding.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/pro-laico/payload-plugins.git",
|
|
9
|
+
"directory": "packages/payload-fonts"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"payload",
|
|
13
|
+
"payloadcms",
|
|
14
|
+
"plugin",
|
|
15
|
+
"fonts",
|
|
16
|
+
"font",
|
|
17
|
+
"woff2",
|
|
18
|
+
"next-font"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": [
|
|
21
|
+
"*.scss",
|
|
22
|
+
"*.css"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"bin": {
|
|
31
|
+
"payload-fonts-download": "./dist/scripts/cli.js"
|
|
32
|
+
},
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js",
|
|
37
|
+
"default": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./admin/FontOriginalUpload": {
|
|
40
|
+
"types": "./dist/components/admin/FontOriginalUpload.d.ts",
|
|
41
|
+
"import": "./dist/components/admin/FontOriginalUpload.js",
|
|
42
|
+
"default": "./dist/components/admin/FontOriginalUpload.js"
|
|
43
|
+
},
|
|
44
|
+
"./DevFonts": {
|
|
45
|
+
"types": "./dist/components/DevFonts.d.ts",
|
|
46
|
+
"import": "./dist/components/DevFonts.js",
|
|
47
|
+
"default": "./dist/components/DevFonts.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist"
|
|
52
|
+
],
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"dotenv": "^17.4.2",
|
|
55
|
+
"fontkit": "^2.0.4",
|
|
56
|
+
"subset-font": "^2.5.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@payloadcms/ui": "^3.0.0",
|
|
60
|
+
"next": ">=15.0.0",
|
|
61
|
+
"payload": "^3.0.0",
|
|
62
|
+
"react": "^19.0.0",
|
|
63
|
+
"react-dom": "^19.0.0"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"next": {
|
|
67
|
+
"optional": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@payloadcms/db-sqlite": "^3.85.1",
|
|
72
|
+
"@payloadcms/ui": "^3.85.1",
|
|
73
|
+
"@types/fontkit": "^2.0.9",
|
|
74
|
+
"@types/node": "^26.0.1",
|
|
75
|
+
"@types/react": "^19.2.17",
|
|
76
|
+
"@types/react-dom": "^19.2.3",
|
|
77
|
+
"@types/subset-font": "^2.3.0",
|
|
78
|
+
"next": "^16.2.9",
|
|
79
|
+
"payload": "^3.85.1",
|
|
80
|
+
"react": "^19.2.7",
|
|
81
|
+
"react-dom": "^19.2.7",
|
|
82
|
+
"typescript": "^6.0.3",
|
|
83
|
+
"vitest": "^4.1.9"
|
|
84
|
+
},
|
|
85
|
+
"engines": {
|
|
86
|
+
"node": ">=18"
|
|
87
|
+
},
|
|
88
|
+
"scripts": {
|
|
89
|
+
"build": "pnpm clean && pnpm build:types && pnpm build:swc && pnpm build:assets",
|
|
90
|
+
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
91
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
92
|
+
"test": "vitest run",
|
|
93
|
+
"test:watch": "vitest",
|
|
94
|
+
"build:swc": "swc ./src -d ./dist --config-file ../../.swcrc --strip-leading-paths",
|
|
95
|
+
"build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly --noCheck",
|
|
96
|
+
"build:assets": "copyfiles -u 1 \"src/**/*.{scss,css}\" dist"
|
|
97
|
+
}
|
|
98
|
+
}
|