@featherk/icons 0.15.8 → 0.16.1
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/README.md +25 -13
- package/dist/docs-manifest.d.ts +1 -0
- package/dist/docs-manifest.js +7 -5
- package/dist/fontawesome/build.cjs +1 -2
- package/dist/fontawesome/build.d.ts +1 -1
- package/dist/fontawesome/build.mjs +2 -3
- package/dist/fontawesome/catalog.cjs +0 -13
- package/dist/fontawesome/catalog.d.ts +0 -8
- package/dist/fontawesome/catalog.mjs +0 -13
- package/dist/fontawesome/chunks/{generate-BBurrhLv.cjs → generate-B_FxftR7.cjs} +12 -1
- package/dist/fontawesome/chunks/{generate-Zq9q2YZD.mjs → generate-DF9R65sV.mjs} +13 -2
- package/dist/fontawesome/chunks/manifest-CF473fsM.mjs +61 -0
- package/dist/fontawesome/chunks/manifest-DEhGKvmi.cjs +60 -0
- package/dist/fontawesome/cli.cjs +23 -26
- package/dist/fontawesome/cli.mjs +23 -26
- package/dist/fontawesome/generate.d.ts +7 -0
- package/dist/fontawesome/manifest.d.ts +35 -0
- package/dist/fontawesome/setup.cjs +147 -179
- package/dist/fontawesome/setup.d.ts +2 -2
- package/dist/fontawesome/setup.mjs +149 -181
- package/dist/fontawesome/vite.cjs +64 -28
- package/dist/fontawesome/vite.d.ts +25 -5
- package/dist/fontawesome/vite.mjs +65 -29
- package/docs/ADDING-ICONS.md +4 -3
- package/docs/COMING-SOON.md +24 -14
- package/docs/ICONS.md +1 -1
- package/docs/fontawesome/CreateFontAwesomeManifest.md +12 -12
- package/docs/fontawesome/FontAwesome.md +47 -48
- package/docs/fontawesome/FontAwesomeCLI.md +14 -19
- package/docs/fontawesome/FontAwesomeDeveloperSetup.md +134 -0
- package/docs/fontawesome/LICENSING.md +61 -82
- package/package.json +1 -1
- package/dist/fontawesome/chunks/manifest-BB3q10t1.mjs +0 -20
- package/dist/fontawesome/chunks/manifest-C15Xa22L.cjs +0 -19
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readFileSync,
|
|
3
|
-
import { resolve
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
4
|
import { emitKeypressEvents } from "node:readline";
|
|
5
5
|
import { parseArgs } from "node:util";
|
|
6
6
|
import { fontAwesomeCatalog, resolveFontAwesomeKeys } from "./catalog.mjs";
|
|
7
|
-
import { r as readFontAwesomeManifest } from "./chunks/manifest-
|
|
7
|
+
import { f as fontAwesomeProSourcesDir, i as isFontAwesomeIsolated, r as readFontAwesomeManifest, a as fontAwesomeManifestKeys } from "./chunks/manifest-CF473fsM.mjs";
|
|
8
8
|
const tokenVariable = "FONTAWESOME_PACKAGE_TOKEN";
|
|
9
9
|
const tokenPlaceholder = `\${${tokenVariable}}`;
|
|
10
10
|
const registry = "https://npm.fontawesome.com/";
|
|
@@ -23,30 +23,29 @@ const workspaceVariables = [
|
|
|
23
23
|
"NPM_CONFIG_WORKSPACES"
|
|
24
24
|
];
|
|
25
25
|
const usage = `Usage:
|
|
26
|
-
featherk-fontawesome-setup
|
|
27
|
-
featherk-fontawesome-setup
|
|
28
|
-
featherk-fontawesome-setup --source-root <dir> --init (--manifest <icons.json> | --keys <a,b>) [--force]
|
|
26
|
+
featherk-fontawesome-setup --manifest <icons.json> [--free-only]
|
|
27
|
+
featherk-fontawesome-setup
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
only) and installs exact pins for all selected keys as devDependencies.
|
|
33
|
-
Commit .npmrc, package.json, and package-lock.json. Later installs, including
|
|
34
|
-
CI, give ${tokenVariable} only to "npm ci --ignore-scripts", then run any
|
|
35
|
-
needed install scripts (npm rebuild for dependencies, plus the app's own) and
|
|
36
|
-
builds without it. Do not export the token persistently.
|
|
29
|
+
Run from the application root. The manifest contains
|
|
30
|
+
{ "free": [keys], "pro": [keys] }, the same file the Vite plugin reads.
|
|
37
31
|
|
|
38
|
-
--
|
|
32
|
+
--manifest (default): installs exact Free pins into the app's devDependencies
|
|
33
|
+
from public npm, and writes exact Pro pins into an isolated private source
|
|
34
|
+
project, ${fontAwesomeProSourcesDir}/, then installs it with the token. The
|
|
35
|
+
app's own install never needs the token. Rerun after changing the manifest.
|
|
36
|
+
Commit package.json, package-lock.json, and ${fontAwesomeProSourcesDir}/
|
|
37
|
+
(its node_modules is ignored).
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
--refresh-lock are refused and a lockfile is required.
|
|
39
|
+
No arguments: installs ${fontAwesomeProSourcesDir}/ from its committed
|
|
40
|
+
lockfile with the token, for CI and fresh clones. Run it after the app's own
|
|
41
|
+
"npm ci".
|
|
42
|
+
|
|
43
|
+
--free-only: Free keys only from public npm. No token, no source project.
|
|
46
44
|
|
|
47
45
|
The token comes from ${tokenVariable} or a hidden prompt in an interactive
|
|
48
|
-
terminal.
|
|
49
|
-
(CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set)
|
|
46
|
+
terminal. --manifest setup changes package.json and is refused in CI
|
|
47
|
+
(CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set). Do not export the token
|
|
48
|
+
persistently.`;
|
|
50
49
|
function promptForTerminalToken() {
|
|
51
50
|
const input = process.stdin;
|
|
52
51
|
if (!input.isTTY || typeof input.setRawMode !== "function") {
|
|
@@ -125,19 +124,13 @@ function requireNpm(context) {
|
|
|
125
124
|
return npmCli;
|
|
126
125
|
}
|
|
127
126
|
async function readKeys(values, context) {
|
|
128
|
-
if (values.keys && values.manifest) {
|
|
129
|
-
throw new Error("Provide either --keys or --manifest, not both.");
|
|
130
|
-
}
|
|
131
|
-
if (values.keys) {
|
|
132
|
-
return values.keys.split(",").map((key) => key.trim()).filter(Boolean);
|
|
133
|
-
}
|
|
134
127
|
if (!values.manifest) {
|
|
135
|
-
throw new Error("Provide --manifest
|
|
128
|
+
throw new Error("Provide --manifest. Use --help for usage.");
|
|
136
129
|
}
|
|
137
|
-
const
|
|
130
|
+
const manifest = await readFontAwesomeManifest(
|
|
138
131
|
resolve(context.cwd, values.manifest)
|
|
139
132
|
);
|
|
140
|
-
return
|
|
133
|
+
return fontAwesomeManifestKeys(manifest);
|
|
141
134
|
}
|
|
142
135
|
function resolvePins(keys) {
|
|
143
136
|
const tiers = new Map(
|
|
@@ -192,54 +185,10 @@ function checkNpmrc(config, file) {
|
|
|
192
185
|
}
|
|
193
186
|
return { fontAwesomeRegistry, hasAuth };
|
|
194
187
|
}
|
|
195
|
-
|
|
196
|
-
const { log } = context;
|
|
197
|
-
if (context.isCi) {
|
|
198
|
-
throw new Error(
|
|
199
|
-
`App-root setup changes package.json and is a local, one-time step. In CI, give ${tokenVariable} only to "npm ci --ignore-scripts", then run needed install scripts and the build without it.`
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
const appRoot = context.cwd;
|
|
203
|
-
if (!existsSync(resolve(appRoot, "package.json"))) {
|
|
204
|
-
throw new Error(
|
|
205
|
-
"Run this command from the application root (package.json not found)."
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
const freeOnly = Boolean(values["free-only"]);
|
|
209
|
-
const pins = resolvePins(await readKeys(values, context));
|
|
210
|
-
const proPins = [...pins.values()].filter((pin) => pin.tier === "pro");
|
|
211
|
-
if (freeOnly && proPins.length) {
|
|
212
|
-
throw new Error(
|
|
213
|
-
`--free-only cannot install Pro keys: ${proPins.map((pin) => pin.key).join(", ")}.`
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
if (!pins.size) {
|
|
217
|
-
throw new Error("No Font Awesome keys selected.");
|
|
218
|
-
}
|
|
219
|
-
const npmrcPath = resolve(appRoot, ".npmrc");
|
|
220
|
-
const config = existsSync(npmrcPath) ? readFileSync(npmrcPath, "utf8") : "";
|
|
221
|
-
const { fontAwesomeRegistry, hasAuth } = checkNpmrc(config, ".npmrc");
|
|
222
|
-
if (freeOnly && fontAwesomeRegistry) {
|
|
223
|
-
throw new Error(
|
|
224
|
-
`.npmrc routes @fortawesome to ${fontAwesomeRegistry}, so this app is set up for Pro. Run without --free-only.`
|
|
225
|
-
);
|
|
226
|
-
}
|
|
188
|
+
function installFreeIntoApp(pins, context) {
|
|
227
189
|
const npmCli = requireNpm(context);
|
|
228
190
|
const environment = { ...context.env };
|
|
229
|
-
|
|
230
|
-
environment[tokenVariable] = await readToken(context);
|
|
231
|
-
const missing = [];
|
|
232
|
-
if (!fontAwesomeRegistry) missing.push(npmrcLines[0], npmrcLines[1]);
|
|
233
|
-
if (!hasAuth) missing.push(npmrcLines[2], npmrcLines[3]);
|
|
234
|
-
if (missing.length) {
|
|
235
|
-
const separator = config && !config.endsWith("\n") ? "\n" : "";
|
|
236
|
-
writeFileSync(npmrcPath, `${config}${separator}${missing.join("\n")}
|
|
237
|
-
`);
|
|
238
|
-
log(
|
|
239
|
-
`${config ? "Updated" : "Created"} .npmrc with the Font Awesome registry and token placeholder.`
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
191
|
+
delete environment[tokenVariable];
|
|
243
192
|
const specs = [...pins].map(([name, pin]) => `${name}@${pin.spec}`);
|
|
244
193
|
const status = context.runNpm({
|
|
245
194
|
npmCli,
|
|
@@ -250,27 +199,17 @@ async function setupAppRoot(values, context) {
|
|
|
250
199
|
"--ignore-scripts",
|
|
251
200
|
"--no-audit",
|
|
252
201
|
"--no-fund",
|
|
253
|
-
...freeOnly ? [] : [pinRegistry],
|
|
254
202
|
...specs
|
|
255
203
|
],
|
|
256
|
-
cwd:
|
|
204
|
+
cwd: context.cwd,
|
|
257
205
|
env: environment
|
|
258
206
|
});
|
|
259
|
-
if (status
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
"Lifecycle scripts were skipped. If needed, run npm rebuild for dependency scripts and the app's own scripts (e.g. npm run prepare --if-present)."
|
|
263
|
-
);
|
|
264
|
-
if (freeOnly) {
|
|
265
|
-
log(
|
|
266
|
-
"Next: commit package.json and package-lock.json. Keep the Vite plugin's allowPro unset (Free only); no CI token is needed."
|
|
267
|
-
);
|
|
268
|
-
} else {
|
|
269
|
-
log(
|
|
270
|
-
`Next: commit .npmrc, package.json, and package-lock.json. Set allowPro: true in the Vite plugin (no sourceRoot). Later installs, including CI, give ${tokenVariable} only to "npm ci --ignore-scripts"; run needed install scripts and builds without it. See LICENSING.md for the TeamCity setup.`
|
|
207
|
+
if (status === 0) {
|
|
208
|
+
context.log(
|
|
209
|
+
`Installed ${specs.length} Font Awesome package(s) into the app: ${specs.join(" ")}`
|
|
271
210
|
);
|
|
272
211
|
}
|
|
273
|
-
return
|
|
212
|
+
return status;
|
|
274
213
|
}
|
|
275
214
|
function readDependencies(packageJsonPath) {
|
|
276
215
|
try {
|
|
@@ -284,109 +223,61 @@ function readDependencies(packageJsonPath) {
|
|
|
284
223
|
return void 0;
|
|
285
224
|
}
|
|
286
225
|
}
|
|
287
|
-
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
throw new Error(
|
|
291
|
-
"--init is a local, one-time step. Commit the scaffolded source project instead of generating it in CI."
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
const pins = resolvePins(await readKeys(values, context));
|
|
295
|
-
const dependencies = {};
|
|
296
|
-
const skipped = [];
|
|
297
|
-
for (const [name, pin] of pins) {
|
|
298
|
-
if (pin.tier === "pro") dependencies[name] = pin.spec;
|
|
299
|
-
else skipped.push(pin.key);
|
|
300
|
-
}
|
|
301
|
-
if (!Object.keys(dependencies).length) {
|
|
302
|
-
throw new Error(
|
|
303
|
-
"No Pro keys selected. Free packages belong in the application's own devDependencies."
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
const sortedDependencies = Object.fromEntries(
|
|
307
|
-
Object.entries(dependencies).sort()
|
|
226
|
+
function writeSourceProject(sourceRoot, proPins, context) {
|
|
227
|
+
const dependencies = Object.fromEntries(
|
|
228
|
+
[...proPins].map(([name, pin]) => [name, pin.spec]).sort()
|
|
308
229
|
);
|
|
230
|
+
const created = !existsSync(resolve(sourceRoot, "package.json"));
|
|
231
|
+
const lockfilePath = resolve(sourceRoot, "package-lock.json");
|
|
232
|
+
const removeStaleLockfile = existsSync(lockfilePath) && readDependencies(resolve(sourceRoot, "package.json")) !== JSON.stringify(dependencies);
|
|
309
233
|
const files = {
|
|
310
234
|
".npmrc": `${npmrcLines.join("\n")}
|
|
311
235
|
`,
|
|
312
236
|
".gitignore": "node_modules/\n",
|
|
313
237
|
"package.json": `${JSON.stringify(
|
|
314
238
|
{
|
|
315
|
-
name:
|
|
239
|
+
name: fontAwesomeProSourcesDir,
|
|
316
240
|
version: "0.0.0",
|
|
317
241
|
private: true,
|
|
318
|
-
dependencies
|
|
242
|
+
dependencies
|
|
319
243
|
},
|
|
320
244
|
null,
|
|
321
245
|
2
|
|
322
246
|
)}
|
|
323
247
|
`
|
|
324
248
|
};
|
|
325
|
-
const existing = Object.keys(files).filter(
|
|
326
|
-
(name) => existsSync(resolve(sourceRoot, name))
|
|
327
|
-
);
|
|
328
|
-
if (existing.length && !values.force) {
|
|
329
|
-
throw new Error(
|
|
330
|
-
`${display(sourceRoot)} already contains ${existing.join(", ")}. Use --force to overwrite.`
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
const lockfilePath = resolve(sourceRoot, "package-lock.json");
|
|
334
|
-
const removeStaleLockfile = existsSync(lockfilePath) && readDependencies(resolve(sourceRoot, "package.json")) !== JSON.stringify(sortedDependencies);
|
|
335
249
|
mkdirSync(sourceRoot, { recursive: true });
|
|
336
250
|
for (const [name, content] of Object.entries(files)) {
|
|
337
251
|
writeFileSync(resolve(sourceRoot, name), content);
|
|
338
252
|
}
|
|
339
253
|
if (removeStaleLockfile) rmSync(lockfilePath);
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
`Skipped Free keys (install them in the application instead): ${skipped.join(", ")}`
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
log(
|
|
346
|
-
`Scaffolded ${display(sourceRoot)} with ${Object.keys(dependencies).length} Pro package(s).`
|
|
254
|
+
context.log(
|
|
255
|
+
`${created ? "Created" : "Updated"} ${fontAwesomeProSourcesDir}/ with ${proPins.size} Pro package(s).`
|
|
347
256
|
);
|
|
348
257
|
if (removeStaleLockfile) {
|
|
349
|
-
log(
|
|
350
|
-
`Removed ${
|
|
258
|
+
context.log(
|
|
259
|
+
`Removed ${fontAwesomeProSourcesDir}/package-lock.json because the Pro pins changed; this install regenerates it.`
|
|
351
260
|
);
|
|
352
261
|
}
|
|
353
|
-
log(
|
|
354
|
-
"Next: run this command with --source-root and without --init, then commit the source project and its package-lock.json."
|
|
355
|
-
);
|
|
356
|
-
return 0;
|
|
357
262
|
}
|
|
358
|
-
async function installSourceProject(sourceRoot,
|
|
359
|
-
const { log, display } = context;
|
|
263
|
+
async function installSourceProject(sourceRoot, token, context) {
|
|
360
264
|
const npmCli = requireNpm(context);
|
|
361
|
-
|
|
362
|
-
if (!existsSync(resolve(sourceRoot, name))) {
|
|
363
|
-
throw new Error(
|
|
364
|
-
`${display(sourceRoot)}/${name} was not found. Check --source-root, or scaffold the project with --init.`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
const npmrc = `${display(sourceRoot)}/.npmrc`;
|
|
265
|
+
const npmrc = `${fontAwesomeProSourcesDir}/.npmrc`;
|
|
369
266
|
const { fontAwesomeRegistry, hasAuth } = checkNpmrc(
|
|
370
267
|
readFileSync(resolve(sourceRoot, ".npmrc"), "utf8"),
|
|
371
268
|
npmrc
|
|
372
269
|
);
|
|
373
270
|
if (!fontAwesomeRegistry || !hasAuth) {
|
|
374
271
|
throw new Error(
|
|
375
|
-
`${npmrc} must contain @fortawesome:registry=${registry} and ${authKey}=${tokenPlaceholder}.
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
const hasLockfile = existsSync(resolve(sourceRoot, "package-lock.json"));
|
|
379
|
-
if (context.isCi && !hasLockfile) {
|
|
380
|
-
throw new Error(
|
|
381
|
-
`${display(sourceRoot)}/package-lock.json is required in CI. Install locally first and commit the lockfile.`
|
|
272
|
+
`${npmrc} must contain @fortawesome:registry=${registry} and ${authKey}=${tokenPlaceholder}. Rerun with --manifest to rewrite it.`
|
|
382
273
|
);
|
|
383
274
|
}
|
|
384
|
-
|
|
275
|
+
const locked = existsSync(resolve(sourceRoot, "package-lock.json"));
|
|
276
|
+
if (context.isCi && !locked) {
|
|
385
277
|
throw new Error(
|
|
386
|
-
|
|
278
|
+
`${fontAwesomeProSourcesDir}/package-lock.json is required in CI. Run setup with --manifest locally first and commit the lockfile.`
|
|
387
279
|
);
|
|
388
280
|
}
|
|
389
|
-
const locked = hasLockfile && !values["refresh-lock"];
|
|
390
281
|
const environment = {
|
|
391
282
|
...context.env,
|
|
392
283
|
[tokenVariable]: await readToken(context)
|
|
@@ -406,12 +297,87 @@ async function installSourceProject(sourceRoot, values, context) {
|
|
|
406
297
|
env: environment
|
|
407
298
|
});
|
|
408
299
|
if (status !== 0) return status;
|
|
409
|
-
const lockfile = `${
|
|
410
|
-
log(
|
|
300
|
+
const lockfile = `${fontAwesomeProSourcesDir}/package-lock.json`;
|
|
301
|
+
context.log(
|
|
411
302
|
locked ? `Pro sources installed from ${lockfile}.` : `Pro sources installed. Review and commit ${lockfile}.`
|
|
412
303
|
);
|
|
304
|
+
context.log(
|
|
305
|
+
"Restart any running Vite dev server so it includes the installed Pro icons."
|
|
306
|
+
);
|
|
307
|
+
return 0;
|
|
308
|
+
}
|
|
309
|
+
async function setupFromManifest(values, context) {
|
|
310
|
+
const { log } = context;
|
|
311
|
+
const freeOnly = Boolean(values["free-only"]);
|
|
312
|
+
if (context.isCi) {
|
|
313
|
+
throw new Error(
|
|
314
|
+
`--manifest setup changes package.json and is a local step. In CI, run the app's own "npm ci", then featherk-fontawesome-setup without arguments to install ${fontAwesomeProSourcesDir}/.`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
const appRoot = context.cwd;
|
|
318
|
+
if (!existsSync(resolve(appRoot, "package.json"))) {
|
|
319
|
+
throw new Error(
|
|
320
|
+
"Run this command from the application root (package.json not found)."
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
const pins = resolvePins(await readKeys(values, context));
|
|
324
|
+
if (!pins.size) {
|
|
325
|
+
throw new Error("No Font Awesome keys selected.");
|
|
326
|
+
}
|
|
327
|
+
const freePins = new Map([...pins].filter(([, pin]) => pin.tier !== "pro"));
|
|
328
|
+
const proPins = new Map([...pins].filter(([, pin]) => pin.tier === "pro"));
|
|
329
|
+
if (freeOnly && proPins.size) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`--free-only cannot install Pro keys: ${[...proPins.values()].map((pin) => pin.key).join(", ")}.`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
const npmrcPath = resolve(appRoot, ".npmrc");
|
|
335
|
+
const config = existsSync(npmrcPath) ? readFileSync(npmrcPath, "utf8") : "";
|
|
336
|
+
const { fontAwesomeRegistry } = checkNpmrc(config, ".npmrc");
|
|
337
|
+
const sourceRoot = resolve(appRoot, fontAwesomeProSourcesDir);
|
|
338
|
+
const isolated = isFontAwesomeIsolated(appRoot);
|
|
339
|
+
if (fontAwesomeRegistry) {
|
|
340
|
+
throw new Error(
|
|
341
|
+
`.npmrc routes @fortawesome to ${fontAwesomeRegistry}, which installs Pro packages in the app itself; that layout is not supported. Remove the Font Awesome lines from .npmrc and any @fortawesome/pro-* packages from the app's devDependencies, then rerun.`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (freeOnly && isolated) {
|
|
345
|
+
throw new Error(
|
|
346
|
+
`${fontAwesomeProSourcesDir}/ exists, so this app uses Pro. Run without --free-only, or remove ${fontAwesomeProSourcesDir}/ first.`
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
if (freePins.size) {
|
|
350
|
+
const status2 = installFreeIntoApp(freePins, context);
|
|
351
|
+
if (status2 !== 0) return status2;
|
|
352
|
+
log(lifecycleNote);
|
|
353
|
+
}
|
|
354
|
+
if (!proPins.size) {
|
|
355
|
+
if (isolated) {
|
|
356
|
+
log(
|
|
357
|
+
`The manifest has no Pro keys; ${fontAwesomeProSourcesDir}/ is no longer needed and can be removed.`
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
log(
|
|
361
|
+
"Next: commit package.json and package-lock.json. Configure the Vite plugin with { manifest }; no token is needed."
|
|
362
|
+
);
|
|
363
|
+
return 0;
|
|
364
|
+
}
|
|
365
|
+
writeSourceProject(sourceRoot, proPins, context);
|
|
366
|
+
const status = await installSourceProject(sourceRoot, void 0, context);
|
|
367
|
+
if (status !== 0) return status;
|
|
368
|
+
log(
|
|
369
|
+
`Next: commit package.json, package-lock.json, and ${fontAwesomeProSourcesDir}/. Configure the Vite plugin with { manifest }; builds include Pro icons wherever ${fontAwesomeProSourcesDir}/ is installed. In CI, run the app's "npm ci" without the token, then featherk-fontawesome-setup with ${tokenVariable}, then the normal build.`
|
|
370
|
+
);
|
|
413
371
|
return 0;
|
|
414
372
|
}
|
|
373
|
+
const lifecycleNote = "Lifecycle scripts were skipped. If needed, run npm rebuild for dependency scripts and the app's own scripts (e.g. npm run prepare --if-present).";
|
|
374
|
+
const removedFlags = [
|
|
375
|
+
"--keys",
|
|
376
|
+
"--source-root",
|
|
377
|
+
"--init",
|
|
378
|
+
"--force",
|
|
379
|
+
"--refresh-lock"
|
|
380
|
+
];
|
|
415
381
|
async function runFontAwesomeSetup(args, io = {}) {
|
|
416
382
|
const cwd = io.cwd ?? process.cwd();
|
|
417
383
|
const env = io.env ?? process.env;
|
|
@@ -423,20 +389,26 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
423
389
|
isCi: Boolean(env.CI) && env.CI !== "false" || Boolean(env.TEAMCITY_VERSION || env.GITHUB_ACTIONS),
|
|
424
390
|
log: io.stdout ?? console.log,
|
|
425
391
|
promptForToken: io.promptForToken ?? promptForTerminalToken,
|
|
426
|
-
runNpm: io.runNpm ?? spawnNpm
|
|
427
|
-
display: (path) => relative(cwd, path) || "."
|
|
392
|
+
runNpm: io.runNpm ?? spawnNpm
|
|
428
393
|
};
|
|
394
|
+
const hasFlag = (flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
429
395
|
try {
|
|
396
|
+
const removed = removedFlags.find(hasFlag);
|
|
397
|
+
if (removed) {
|
|
398
|
+
throw new Error(
|
|
399
|
+
`${removed} was removed in 0.16.0. Run setup with --manifest; Pro sources always live in ${fontAwesomeProSourcesDir}/, and rerunning with --manifest updates them. Use --help for usage.`
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
if (hasFlag("--pro-in-app")) {
|
|
403
|
+
throw new Error(
|
|
404
|
+
`--pro-in-app was removed. Pro packages always install into ${fontAwesomeProSourcesDir}/, so the app's own install never needs the token. Run setup with --manifest.`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
430
407
|
const { values } = parseArgs({
|
|
431
408
|
args: [...args],
|
|
432
409
|
options: {
|
|
433
|
-
"source-root": { type: "string" },
|
|
434
410
|
"free-only": { type: "boolean" },
|
|
435
|
-
init: { type: "boolean" },
|
|
436
|
-
keys: { type: "string" },
|
|
437
411
|
manifest: { type: "string" },
|
|
438
|
-
force: { type: "boolean" },
|
|
439
|
-
"refresh-lock": { type: "boolean" },
|
|
440
412
|
help: { type: "boolean", short: "h" }
|
|
441
413
|
},
|
|
442
414
|
strict: true,
|
|
@@ -446,26 +418,22 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
446
418
|
context.log(usage);
|
|
447
419
|
return 0;
|
|
448
420
|
}
|
|
449
|
-
if (values
|
|
450
|
-
|
|
451
|
-
throw new Error(
|
|
452
|
-
"--init, --force, and --refresh-lock apply only with --source-root."
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
return await setupAppRoot(values, context);
|
|
421
|
+
if (values.manifest !== void 0) {
|
|
422
|
+
return await setupFromManifest(values, context);
|
|
456
423
|
}
|
|
457
424
|
if (values["free-only"]) {
|
|
458
|
-
throw new Error(
|
|
459
|
-
"--free-only applies only to app-root setup; an isolated source project holds Pro packages."
|
|
460
|
-
);
|
|
425
|
+
throw new Error("--free-only requires --manifest.");
|
|
461
426
|
}
|
|
462
|
-
if (
|
|
427
|
+
if (!isFontAwesomeIsolated(cwd)) {
|
|
463
428
|
throw new Error(
|
|
464
|
-
|
|
429
|
+
`${fontAwesomeProSourcesDir}/package.json was not found. Run from the application root; for first-time setup, run with --manifest <icons.json>.`
|
|
465
430
|
);
|
|
466
431
|
}
|
|
467
|
-
|
|
468
|
-
|
|
432
|
+
return await installSourceProject(
|
|
433
|
+
resolve(cwd, fontAwesomeProSourcesDir),
|
|
434
|
+
void 0,
|
|
435
|
+
context
|
|
436
|
+
);
|
|
469
437
|
} catch (error) {
|
|
470
438
|
stderr(error instanceof Error ? error.message : "Unknown error");
|
|
471
439
|
return 1;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const node_path = require("node:path");
|
|
4
4
|
const promises = require("node:fs/promises");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const generate = require("./chunks/generate-B_FxftR7.cjs");
|
|
6
|
+
const manifest = require("./chunks/manifest-DEhGKvmi.cjs");
|
|
7
7
|
const virtualId = "virtual:featherk/fontawesome";
|
|
8
8
|
const resolvedId = `\0${virtualId}`;
|
|
9
9
|
function dependencyKey(file) {
|
|
@@ -11,20 +11,56 @@ function dependencyKey(file) {
|
|
|
11
11
|
return process.platform === "win32" ? path.toLowerCase() : path;
|
|
12
12
|
}
|
|
13
13
|
function featherkFontAwesome(options) {
|
|
14
|
+
const legacy = options;
|
|
15
|
+
if (legacy.keys !== void 0 || legacy.allowPro !== void 0) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'Font Awesome Vite options "keys" and "allowPro" were removed in 0.16.0. List the keys in a { free, pro } manifest and pass { manifest: "fontawesome.keys.json" }.'
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (legacy.sourceRoot !== void 0 || legacy.proMode !== void 0) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Font Awesome Vite options "sourceRoot" and "proMode" were removed in 0.16.0. Pro sources always live in ${manifest.fontAwesomeProSourcesDir}/ and are used wherever it is installed; pass only { manifest }.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (typeof options.manifest !== "string" || !options.manifest.trim()) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
'Font Awesome Vite options require a manifest path, such as { manifest: "fontawesome.keys.json" }'
|
|
28
|
+
);
|
|
29
|
+
}
|
|
14
30
|
let root = node_path.resolve(options.root ?? process.cwd());
|
|
31
|
+
let logger;
|
|
15
32
|
let generation;
|
|
16
33
|
let dependencies = /* @__PURE__ */ new Set();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
let watchFiles = [];
|
|
35
|
+
async function resolveSelection() {
|
|
36
|
+
const manifestFile = node_path.resolve(root, options.manifest);
|
|
37
|
+
const manifest$1 = await manifest.readFontAwesomeManifest(manifestFile).catch(
|
|
38
|
+
(error) => {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Cannot read Font Awesome manifest ${node_path.relative(root, manifestFile) || manifestFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
return {
|
|
45
|
+
...manifest.selectFontAwesomeManifestKeys(manifest$1, root),
|
|
46
|
+
// Match the real paths that handleHotUpdate compares against.
|
|
47
|
+
manifestFile: await promises.realpath(manifestFile)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function regenerate(selection) {
|
|
51
|
+
generation = (async () => {
|
|
52
|
+
const selected = selection ?? await resolveSelection();
|
|
53
|
+
const result = await generate.generateFaIcons({
|
|
54
|
+
keys: selected.keys,
|
|
55
|
+
root,
|
|
56
|
+
sourceRoot: selected.sourceRoot,
|
|
57
|
+
allowPro: selected.allowPro,
|
|
58
|
+
virtualTypesFile: options.virtualTypesFile === false ? void 0 : options.virtualTypesFile ?? "src/featherk-fontawesome.d.ts"
|
|
59
|
+
});
|
|
60
|
+
watchFiles = [...result.dependencies, selected.manifestFile];
|
|
61
|
+
dependencies = new Set(watchFiles.map(dependencyKey));
|
|
26
62
|
return result;
|
|
27
|
-
});
|
|
63
|
+
})();
|
|
28
64
|
return generation;
|
|
29
65
|
}
|
|
30
66
|
return {
|
|
@@ -32,20 +68,12 @@ function featherkFontAwesome(options) {
|
|
|
32
68
|
enforce: "pre",
|
|
33
69
|
async configResolved(config) {
|
|
34
70
|
root = node_path.resolve(config.root, options.root ?? ".");
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
if (installCommand) {
|
|
39
|
-
console.info(
|
|
40
|
-
`[featherk-fontawesome] Install selected source packages with:
|
|
41
|
-
${installCommand}`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
await regenerate();
|
|
71
|
+
if (config.command === "build") logger = config.logger;
|
|
72
|
+
await regenerate(await resolveSelection());
|
|
45
73
|
},
|
|
46
74
|
async buildStart() {
|
|
47
|
-
|
|
48
|
-
for (const file of
|
|
75
|
+
await regenerate();
|
|
76
|
+
for (const file of watchFiles) this.addWatchFile(file);
|
|
49
77
|
},
|
|
50
78
|
resolveId(id) {
|
|
51
79
|
return id === virtualId ? resolvedId : void 0;
|
|
@@ -55,14 +83,14 @@ ${installCommand}`
|
|
|
55
83
|
return (await (generation ?? regenerate())).moduleCode;
|
|
56
84
|
},
|
|
57
85
|
async configureServer(server) {
|
|
58
|
-
|
|
59
|
-
server.watcher.add(
|
|
86
|
+
await (generation ?? regenerate());
|
|
87
|
+
server.watcher.add(watchFiles);
|
|
60
88
|
},
|
|
61
89
|
async handleHotUpdate(context) {
|
|
62
90
|
const file = await promises.realpath(context.file).catch(() => context.file);
|
|
63
91
|
if (!dependencies.has(dependencyKey(file))) return void 0;
|
|
64
|
-
|
|
65
|
-
context.server.watcher.add(
|
|
92
|
+
await regenerate();
|
|
93
|
+
context.server.watcher.add(watchFiles);
|
|
66
94
|
const module2 = context.server.moduleGraph.getModuleById(resolvedId);
|
|
67
95
|
if (module2) context.server.moduleGraph.invalidateModule(module2);
|
|
68
96
|
context.server.ws.send({ type: "full-reload" });
|
|
@@ -77,6 +105,14 @@ ${installCommand}`
|
|
|
77
105
|
source: result.notices
|
|
78
106
|
});
|
|
79
107
|
}
|
|
108
|
+
},
|
|
109
|
+
async closeBundle() {
|
|
110
|
+
const result = await generation?.catch(() => void 0);
|
|
111
|
+
if (logger && result) {
|
|
112
|
+
logger.info(
|
|
113
|
+
`[featherk-fontawesome] Generated ${generate.summarizeFaIcons(result.provenance)}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
80
116
|
}
|
|
81
117
|
};
|
|
82
118
|
}
|
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the Font Awesome virtual module plugin. Selections come
|
|
4
|
+
* from the same keys-only `{ free, pro }` manifest used by
|
|
5
|
+
* `featherk-fontawesome-setup`.
|
|
6
|
+
*
|
|
7
|
+
* The `free` keys come from the project's own installed packages. The `pro`
|
|
8
|
+
* keys are generated from the `fontawesome-pro-sources/` source project, only
|
|
9
|
+
* in builds where that project is installed.
|
|
10
|
+
*/
|
|
11
|
+
export interface FontAwesomeViteOptions {
|
|
12
|
+
/** Keys-only manifest path, relative to the project root. */
|
|
13
|
+
manifest: string;
|
|
14
|
+
/** Project root, relative to Vite's root. */
|
|
15
|
+
root?: string;
|
|
5
16
|
virtualTypesFile?: string | false;
|
|
17
|
+
/** Removed in 0.16.0; list keys in the manifest instead. */
|
|
18
|
+
keys?: never;
|
|
19
|
+
/** Removed in 0.16.0; Pro selection follows the manifest and layout. */
|
|
20
|
+
allowPro?: never;
|
|
21
|
+
/** Removed in 0.16.0; Pro sources always live in `fontawesome-pro-sources/`. */
|
|
22
|
+
sourceRoot?: never;
|
|
6
23
|
}
|
|
7
24
|
/**
|
|
8
25
|
* Creates the Vite plugin for `virtual:featherk/fontawesome`.
|
|
9
26
|
*
|
|
10
|
-
*
|
|
11
|
-
* notices are emitted into production builds.
|
|
27
|
+
* Keys are read from the manifest and resolved during Vite config setup, and
|
|
28
|
+
* their license notices are emitted into production builds. Mode gating
|
|
29
|
+
* selects which keys to generate; it is not license authorization.
|
|
30
|
+
*
|
|
31
|
+
* @throws If `manifest` is missing or a removed option is provided.
|
|
12
32
|
*/
|
|
13
33
|
export declare function featherkFontAwesome(options: FontAwesomeViteOptions): Plugin;
|