@featherk/icons 0.16.0 → 0.16.2
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 +10 -10
- package/dist/docs-manifest.js +6 -6
- package/dist/fontawesome/chunks/{manifest-CSRIDvaR.mjs → manifest-CF473fsM.mjs} +6 -1
- package/dist/fontawesome/chunks/{manifest-Yjw62jxG.cjs → manifest-DEhGKvmi.cjs} +6 -1
- package/dist/fontawesome/cli.cjs +4 -4
- package/dist/fontawesome/cli.mjs +4 -4
- package/dist/fontawesome/manifest.d.ts +5 -6
- package/dist/fontawesome/setup.cjs +19 -56
- package/dist/fontawesome/setup.mjs +20 -57
- package/dist/fontawesome/vite.cjs +1 -1
- package/dist/fontawesome/vite.d.ts +3 -4
- package/dist/fontawesome/vite.mjs +1 -1
- 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 +11 -11
- package/docs/fontawesome/FontAwesome.md +7 -12
- package/docs/fontawesome/FontAwesomeCLI.md +1 -1
- package/docs/fontawesome/FontAwesomeDeveloperSetup.md +1 -1
- package/docs/fontawesome/LICENSING.md +11 -73
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ const icon = getCustomIcon("search");
|
|
|
17
17
|
|
|
18
18
|
- `CustomIcon`: union of supported icon identifier strings (see `packages/icons/src/custom-icon.ts`).
|
|
19
19
|
- `GetCustomIconOptions`: `{ viewBox?: string; color?: string }` —
|
|
20
|
-
|
|
20
|
+
`viewBox` overrides the SVG viewBox; `color` replaces `currentColor` fills/strokes.
|
|
21
21
|
|
|
22
22
|
Example — type an icon name:
|
|
23
23
|
|
|
@@ -45,17 +45,17 @@ Example — change viewBox and color:
|
|
|
45
45
|
<SvgIcon :icon="successIcon" />
|
|
46
46
|
</template>
|
|
47
47
|
<script setup lang="ts">
|
|
48
|
-
import { SvgIcon } from "@progress/kendo-vue-common";
|
|
49
|
-
import { getCustomIcon } from "@featherk/icons";
|
|
48
|
+
import { SvgIcon } from "@progress/kendo-vue-common";
|
|
49
|
+
import { getCustomIcon } from "@featherk/icons";
|
|
50
50
|
|
|
51
|
-
const helpIcon = getCustomIcon("help", {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
51
|
+
const helpIcon = getCustomIcon("help", {
|
|
52
|
+
viewBox: "0 0 28 28",
|
|
53
|
+
color: "var(--kendo-color-primary)",
|
|
54
|
+
});
|
|
55
55
|
|
|
56
|
-
const successIcon = getCustomIcon("check", {
|
|
57
|
-
|
|
58
|
-
});
|
|
56
|
+
const successIcon = getCustomIcon("check", {
|
|
57
|
+
color: "var(--kendo-color-success)",
|
|
58
|
+
});
|
|
59
59
|
</script>
|
|
60
60
|
```
|
|
61
61
|
|
package/dist/docs-manifest.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generated by scripts/generate-docs-manifest.mjs. Do not edit.
|
|
2
2
|
export const packageName = "@featherk/icons";
|
|
3
3
|
|
|
4
|
-
export const version = "0.16.
|
|
4
|
+
export const version = "0.16.2";
|
|
5
5
|
|
|
6
6
|
export const paths = {
|
|
7
7
|
CreateFontAwesomeManifest: "fontawesome/CreateFontAwesomeManifest.md",
|
|
@@ -12,11 +12,11 @@ export const paths = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const docs = {
|
|
15
|
-
CreateFontAwesomeManifest: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.
|
|
16
|
-
FontAwesome: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.
|
|
17
|
-
FontAwesomeCLI: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.
|
|
18
|
-
FontAwesomeDeveloperSetup: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.
|
|
19
|
-
LICENSING: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.
|
|
15
|
+
CreateFontAwesomeManifest: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.2/docs/fontawesome/CreateFontAwesomeManifest.md",
|
|
16
|
+
FontAwesome: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.2/docs/fontawesome/FontAwesome.md",
|
|
17
|
+
FontAwesomeCLI: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.2/docs/fontawesome/FontAwesomeCLI.md",
|
|
18
|
+
FontAwesomeDeveloperSetup: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.2/docs/fontawesome/FontAwesomeDeveloperSetup.md",
|
|
19
|
+
LICENSING: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.2/docs/fontawesome/LICENSING.md",
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export const docUrl = (name, host = "https://cdn.jsdelivr.net/npm") =>
|
|
@@ -40,7 +40,12 @@ function fontAwesomeManifestKeys(manifest) {
|
|
|
40
40
|
function selectFontAwesomeManifestKeys(manifest, root) {
|
|
41
41
|
const keys = fontAwesomeManifestKeys(manifest);
|
|
42
42
|
if (!isFontAwesomeIsolated(root)) {
|
|
43
|
-
|
|
43
|
+
if (manifest.pro.length) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Font Awesome manifest has Pro keys, but ${fontAwesomeProSourcesDir}/ was not found. Run "featherk-fontawesome-setup --manifest <manifest>" to create it.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return { keys, allowPro: false };
|
|
44
49
|
}
|
|
45
50
|
if (!isFontAwesomeProInstalled(root)) {
|
|
46
51
|
return { keys: manifest.free, allowPro: false };
|
|
@@ -41,7 +41,12 @@ function fontAwesomeManifestKeys(manifest) {
|
|
|
41
41
|
function selectFontAwesomeManifestKeys(manifest, root) {
|
|
42
42
|
const keys = fontAwesomeManifestKeys(manifest);
|
|
43
43
|
if (!isFontAwesomeIsolated(root)) {
|
|
44
|
-
|
|
44
|
+
if (manifest.pro.length) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Font Awesome manifest has Pro keys, but ${fontAwesomeProSourcesDir}/ was not found. Run "featherk-fontawesome-setup --manifest <manifest>" to create it.`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return { keys, allowPro: false };
|
|
45
50
|
}
|
|
46
51
|
if (!isFontAwesomeProInstalled(root)) {
|
|
47
52
|
return { keys: manifest.free, allowPro: false };
|
package/dist/fontawesome/cli.cjs
CHANGED
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const node_path = require("node:path");
|
|
4
4
|
const node_util = require("node:util");
|
|
5
5
|
const generate = require("./chunks/generate-B_FxftR7.cjs");
|
|
6
|
-
const manifest = require("./chunks/manifest-
|
|
6
|
+
const manifest = require("./chunks/manifest-DEhGKvmi.cjs");
|
|
7
7
|
const usage = `Usage: featherk-fontawesome --manifest <icons.json> [--root <project>] [--out <icons.mjs>] [--virtual-types <types.d.ts>]
|
|
8
8
|
|
|
9
9
|
The JSON manifest contains { "free": [keys], "pro": [keys] }, the same file
|
|
10
10
|
used by featherk-fontawesome-setup and the Vite plugin.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
Free keys are generated from the project's own installed packages. Pro keys
|
|
12
|
+
are generated from the ${manifest.fontAwesomeProSourcesDir}/ source project, only when
|
|
13
|
+
it is installed.
|
|
14
14
|
Provide --out, --virtual-types, or both. Paths are relative to the project root.
|
|
15
15
|
This command does not download assets or authenticate; install licensed packages first.
|
|
16
16
|
Generated assets belong to the consuming project, never the @featherk/icons package.`;
|
package/dist/fontawesome/cli.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
3
|
import { g as generateFaIcons, s as summarizeFaIcons } from "./chunks/generate-DF9R65sV.mjs";
|
|
4
|
-
import { f as fontAwesomeProSourcesDir, r as readFontAwesomeManifest, s as selectFontAwesomeManifestKeys } from "./chunks/manifest-
|
|
4
|
+
import { f as fontAwesomeProSourcesDir, r as readFontAwesomeManifest, s as selectFontAwesomeManifestKeys } from "./chunks/manifest-CF473fsM.mjs";
|
|
5
5
|
const usage = `Usage: featherk-fontawesome --manifest <icons.json> [--root <project>] [--out <icons.mjs>] [--virtual-types <types.d.ts>]
|
|
6
6
|
|
|
7
7
|
The JSON manifest contains { "free": [keys], "pro": [keys] }, the same file
|
|
8
8
|
used by featherk-fontawesome-setup and the Vite plugin.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
Free keys are generated from the project's own installed packages. Pro keys
|
|
10
|
+
are generated from the ${fontAwesomeProSourcesDir}/ source project, only when
|
|
11
|
+
it is installed.
|
|
12
12
|
Provide --out, --virtual-types, or both. Paths are relative to the project root.
|
|
13
13
|
This command does not download assets or authenticate; install licensed packages first.
|
|
14
14
|
Generated assets belong to the consuming project, never the @featherk/icons package.`;
|
|
@@ -39,12 +39,11 @@ export declare function fontAwesomeManifestKeys(manifest: FontAwesomeKeysManifes
|
|
|
39
39
|
/**
|
|
40
40
|
* Selects the manifest keys for one build of the application at `root`.
|
|
41
41
|
*
|
|
42
|
-
*
|
|
43
|
-
* `fontawesome-pro-sources`, only when that project is
|
|
44
|
-
* the build is Free-only and never reads it.
|
|
45
|
-
* the application installed its own sources, so every key is selected; a
|
|
46
|
-
* Free-only manifest has no `pro` keys.
|
|
42
|
+
* The `free` keys are always selected. The `pro` keys are selected, and
|
|
43
|
+
* resolved from `fontawesome-pro-sources`, only when that project is
|
|
44
|
+
* installed; otherwise the build is Free-only and never reads it.
|
|
47
45
|
*
|
|
48
|
-
* @throws If a Pro-tier key is listed under `free
|
|
46
|
+
* @throws If a Pro-tier key is listed under `free`, or the manifest has `pro`
|
|
47
|
+
* keys but the application has no `fontawesome-pro-sources` project.
|
|
49
48
|
*/
|
|
50
49
|
export declare function selectFontAwesomeManifestKeys(manifest: FontAwesomeKeysManifest, root: string): FontAwesomeManifestSelection;
|
|
@@ -6,7 +6,7 @@ const node_path = require("node:path");
|
|
|
6
6
|
const node_readline = require("node:readline");
|
|
7
7
|
const node_util = require("node:util");
|
|
8
8
|
const fontawesome_catalog = require("./catalog.cjs");
|
|
9
|
-
const manifest = require("./chunks/manifest-
|
|
9
|
+
const manifest = require("./chunks/manifest-DEhGKvmi.cjs");
|
|
10
10
|
const tokenVariable = "FONTAWESOME_PACKAGE_TOKEN";
|
|
11
11
|
const tokenPlaceholder = `\${${tokenVariable}}`;
|
|
12
12
|
const registry = "https://npm.fontawesome.com/";
|
|
@@ -25,7 +25,7 @@ const workspaceVariables = [
|
|
|
25
25
|
"NPM_CONFIG_WORKSPACES"
|
|
26
26
|
];
|
|
27
27
|
const usage = `Usage:
|
|
28
|
-
featherk-fontawesome-setup --manifest <icons.json> [--free-only
|
|
28
|
+
featherk-fontawesome-setup --manifest <icons.json> [--free-only]
|
|
29
29
|
featherk-fontawesome-setup
|
|
30
30
|
|
|
31
31
|
Run from the application root. The manifest contains
|
|
@@ -44,12 +44,6 @@ lockfile with the token, for CI and fresh clones. Run it after the app's own
|
|
|
44
44
|
|
|
45
45
|
--free-only: Free keys only from public npm. No token, no source project.
|
|
46
46
|
|
|
47
|
-
--pro-in-app: installs Free and Pro pins into the app's own devDependencies
|
|
48
|
-
and routes @fortawesome to the Pro registry in the app's .npmrc (token
|
|
49
|
-
placeholder only). Every install of the app, including CI, then needs the
|
|
50
|
-
token for "npm ci --ignore-scripts". Use only when the isolated project is not
|
|
51
|
-
an option.
|
|
52
|
-
|
|
53
47
|
The token comes from ${tokenVariable} or a hidden prompt in an interactive
|
|
54
48
|
terminal. --manifest setup changes package.json and is refused in CI
|
|
55
49
|
(CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set). Do not export the token
|
|
@@ -193,11 +187,10 @@ function checkNpmrc(config, file) {
|
|
|
193
187
|
}
|
|
194
188
|
return { fontAwesomeRegistry, hasAuth };
|
|
195
189
|
}
|
|
196
|
-
function
|
|
190
|
+
function installFreeIntoApp(pins, context) {
|
|
197
191
|
const npmCli = requireNpm(context);
|
|
198
192
|
const environment = { ...context.env };
|
|
199
193
|
delete environment[tokenVariable];
|
|
200
|
-
if (pro && token) environment[tokenVariable] = token;
|
|
201
194
|
const specs = [...pins].map(([name, pin]) => `${name}@${pin.spec}`);
|
|
202
195
|
const status = context.runNpm({
|
|
203
196
|
npmCli,
|
|
@@ -208,7 +201,6 @@ function installIntoApp(pins, pro, token, context) {
|
|
|
208
201
|
"--ignore-scripts",
|
|
209
202
|
"--no-audit",
|
|
210
203
|
"--no-fund",
|
|
211
|
-
...pro ? [pinRegistry] : [],
|
|
212
204
|
...specs
|
|
213
205
|
],
|
|
214
206
|
cwd: context.cwd,
|
|
@@ -311,15 +303,14 @@ async function installSourceProject(sourceRoot, token, context) {
|
|
|
311
303
|
context.log(
|
|
312
304
|
locked ? `Pro sources installed from ${lockfile}.` : `Pro sources installed. Review and commit ${lockfile}.`
|
|
313
305
|
);
|
|
306
|
+
context.log(
|
|
307
|
+
"Restart any running Vite dev server so it includes the installed Pro icons."
|
|
308
|
+
);
|
|
314
309
|
return 0;
|
|
315
310
|
}
|
|
316
311
|
async function setupFromManifest(values, context) {
|
|
317
312
|
const { log } = context;
|
|
318
313
|
const freeOnly = Boolean(values["free-only"]);
|
|
319
|
-
const proInApp = Boolean(values["pro-in-app"]);
|
|
320
|
-
if (freeOnly && proInApp) {
|
|
321
|
-
throw new Error("Use either --free-only or --pro-in-app, not both.");
|
|
322
|
-
}
|
|
323
314
|
if (context.isCi) {
|
|
324
315
|
throw new Error(
|
|
325
316
|
`--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 ${manifest.fontAwesomeProSourcesDir}/.`
|
|
@@ -344,17 +335,12 @@ async function setupFromManifest(values, context) {
|
|
|
344
335
|
}
|
|
345
336
|
const npmrcPath = node_path.resolve(appRoot, ".npmrc");
|
|
346
337
|
const config = node_fs.existsSync(npmrcPath) ? node_fs.readFileSync(npmrcPath, "utf8") : "";
|
|
347
|
-
const { fontAwesomeRegistry
|
|
338
|
+
const { fontAwesomeRegistry } = checkNpmrc(config, ".npmrc");
|
|
348
339
|
const sourceRoot = node_path.resolve(appRoot, manifest.fontAwesomeProSourcesDir);
|
|
349
340
|
const isolated = manifest.isFontAwesomeIsolated(appRoot);
|
|
350
|
-
if (
|
|
351
|
-
throw new Error(
|
|
352
|
-
`${manifest.fontAwesomeProSourcesDir}/ exists, so this app keeps Pro in the isolated source project. Run without --pro-in-app, or remove ${manifest.fontAwesomeProSourcesDir}/ first.`
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
if (!proInApp && fontAwesomeRegistry) {
|
|
341
|
+
if (fontAwesomeRegistry) {
|
|
356
342
|
throw new Error(
|
|
357
|
-
`.npmrc routes @fortawesome to ${fontAwesomeRegistry},
|
|
343
|
+
`.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.`
|
|
358
344
|
);
|
|
359
345
|
}
|
|
360
346
|
if (freeOnly && isolated) {
|
|
@@ -362,34 +348,8 @@ async function setupFromManifest(values, context) {
|
|
|
362
348
|
`${manifest.fontAwesomeProSourcesDir}/ exists, so this app uses Pro. Run without --free-only, or remove ${manifest.fontAwesomeProSourcesDir}/ first.`
|
|
363
349
|
);
|
|
364
350
|
}
|
|
365
|
-
if (proInApp) {
|
|
366
|
-
const token = proPins.size ? await readToken(context) : void 0;
|
|
367
|
-
if (proPins.size) {
|
|
368
|
-
const missing = [];
|
|
369
|
-
if (!fontAwesomeRegistry) missing.push(npmrcLines[0], npmrcLines[1]);
|
|
370
|
-
if (!hasAuth) missing.push(npmrcLines[2], npmrcLines[3]);
|
|
371
|
-
if (missing.length) {
|
|
372
|
-
const separator = config && !config.endsWith("\n") ? "\n" : "";
|
|
373
|
-
node_fs.writeFileSync(
|
|
374
|
-
npmrcPath,
|
|
375
|
-
`${config}${separator}${missing.join("\n")}
|
|
376
|
-
`
|
|
377
|
-
);
|
|
378
|
-
log(
|
|
379
|
-
`${config ? "Updated" : "Created"} .npmrc with the Font Awesome registry and token placeholder.`
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
const status2 = installIntoApp(pins, proPins.size > 0, token, context);
|
|
384
|
-
if (status2 !== 0) return status2;
|
|
385
|
-
log(lifecycleNote);
|
|
386
|
-
log(
|
|
387
|
-
`Next: commit .npmrc, package.json, and package-lock.json. Configure the Vite plugin with { manifest }. Every later install, including CI, gives ${tokenVariable} only to "npm ci --ignore-scripts"; run needed install scripts and builds without it.`
|
|
388
|
-
);
|
|
389
|
-
return 0;
|
|
390
|
-
}
|
|
391
351
|
if (freePins.size) {
|
|
392
|
-
const status2 =
|
|
352
|
+
const status2 = installFreeIntoApp(freePins, context);
|
|
393
353
|
if (status2 !== 0) return status2;
|
|
394
354
|
log(lifecycleNote);
|
|
395
355
|
}
|
|
@@ -433,20 +393,23 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
433
393
|
promptForToken: io.promptForToken ?? promptForTerminalToken,
|
|
434
394
|
runNpm: io.runNpm ?? spawnNpm
|
|
435
395
|
};
|
|
396
|
+
const hasFlag = (flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
436
397
|
try {
|
|
437
|
-
const removed = removedFlags.find(
|
|
438
|
-
(flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`))
|
|
439
|
-
);
|
|
398
|
+
const removed = removedFlags.find(hasFlag);
|
|
440
399
|
if (removed) {
|
|
441
400
|
throw new Error(
|
|
442
401
|
`${removed} was removed in 0.16.0. Run setup with --manifest; Pro sources always live in ${manifest.fontAwesomeProSourcesDir}/, and rerunning with --manifest updates them. Use --help for usage.`
|
|
443
402
|
);
|
|
444
403
|
}
|
|
404
|
+
if (hasFlag("--pro-in-app")) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
`--pro-in-app was removed. Pro packages always install into ${manifest.fontAwesomeProSourcesDir}/, so the app's own install never needs the token. Run setup with --manifest.`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
445
409
|
const { values } = node_util.parseArgs({
|
|
446
410
|
args: [...args],
|
|
447
411
|
options: {
|
|
448
412
|
"free-only": { type: "boolean" },
|
|
449
|
-
"pro-in-app": { type: "boolean" },
|
|
450
413
|
manifest: { type: "string" },
|
|
451
414
|
help: { type: "boolean", short: "h" }
|
|
452
415
|
},
|
|
@@ -460,8 +423,8 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
460
423
|
if (values.manifest !== void 0) {
|
|
461
424
|
return await setupFromManifest(values, context);
|
|
462
425
|
}
|
|
463
|
-
if (values["free-only"]
|
|
464
|
-
throw new Error("--free-only
|
|
426
|
+
if (values["free-only"]) {
|
|
427
|
+
throw new Error("--free-only requires --manifest.");
|
|
465
428
|
}
|
|
466
429
|
if (!manifest.isFontAwesomeIsolated(cwd)) {
|
|
467
430
|
throw new Error(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readFileSync,
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
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 { f as fontAwesomeProSourcesDir, i as isFontAwesomeIsolated, r as readFontAwesomeManifest, a as fontAwesomeManifestKeys } 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,7 +23,7 @@ const workspaceVariables = [
|
|
|
23
23
|
"NPM_CONFIG_WORKSPACES"
|
|
24
24
|
];
|
|
25
25
|
const usage = `Usage:
|
|
26
|
-
featherk-fontawesome-setup --manifest <icons.json> [--free-only
|
|
26
|
+
featherk-fontawesome-setup --manifest <icons.json> [--free-only]
|
|
27
27
|
featherk-fontawesome-setup
|
|
28
28
|
|
|
29
29
|
Run from the application root. The manifest contains
|
|
@@ -42,12 +42,6 @@ lockfile with the token, for CI and fresh clones. Run it after the app's own
|
|
|
42
42
|
|
|
43
43
|
--free-only: Free keys only from public npm. No token, no source project.
|
|
44
44
|
|
|
45
|
-
--pro-in-app: installs Free and Pro pins into the app's own devDependencies
|
|
46
|
-
and routes @fortawesome to the Pro registry in the app's .npmrc (token
|
|
47
|
-
placeholder only). Every install of the app, including CI, then needs the
|
|
48
|
-
token for "npm ci --ignore-scripts". Use only when the isolated project is not
|
|
49
|
-
an option.
|
|
50
|
-
|
|
51
45
|
The token comes from ${tokenVariable} or a hidden prompt in an interactive
|
|
52
46
|
terminal. --manifest setup changes package.json and is refused in CI
|
|
53
47
|
(CI, TEAMCITY_VERSION, or GITHUB_ACTIONS is set). Do not export the token
|
|
@@ -191,11 +185,10 @@ function checkNpmrc(config, file) {
|
|
|
191
185
|
}
|
|
192
186
|
return { fontAwesomeRegistry, hasAuth };
|
|
193
187
|
}
|
|
194
|
-
function
|
|
188
|
+
function installFreeIntoApp(pins, context) {
|
|
195
189
|
const npmCli = requireNpm(context);
|
|
196
190
|
const environment = { ...context.env };
|
|
197
191
|
delete environment[tokenVariable];
|
|
198
|
-
if (pro && token) environment[tokenVariable] = token;
|
|
199
192
|
const specs = [...pins].map(([name, pin]) => `${name}@${pin.spec}`);
|
|
200
193
|
const status = context.runNpm({
|
|
201
194
|
npmCli,
|
|
@@ -206,7 +199,6 @@ function installIntoApp(pins, pro, token, context) {
|
|
|
206
199
|
"--ignore-scripts",
|
|
207
200
|
"--no-audit",
|
|
208
201
|
"--no-fund",
|
|
209
|
-
...pro ? [pinRegistry] : [],
|
|
210
202
|
...specs
|
|
211
203
|
],
|
|
212
204
|
cwd: context.cwd,
|
|
@@ -309,15 +301,14 @@ async function installSourceProject(sourceRoot, token, context) {
|
|
|
309
301
|
context.log(
|
|
310
302
|
locked ? `Pro sources installed from ${lockfile}.` : `Pro sources installed. Review and commit ${lockfile}.`
|
|
311
303
|
);
|
|
304
|
+
context.log(
|
|
305
|
+
"Restart any running Vite dev server so it includes the installed Pro icons."
|
|
306
|
+
);
|
|
312
307
|
return 0;
|
|
313
308
|
}
|
|
314
309
|
async function setupFromManifest(values, context) {
|
|
315
310
|
const { log } = context;
|
|
316
311
|
const freeOnly = Boolean(values["free-only"]);
|
|
317
|
-
const proInApp = Boolean(values["pro-in-app"]);
|
|
318
|
-
if (freeOnly && proInApp) {
|
|
319
|
-
throw new Error("Use either --free-only or --pro-in-app, not both.");
|
|
320
|
-
}
|
|
321
312
|
if (context.isCi) {
|
|
322
313
|
throw new Error(
|
|
323
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}/.`
|
|
@@ -342,17 +333,12 @@ async function setupFromManifest(values, context) {
|
|
|
342
333
|
}
|
|
343
334
|
const npmrcPath = resolve(appRoot, ".npmrc");
|
|
344
335
|
const config = existsSync(npmrcPath) ? readFileSync(npmrcPath, "utf8") : "";
|
|
345
|
-
const { fontAwesomeRegistry
|
|
336
|
+
const { fontAwesomeRegistry } = checkNpmrc(config, ".npmrc");
|
|
346
337
|
const sourceRoot = resolve(appRoot, fontAwesomeProSourcesDir);
|
|
347
338
|
const isolated = isFontAwesomeIsolated(appRoot);
|
|
348
|
-
if (
|
|
349
|
-
throw new Error(
|
|
350
|
-
`${fontAwesomeProSourcesDir}/ exists, so this app keeps Pro in the isolated source project. Run without --pro-in-app, or remove ${fontAwesomeProSourcesDir}/ first.`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
if (!proInApp && fontAwesomeRegistry) {
|
|
339
|
+
if (fontAwesomeRegistry) {
|
|
354
340
|
throw new Error(
|
|
355
|
-
`.npmrc routes @fortawesome to ${fontAwesomeRegistry},
|
|
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.`
|
|
356
342
|
);
|
|
357
343
|
}
|
|
358
344
|
if (freeOnly && isolated) {
|
|
@@ -360,34 +346,8 @@ async function setupFromManifest(values, context) {
|
|
|
360
346
|
`${fontAwesomeProSourcesDir}/ exists, so this app uses Pro. Run without --free-only, or remove ${fontAwesomeProSourcesDir}/ first.`
|
|
361
347
|
);
|
|
362
348
|
}
|
|
363
|
-
if (proInApp) {
|
|
364
|
-
const token = proPins.size ? await readToken(context) : void 0;
|
|
365
|
-
if (proPins.size) {
|
|
366
|
-
const missing = [];
|
|
367
|
-
if (!fontAwesomeRegistry) missing.push(npmrcLines[0], npmrcLines[1]);
|
|
368
|
-
if (!hasAuth) missing.push(npmrcLines[2], npmrcLines[3]);
|
|
369
|
-
if (missing.length) {
|
|
370
|
-
const separator = config && !config.endsWith("\n") ? "\n" : "";
|
|
371
|
-
writeFileSync(
|
|
372
|
-
npmrcPath,
|
|
373
|
-
`${config}${separator}${missing.join("\n")}
|
|
374
|
-
`
|
|
375
|
-
);
|
|
376
|
-
log(
|
|
377
|
-
`${config ? "Updated" : "Created"} .npmrc with the Font Awesome registry and token placeholder.`
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
const status2 = installIntoApp(pins, proPins.size > 0, token, context);
|
|
382
|
-
if (status2 !== 0) return status2;
|
|
383
|
-
log(lifecycleNote);
|
|
384
|
-
log(
|
|
385
|
-
`Next: commit .npmrc, package.json, and package-lock.json. Configure the Vite plugin with { manifest }. Every later install, including CI, gives ${tokenVariable} only to "npm ci --ignore-scripts"; run needed install scripts and builds without it.`
|
|
386
|
-
);
|
|
387
|
-
return 0;
|
|
388
|
-
}
|
|
389
349
|
if (freePins.size) {
|
|
390
|
-
const status2 =
|
|
350
|
+
const status2 = installFreeIntoApp(freePins, context);
|
|
391
351
|
if (status2 !== 0) return status2;
|
|
392
352
|
log(lifecycleNote);
|
|
393
353
|
}
|
|
@@ -431,20 +391,23 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
431
391
|
promptForToken: io.promptForToken ?? promptForTerminalToken,
|
|
432
392
|
runNpm: io.runNpm ?? spawnNpm
|
|
433
393
|
};
|
|
394
|
+
const hasFlag = (flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
434
395
|
try {
|
|
435
|
-
const removed = removedFlags.find(
|
|
436
|
-
(flag) => args.some((arg) => arg === flag || arg.startsWith(`${flag}=`))
|
|
437
|
-
);
|
|
396
|
+
const removed = removedFlags.find(hasFlag);
|
|
438
397
|
if (removed) {
|
|
439
398
|
throw new Error(
|
|
440
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.`
|
|
441
400
|
);
|
|
442
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
|
+
}
|
|
443
407
|
const { values } = parseArgs({
|
|
444
408
|
args: [...args],
|
|
445
409
|
options: {
|
|
446
410
|
"free-only": { type: "boolean" },
|
|
447
|
-
"pro-in-app": { type: "boolean" },
|
|
448
411
|
manifest: { type: "string" },
|
|
449
412
|
help: { type: "boolean", short: "h" }
|
|
450
413
|
},
|
|
@@ -458,8 +421,8 @@ async function runFontAwesomeSetup(args, io = {}) {
|
|
|
458
421
|
if (values.manifest !== void 0) {
|
|
459
422
|
return await setupFromManifest(values, context);
|
|
460
423
|
}
|
|
461
|
-
if (values["free-only"]
|
|
462
|
-
throw new Error("--free-only
|
|
424
|
+
if (values["free-only"]) {
|
|
425
|
+
throw new Error("--free-only requires --manifest.");
|
|
463
426
|
}
|
|
464
427
|
if (!isFontAwesomeIsolated(cwd)) {
|
|
465
428
|
throw new Error(
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const node_path = require("node:path");
|
|
4
4
|
const promises = require("node:fs/promises");
|
|
5
5
|
const generate = require("./chunks/generate-B_FxftR7.cjs");
|
|
6
|
-
const manifest = require("./chunks/manifest-
|
|
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) {
|
|
@@ -4,10 +4,9 @@ import type { Plugin } from "vite";
|
|
|
4
4
|
* from the same keys-only `{ free, pro }` manifest used by
|
|
5
5
|
* `featherk-fontawesome-setup`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* builds where that project is installed.
|
|
10
|
-
* project's own installed packages.
|
|
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.
|
|
11
10
|
*/
|
|
12
11
|
export interface FontAwesomeViteOptions {
|
|
13
12
|
/** Keys-only manifest path, relative to the project root. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve, relative } from "node:path";
|
|
2
2
|
import { realpath } from "node:fs/promises";
|
|
3
3
|
import { g as generateFaIcons, s as summarizeFaIcons } from "./chunks/generate-DF9R65sV.mjs";
|
|
4
|
-
import { f as fontAwesomeProSourcesDir, r as readFontAwesomeManifest, s as selectFontAwesomeManifestKeys } from "./chunks/manifest-
|
|
4
|
+
import { f as fontAwesomeProSourcesDir, r as readFontAwesomeManifest, s as selectFontAwesomeManifestKeys } from "./chunks/manifest-CF473fsM.mjs";
|
|
5
5
|
const virtualId = "virtual:featherk/fontawesome";
|
|
6
6
|
const resolvedId = `\0${virtualId}`;
|
|
7
7
|
function dependencyKey(file) {
|
package/docs/ADDING-ICONS.md
CHANGED
|
@@ -10,8 +10,8 @@ iconography repository provides validation tools for its source assets.
|
|
|
10
10
|
|
|
11
11
|
Keep the category directory and filename when copying an icon:
|
|
12
12
|
|
|
13
|
-
| Source in `iconography`
|
|
14
|
-
|
|
|
13
|
+
| Source in `iconography` | Destination in this repository |
|
|
14
|
+
| ---------------------------------- | -------------------------------------------- |
|
|
15
15
|
| `src/icons/<category>/ic_Name.svg` | `packages/icons/icon/<category>/ic_Name.svg` |
|
|
16
16
|
|
|
17
17
|
For example, copy `src/icons/action/ic_Edit.svg` to
|
|
@@ -35,6 +35,7 @@ entire iconography repository.
|
|
|
35
35
|
missing IDs, and duplicate filenames. The full check also enforces the 5 KB
|
|
36
36
|
file-size limit. After changing the source inventory, refresh it with
|
|
37
37
|
`npm run document:icons`.
|
|
38
|
+
|
|
38
39
|
3. Copy the selected SVG files unchanged into the matching category directories
|
|
39
40
|
under `packages/icons/icon/`. Create the destination category directory if
|
|
40
41
|
needed. Do not copy generated package output in place of the SVG source
|
|
@@ -55,4 +56,4 @@ entire iconography repository.
|
|
|
55
56
|
The package generator derives each public icon name from its filename by
|
|
56
57
|
removing the `ic_` prefix and `.svg` extension, then lowercasing the remainder.
|
|
57
58
|
For example, `ic_User_Profile.svg` becomes `user_profile`. Keep filenames
|
|
58
|
-
unique across categories; the iconography validator checks this requirement.
|
|
59
|
+
unique across categories; the iconography validator checks this requirement.
|
package/docs/COMING-SOON.md
CHANGED
|
@@ -6,12 +6,13 @@ notice. They were moved out of the main README to keep the public surface area
|
|
|
6
6
|
stable while we iterate on behaviour and naming.
|
|
7
7
|
|
|
8
8
|
Quick summary:
|
|
9
|
+
|
|
9
10
|
- `getIconCssUrl` / `getIconCssUrlBase64` — convenience helpers that return a
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
wrapped `url("...")` string suitable for assigning directly to CSS
|
|
12
|
+
`background-image` (UTF‑8 and base64 variants respectively).
|
|
12
13
|
- `getIconDataUrlBase64` — base64-encoded data URL variant of `getIconDataUrl`.
|
|
13
14
|
- Usage examples and small CSS snippets that simplify embedding icons as
|
|
14
|
-
|
|
15
|
+
backgrounds or masks in styles.
|
|
15
16
|
|
|
16
17
|
Please treat these helpers as unstable. If you rely on them, expect possible
|
|
17
18
|
breaking changes in future releases and prefer the lower-level `getIconDataUrl`
|
|
@@ -30,20 +31,23 @@ import { getCustomIcon, getIconDataUrl } from "@featherk/icons";
|
|
|
30
31
|
const search = getCustomIcon("search");
|
|
31
32
|
const searchIconUrl = getIconDataUrl(search);
|
|
32
33
|
// Provide it to CSS via a custom property (example only)
|
|
33
|
-
document.documentElement.style.setProperty(
|
|
34
|
+
document.documentElement.style.setProperty(
|
|
35
|
+
"--search-icon",
|
|
36
|
+
`url("${searchIconUrl}")`,
|
|
37
|
+
);
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
```css
|
|
37
41
|
.button::after {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
content: "";
|
|
43
|
+
display: inline-block;
|
|
44
|
+
width: 1em;
|
|
45
|
+
height: 1em;
|
|
46
|
+
background: no-repeat center/contain var(--search-icon);
|
|
47
|
+
/* Alternatively, to tint using current text color:
|
|
44
48
|
mask: var(--search-icon) no-repeat center / contain;
|
|
45
49
|
background-color: currentColor; */
|
|
46
|
-
|
|
50
|
+
margin-left: 0.25rem;
|
|
47
51
|
}
|
|
48
52
|
```
|
|
49
53
|
|
|
@@ -53,7 +57,11 @@ If you prefer a ready-to-use CSS value, use `getIconCssUrl` (UTF‑8) or
|
|
|
53
57
|
`getIconCssUrlBase64` (base64). Both return a wrapped `url("...")` string.
|
|
54
58
|
|
|
55
59
|
```ts
|
|
56
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
getCustomIcon,
|
|
62
|
+
getIconCssUrl,
|
|
63
|
+
getIconCssUrlBase64,
|
|
64
|
+
} from "@featherk/icons";
|
|
57
65
|
|
|
58
66
|
const arrowLeft = getCustomIcon("arrow_left");
|
|
59
67
|
const arrowLeftBg = getIconCssUrl(arrowLeft);
|
|
@@ -74,6 +82,8 @@ import { getCustomIcon, getIconDataUrlBase64 } from "@featherk/icons";
|
|
|
74
82
|
const search = getCustomIcon("search");
|
|
75
83
|
const searchIconUrlBase64 = getIconDataUrlBase64(search);
|
|
76
84
|
// Example: set as CSS background
|
|
77
|
-
document.documentElement.style.setProperty(
|
|
85
|
+
document.documentElement.style.setProperty(
|
|
86
|
+
"--search-icon",
|
|
87
|
+
`url("${searchIconUrlBase64}")`,
|
|
88
|
+
);
|
|
78
89
|
```
|
|
79
|
-
|
package/docs/ICONS.md
CHANGED
|
@@ -13,17 +13,17 @@ The steps below help UX/Design create a precise handoff. Do not assume every ico
|
|
|
13
13
|
|
|
14
14
|
## Where Each Field Comes From
|
|
15
15
|
|
|
16
|
-
| Catalog field
|
|
17
|
-
|
|
|
18
|
-
| `key`
|
|
19
|
-
| `name`
|
|
20
|
-
| `version`
|
|
21
|
-
| `family`
|
|
22
|
-
| `style`
|
|
23
|
-
| `package`
|
|
24
|
-
| `registryPackage` | UX/Design Engineer
|
|
25
|
-
| `exportName`
|
|
26
|
-
| `tier`
|
|
16
|
+
| Catalog field | Who supplies it | Meaning |
|
|
17
|
+
| ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
18
|
+
| `key` | UX/Design Engineer | Stable, globally unique lookup key for exactly one catalog variant; supplied to Vite/CLI by the consumer |
|
|
19
|
+
| `name` | Font Awesome catalog | Canonical icon name, such as `house`, without the `fa-` CSS prefix |
|
|
20
|
+
| `version` | UX and release approval | Exact source-package release, such as `7.0.0`, not `latest`, a range, or the first version that introduced the icon |
|
|
21
|
+
| `family` | UX/design selection | Supported family identifier, such as `classic` or `sharp` |
|
|
22
|
+
| `style` | UX/design selection | Supported style identifier, such as `solid`, `regular`, or `light` |
|
|
23
|
+
| `package` | UX/Design Engineer | Exact installed dependency name; may be an npm alias such as `fa-solid-v5` |
|
|
24
|
+
| `registryPackage` | UX/Design Engineer | Canonical npm package name targeted by `package` and checked against installed package metadata |
|
|
25
|
+
| `exportName` | UX/Design Engineer | Exact individual icon export in the source package |
|
|
26
|
+
| `tier` | UX/Design Engineer | `free` or `pro` classification for the exact variant; descriptive only, not proof of entitlement |
|
|
27
27
|
|
|
28
28
|
Each catalog key identifies one exact name/version/family/style/package/export variant. Different styles or releases require different keys. Catalog records are maintained and published by FeatherK; consuming applications do not copy these fields into their selection manifest. `tier` describes the Font Awesome product tier only; it does not grant access or establish license coverage. Package availability and Pro entitlement must still be confirmed independently.
|
|
29
29
|
|
|
@@ -30,7 +30,7 @@ One keys-only manifest drives everything: the setup command installs exactly wha
|
|
|
30
30
|
featherkFontAwesome({ manifest: "fontawesome.keys.json" });
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
4. **Build** with the application's normal `dev` and `build` scripts. Wherever `fontawesome-pro-sources/` is installed (step 2 locally, or the
|
|
33
|
+
4. **Build** with the application's normal `dev` and `build` scripts. Wherever `fontawesome-pro-sources/` is installed (step 2 locally, or the `npx featherk-fontawesome-setup` step in CI), builds include the Pro icons. Where it isn't installed, builds include only the Free icons.
|
|
34
34
|
5. **Render icons** from the virtual module; see the [rendering example](#render-the-selected-key).
|
|
35
35
|
6. **Preserve license notices** in application distribution; see [Preserve license notices](#preserve-license-notices).
|
|
36
36
|
|
|
@@ -49,7 +49,7 @@ The repository's Pro demo selects Classic Light `house` from Font Awesome Pro 7
|
|
|
49
49
|
|
|
50
50
|
This follows the demo's Vite virtual-module flow. The Pro page filters generated provenance for `pro-` keys and passes the choices to its shared renderer; an application can also render this selected icon directly:
|
|
51
51
|
|
|
52
|
-
```
|
|
52
|
+
```html
|
|
53
53
|
<template>
|
|
54
54
|
<SvgIcon :icon="houseIcon" />
|
|
55
55
|
</template>
|
|
@@ -94,7 +94,7 @@ npm install --save-dev @featherk/icons vite@^7.0.0
|
|
|
94
94
|
|
|
95
95
|
## Install Source Packages
|
|
96
96
|
|
|
97
|
-
Run `featherk-fontawesome-setup --manifest fontawesome.keys.json` from the application root (Quick Start step 2). The catalog maps each key to its local dependency name, canonical registry package, export, and exact version, and the command installs only the packages the manifest needs, pinned to those versions, including npm aliases where one release must sit beside another (see [alias details](#about-aliases-and-why-use-them)). Free packages go into the application's `devDependencies`. Pro packages go into `fontawesome-pro-sources/`, whose `.npmrc` holds only a token placeholder, and the token is passed only to npm. On a fresh clone or in CI, run `npx featherk-fontawesome-setup` without arguments after the application's `npm ci` to install that project from its lockfile. See [Pro licensing and setup](LICENSING.md#consuming-applications) for the token, CI, TeamCity, and the `--
|
|
97
|
+
Run `featherk-fontawesome-setup --manifest fontawesome.keys.json` from the application root (Quick Start step 2). The catalog maps each key to its local dependency name, canonical registry package, export, and exact version, and the command installs only the packages the manifest needs, pinned to those versions, including npm aliases where one release must sit beside another (see [alias details](#about-aliases-and-why-use-them)). Free packages go into the application's `devDependencies`. Pro packages go into `fontawesome-pro-sources/`, whose `.npmrc` holds only a token placeholder, and the token is passed only to npm. On a fresh clone or in CI, run `npx featherk-fontawesome-setup` without arguments after the application's `npm ci` to install that project from its lockfile. See [Pro licensing and setup](LICENSING.md#consuming-applications) for the token, CI, TeamCity, and the `--free-only` exception. Never put a Pro token in a command or commit it.
|
|
98
98
|
|
|
99
99
|
During generation, the installed package's declared name is checked against `registryPackage` and its version against the catalog before the icon module is loaded. When a package is missing, generation fails with a message that points to the setup command; nobody installs Font Awesome packages by hand. At the end of each build, Vite logs the source packages the icons came from, for information only. The setup command is not a license or access check.
|
|
100
100
|
|
|
@@ -112,15 +112,15 @@ export default defineConfig({
|
|
|
112
112
|
});
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
The plugin reads the manifest relative to the Vite project root and validates every key through the catalog. It always generates the `free` keys. When the project has `fontawesome-pro-sources/`, it adds the `pro` keys, resolved from that project, only when that project is installed (its `node_modules` exists); otherwise it never reads it. A build where the install was skipped is Free-only, and code that uses a Pro key then fails type checking, because the generated key union contains only Free keys.
|
|
115
|
+
The plugin reads the manifest relative to the Vite project root and validates every key through the catalog. It always generates the `free` keys. When the project has `fontawesome-pro-sources/`, it adds the `pro` keys, resolved from that project, only when that project is installed (its `node_modules` exists); otherwise it never reads it. A build where the install was skipped is Free-only, and code that uses a Pro key then fails type checking, because the generated key union contains only Free keys. A manifest with `pro` keys in a project without `fontawesome-pro-sources/` fails with a message to run the setup command. A Pro-tier key listed under `free` is rejected with a message to move it to `pro`. Selecting keys this way is not license authorization. The plugin watches the manifest and reloads the dev server when it changes. The catalog supplies exact metadata, and the generator validates installed source versions and identities at runtime.
|
|
116
116
|
|
|
117
117
|
### Upgrading from 0.15
|
|
118
118
|
|
|
119
|
-
0.16.0 removed the plugin's `keys`, `allowPro`, and `sourceRoot` options; the setup command's `--keys`, `--source-root`, `--init`, `--force`, and `--refresh-lock`; and the CLI's `--allow-pro` and `--source-root`. Passing them fails with a message that explains the replacement. Move the keys into the manifest, pass `{ manifest }`, and rerun `featherk-fontawesome-setup --manifest fontawesome.keys.json`, which moves Pro packages into `fontawesome-pro-sources/`.
|
|
119
|
+
0.16.0 removed the plugin's `keys`, `allowPro`, and `sourceRoot` options; the setup command's `--keys`, `--source-root`, `--init`, `--force`, and `--refresh-lock`; and the CLI's `--allow-pro` and `--source-root`. Passing them fails with a message that explains the replacement. Move the keys into the manifest, pass `{ manifest }`, and rerun `featherk-fontawesome-setup --manifest fontawesome.keys.json`, which moves Pro packages into `fontawesome-pro-sources/`. Pro packages always live in `fontawesome-pro-sources/`; installing them into the application itself is not supported.
|
|
120
120
|
|
|
121
121
|
### Render the Selected Key
|
|
122
122
|
|
|
123
|
-
```
|
|
123
|
+
```html
|
|
124
124
|
<template>
|
|
125
125
|
<!-- Step 5: Render the generated descriptor directly through Kendo. -->
|
|
126
126
|
<SvgIcon :icon="userIcon" />
|
|
@@ -173,8 +173,7 @@ The real `content` contains the complete path data; the abbreviated example is n
|
|
|
173
173
|
While viewing the application on a running Vite dev server, inspect a descriptor from the browser console:
|
|
174
174
|
|
|
175
175
|
```js
|
|
176
|
-
const { getFaIcon } =
|
|
177
|
-
await import("/@id/__x00__virtual:featherk/fontawesome");
|
|
176
|
+
const { getFaIcon } = await import("/@id/__x00__virtual:featherk/fontawesome");
|
|
178
177
|
|
|
179
178
|
console.log(getFaIcon("rocket"));
|
|
180
179
|
```
|
|
@@ -213,10 +212,6 @@ In the FeatherK monorepo, the exact root-relative pattern is `demos/src/featherk
|
|
|
213
212
|
|
|
214
213
|
Most applications need only the [Quick Start](#quick-start). Use these only when it doesn't fit.
|
|
215
214
|
|
|
216
|
-
### Pro in the Application
|
|
217
|
-
|
|
218
|
-
An application whose tooling cannot use the separate `fontawesome-pro-sources/` project can install Pro packages into its own dependencies with `featherk-fontawesome-setup --manifest fontawesome.keys.json --pro-in-app` (see [Exception: Pro in the Application](LICENSING.md#exception-pro-in-the-application)). The plugin options stay `{ manifest }`, and every build includes the Pro keys. The cost is that every install of the application, by every developer and CI job, then needs the token. Use it only with a real reason.
|
|
219
|
-
|
|
220
215
|
### Type Checks Before Vite, and Non-Vite Projects
|
|
221
216
|
|
|
222
217
|
The plugin writes its declarations when Vite starts, which is too late for a `vue-tsc` or `tsc` step that runs first. Projects in that situation, and projects that don't use Vite, generate with the `featherk-fontawesome` CLI from the same manifest; see [CLI and non-Vite setup](FontAwesomeCLI.md). Custom Node tooling can call `generateFaIcons` from `@featherk/icons/fontawesome/build`, which takes resolved keys instead of a manifest.
|
|
@@ -5,7 +5,7 @@ This is an advanced supplement. Most applications need only the Vite plugin; sta
|
|
|
5
5
|
The CLI reads the same keys-only manifest as the setup command and the Vite plugin, and selects keys the same way:
|
|
6
6
|
|
|
7
7
|
- When the project has `fontawesome-pro-sources/` (the [default setup](LICENSING.md#default-isolated-pro-sources)), it generates the `pro` keys from that project only when it is installed. Otherwise it generates the `free` keys alone.
|
|
8
|
-
- Without `fontawesome-pro-sources/` (Free-only
|
|
8
|
+
- Without `fontawesome-pro-sources/` (a Free-only setup), it generates the `free` keys; a manifest with `pro` keys then fails with a message to run the setup command.
|
|
9
9
|
|
|
10
10
|
Install source packages first with `featherk-fontawesome-setup --manifest fontawesome.keys.json` ([Install Source Packages](FontAwesome.md#install-source-packages)). The CLI validates the installed packages; it does not install them or authenticate with a registry.
|
|
11
11
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# FeatherK FontAwesome Developer Setup
|
|
2
2
|
|
|
3
|
-
This is the step-by-step setup for a developer adding Font Awesome icons to an application with `@featherk/icons`, on a local machine and in CI. It covers the default layout every team uses: Free packages in the application, Pro packages in a private `fontawesome-pro-sources/` project. For background, see [Font Awesome Build Integration](FontAwesome.md). For licensing, token handling, and the `--free-only`
|
|
3
|
+
This is the step-by-step setup for a developer adding Font Awesome icons to an application with `@featherk/icons`, on a local machine and in CI. It covers the default layout every team uses: Free packages in the application, Pro packages in a private `fontawesome-pro-sources/` project. For background, see [Font Awesome Build Integration](FontAwesome.md). For licensing, token handling, and the `--free-only` exception, see [Font Awesome Pro Licensing and Setup](LICENSING.md).
|
|
4
4
|
|
|
5
5
|
## Before You Start
|
|
6
6
|
|
|
@@ -52,9 +52,9 @@ npm run dev --workspace=@featherk/demos
|
|
|
52
52
|
npm run build --workspace=@featherk/demos
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
`setup:fontawesome:pro` runs `featherk-fontawesome-setup` without arguments, which installs `demos/fontawesome-pro-sources` from its committed lockfile with `npm ci`. The installer checks for the token without printing it. Review and commit dependency/integrity metadata for reproducible CI, ensuring it contains no credentials. Source `node_modules` and application artifacts remain ignored.
|
|
55
|
+
`setup:fontawesome:pro` runs `featherk-fontawesome-setup` without arguments, which installs `demos/fontawesome-pro-sources` from its committed lockfile with `npm ci`. The installer checks for the token without printing it. Review and commit dependency/integrity metadata for reproducible CI, ensuring it contains no credentials. Source `node_modules` and application artifacts remain ignored.
|
|
56
56
|
|
|
57
|
-
The UX-approved Pro manifest requests Regular Rocket, Light Feather, and Light
|
|
57
|
+
The UX-approved Pro manifest requests Regular Rocket, Light Feather, Light Heart, and Light House (`pro-rocket-regular`, `pro-feather-light`, `pro-heart-light`, `pro-house-light`). An authorized installation of these pins succeeded on October 15, 2026 (see [Validation Boundary](#validation-boundary)). If entitlement, releases, or exports later become unavailable, Dev must stop installation/generation and return to UX/Design for approval before changing the manifest or dependencies; never substitute silently.
|
|
58
58
|
|
|
59
59
|
The demo has no separate Pro scripts: its normal `dev` and `build` include the Pro icons once `demos/fontawesome-pro-sources` is installed, and only the Free icons otherwise. `demos/turbo.json` adds `fontawesome-pro-sources/node_modules/.package-lock.json`, which npm writes on install, to the build's cache inputs, so the root Turborepo build never replays a Free build where Pro sources are installed, or the reverse. Do not put paid outputs into shared or remote caches.
|
|
60
60
|
|
|
@@ -154,7 +154,7 @@ Without arguments, the command runs `npm ci` in `fontawesome-pro-sources/` with
|
|
|
154
154
|
|
|
155
155
|
### Setup Safety Checks
|
|
156
156
|
|
|
157
|
-
Before supplying the token, the command checks
|
|
157
|
+
Before supplying the token, the command checks `fontawesome-pro-sources/.npmrc`. It refuses any of the following:
|
|
158
158
|
|
|
159
159
|
- a `@fortawesome` registry other than `https://npm.fontawesome.com/`
|
|
160
160
|
- any reference to `FONTAWESOME_PACKAGE_TOKEN` outside `//npm.fontawesome.com/:_authToken`
|
|
@@ -162,7 +162,9 @@ Before supplying the token, the command checks the `.npmrc` it will install with
|
|
|
162
162
|
|
|
163
163
|
It also pins the Font Awesome registry on the npm command line, which overrides other npm configuration, so the token can only be sent to Font Awesome. It installs with `--ignore-scripts`, so lifecycle scripts never run while the token is present, passes the token only to that npm process, and never prints it. Setup with `--manifest` changes `package.json`, so it refuses to run in CI.
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
`npm ci` lifecycle scripts and build tools run arbitrary Node code that can read any token in their environment, and log masking does not prevent that. Give the token only to `featherk-fontawesome-setup`, never to the application's `npm ci`, its build, or a whole CI job, and do not export it persistently.
|
|
166
|
+
|
|
167
|
+
The application's own `.npmrc` must not route `@fortawesome` to a registry: Free packages come from public npm, and Pro packages only from `fontawesome-pro-sources/`. Setup refuses an application whose `.npmrc` does. That includes an application set up with the `--pro-in-app` option, which shipped in 0.16.0 and was then removed; remove the Font Awesome lines from its `.npmrc` and any `@fortawesome/pro-*` packages from its `devDependencies`, then rerun setup with `--manifest`.
|
|
166
168
|
|
|
167
169
|
### Exception: Free Only
|
|
168
170
|
|
|
@@ -174,55 +176,6 @@ npx featherk-fontawesome-setup --manifest fontawesome.keys.json --free-only
|
|
|
174
176
|
|
|
175
177
|
Free packages come from public npm. The command needs no token or CI configuration and creates no source project. The default command behaves the same way for a manifest without Pro keys; `--free-only` also guarantees it, failing if the manifest contains Pro keys, if `fontawesome-pro-sources/` exists, or if `.npmrc` routes `@fortawesome` to a registry. Configure the Vite plugin with `{ manifest: "fontawesome.keys.json" }`. To add Pro later, add the keys to the manifest and rerun without `--free-only`.
|
|
176
178
|
|
|
177
|
-
### Exception: Pro in the Application
|
|
178
|
-
|
|
179
|
-
Use this only when an isolated source project is not an option, for example when the application's toolchain cannot resolve packages from the separate `fontawesome-pro-sources/` project:
|
|
180
|
-
|
|
181
|
-
```sh
|
|
182
|
-
npx featherk-fontawesome-setup --manifest fontawesome.keys.json --pro-in-app
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
The command adds the two Font Awesome lines shown above to the application's own `.npmrc`, creating it if needed (existing settings are kept, and the lines are not duplicated on later runs), then installs the exact Free and Pro pins into the application's `devDependencies` with the token. Commit `.npmrc`, `package.json`, and `package-lock.json`, and configure the Vite plugin with `{ manifest: "fontawesome.keys.json" }`. Without `fontawesome-pro-sources/`, every build includes the Pro keys.
|
|
186
|
-
|
|
187
|
-
The cost is that the scope line routes **all** `@fortawesome` packages, Free included, to the Font Awesome registry. Every install of the application, by every developer and CI job, then needs `FONTAWESOME_PACKAGE_TOKEN` and an applicable seat.
|
|
188
|
-
|
|
189
|
-
#### Token-Scoped Installs
|
|
190
|
-
|
|
191
|
-
`npm ci` runs lifecycle scripts from the application and every dependency, and later build tools run arbitrary Node code. Any of them can read a token in their environment. Log masking and Vite's `VITE_` client-variable filter do not prevent this. Do not export the token persistently or for a whole CI build. In a Pro-in-the-application setup, give it only to an install that skips scripts, then run anything that needs scripts without it:
|
|
192
|
-
|
|
193
|
-
1. With the token: `npm ci --ignore-scripts`.
|
|
194
|
-
2. Without the token, run any install scripts the application needs:
|
|
195
|
-
- `npm rebuild` runs the dependency install scripts that step 1 skipped. On npm 12 and later, dependency scripts run only when approved in the application's `allowScripts` (`npm install-scripts approve <pkg>`), and `npm rebuild` follows the same approvals. Older npm versions run all of them.
|
|
196
|
-
- `npm rebuild` does not run the application's own lifecycle scripts. Run those explicitly, for example `npm run prepare --if-present`.
|
|
197
|
-
3. Without the token: `npm run dev`, `npm run build`, tests, and deployment. npm runs normally when the `.npmrc` placeholder is unset; only `@fortawesome` registry requests need it.
|
|
198
|
-
|
|
199
|
-
Git Bash:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
read -r -s -p "Font Awesome package token: " fa_token; echo
|
|
203
|
-
FONTAWESOME_PACKAGE_TOKEN="$fa_token" npm ci --ignore-scripts
|
|
204
|
-
install_status=$?
|
|
205
|
-
unset fa_token
|
|
206
|
-
[[ $install_status -eq 0 ]] && npm rebuild
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
PowerShell:
|
|
210
|
-
|
|
211
|
-
```powershell
|
|
212
|
-
$env:FONTAWESOME_PACKAGE_TOKEN = [System.Net.NetworkCredential]::new(
|
|
213
|
-
"", (Read-Host "Font Awesome package token" -AsSecureString)
|
|
214
|
-
).Password
|
|
215
|
-
try {
|
|
216
|
-
npm ci --ignore-scripts
|
|
217
|
-
if ($LASTEXITCODE -ne 0) { throw "Font Awesome package installation failed." }
|
|
218
|
-
} finally {
|
|
219
|
-
Remove-Item Env:FONTAWESOME_PACKAGE_TOKEN -ErrorAction SilentlyContinue
|
|
220
|
-
}
|
|
221
|
-
npm rebuild
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
The default layout needs none of this: the application's `npm ci` has no token, and `featherk-fontawesome-setup` already installs the source project with `--ignore-scripts`.
|
|
225
|
-
|
|
226
179
|
### Generation and Licensing Boundaries
|
|
227
180
|
|
|
228
181
|
Keep Pro keys in the manifest's `pro` group. Public or uncredentialed builds must not include paid inputs: run them where `fontawesome-pro-sources/` is not installed.
|
|
@@ -233,7 +186,7 @@ For non-Vite applications or declaration generation before a standalone type che
|
|
|
233
186
|
|
|
234
187
|
FeatherK and `feather-k-<demo-name>` repositories use GitHub Actions. TeamCity applies only to enterprise apps using that platform.
|
|
235
188
|
|
|
236
|
-
|
|
189
|
+
A build that includes Pro icons has three steps: the application's normal `npm ci` without the token, a token-scoped `npx featherk-fontawesome-setup` that installs `fontawesome-pro-sources/` from its lockfile, and the application's normal build without the token. Builds that don't need Pro icons skip the middle step and come out Free-only.
|
|
237
190
|
|
|
238
191
|
Use a dedicated trusted Actions job with a protected Environment and approval/branch rules. Supply the token only to source installation, not public publishing or client compilation. After checkout and Node/root dependency setup:
|
|
239
192
|
|
|
@@ -247,7 +200,7 @@ Use a dedicated trusted Actions job with a protected Environment and approval/br
|
|
|
247
200
|
run: npm run build --workspace=@featherk/demos
|
|
248
201
|
```
|
|
249
202
|
|
|
250
|
-
In CI, detected from `CI`, `TEAMCITY_VERSION`, or `GITHUB_ACTIONS`, the setup command refuses `--manifest` setup, and the source-project install requires the committed `package-lock.json`. Unattended jobs therefore only run a locked `npm ci` and never resolve new versions.
|
|
203
|
+
In CI, detected from `CI`, `TEAMCITY_VERSION`, or `GITHUB_ACTIONS`, the setup command refuses `--manifest` setup, and the source-project install requires the committed `package-lock.json`. Unattended jobs therefore only run a locked `npm ci` and never resolve new versions. Supply the token only to the `featherk-fontawesome-setup` step, never to the whole job. With no token and no interactive terminal, the command fails instead of prompting.
|
|
251
204
|
|
|
252
205
|
Configure the protected Environment separately; this fragment grants no license rights. Restrict paid caches/archives/artifacts, and never execute untrusted PR code with the token, including via `pull_request_target`. Normal public FeatherK publishing must not receive Pro credentials or use the licensed profile.
|
|
253
206
|
|
|
@@ -258,7 +211,7 @@ Do not define the token as an `env.` parameter. TeamCity passes `env.` parameter
|
|
|
258
211
|
1. In the build configuration, add a parameter named `fontawesome.package.token` with type **Password**. Use no `env.` prefix, so TeamCity does not export it to the steps' environment.
|
|
259
212
|
2. Add a Command Line step that sets the variable for one command only. Each Command Line step runs in its own process, so the variable does not carry into later steps.
|
|
260
213
|
|
|
261
|
-
|
|
214
|
+
Leave the application's existing `npm ci` step unchanged and add this step after it:
|
|
262
215
|
|
|
263
216
|
```sh
|
|
264
217
|
# Linux agent
|
|
@@ -273,21 +226,6 @@ Do not define the token as an `env.` parameter. TeamCity passes `env.` parameter
|
|
|
273
226
|
|
|
274
227
|
Leave the build step unchanged: with the sources installed, the normal build includes the Pro icons.
|
|
275
228
|
|
|
276
|
-
For [Pro in the application](#exception-pro-in-the-application), change the existing install step instead:
|
|
277
|
-
|
|
278
|
-
```sh
|
|
279
|
-
# Linux agent
|
|
280
|
-
FONTAWESOME_PACKAGE_TOKEN='%fontawesome.package.token%' npm ci --ignore-scripts
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
```bat
|
|
284
|
-
rem Windows agent
|
|
285
|
-
set "FONTAWESOME_PACKAGE_TOKEN=%fontawesome.package.token%"
|
|
286
|
-
npm ci --ignore-scripts
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
If the application or its dependencies need install scripts, add a step without the token. Use `npm rebuild` for dependency scripts, which follows `allowScripts` approvals on npm 12 and later. Run the application's own scripts explicitly, for example `npm run prepare --if-present`, because `npm rebuild` does not run them. See [Token-Scoped Installs](#token-scoped-installs).
|
|
290
|
-
|
|
291
229
|
3. Leave the build, test, and deploy steps free of the parameter. They never reference it.
|
|
292
230
|
|
|
293
231
|
Password parameters are masked in build logs, but masking does not stop code running in a step from reading the value. TeamCity also writes the step script, with the substituted value, to a temporary file on the agent. Limit the parameter to trusted build configurations and agents, and never run untrusted pull-request code in a build that defines it. Build agents must be able to reach `npm.fontawesome.com`. [Free-only](#exception-free-only) applications need no TeamCity configuration.
|
|
@@ -300,6 +238,6 @@ Enterprise Pages must enforce authentication on deployed URLs/static assets; rep
|
|
|
300
238
|
|
|
301
239
|
Public `@featherk/icons` artifacts contain tooling and owned icons only: no paid dependencies/artwork, source caches, credentials, or generated paid-icon collections. Private distribution alone does not establish entitlement.
|
|
302
240
|
|
|
303
|
-
|
|
241
|
+
Automated tests use synthetic packages, so public CI needs no secrets. On October 15, 2026, an authorized installation of `demos/fontawesome-pro-sources` was checked locally: `npm run verify:fontawesome --workspace=@featherk/demos` verified all 14 demo selections, including the four Pro exports, against the installed packages (path data, viewBox, version, and style), and the build emitted both the Free and Pro license notices. Rendering of the Pro page in a browser was not part of that check. Re-run the verification after changing pins. Pro+ collections requiring Kits remain outside this no-Kit implementation.
|
|
304
242
|
|
|
305
|
-
References: [package authentication](https://docs.fontawesome.com/web/setup/packages), [Pro license](https://fontawesome.com/license), and [Font Awesome account](https://fontawesome.com/account).
|
|
243
|
+
References: [package authentication](https://docs.fontawesome.com/web/setup/packages), [Pro license](https://fontawesome.com/license), and [Font Awesome account](https://fontawesome.com/account).
|