@featherk/icons 0.16.0 → 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 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
- `viewBox` overrides the SVG viewBox; `color` replaces `currentColor` fills/strokes.
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
- viewBox: "0 0 28 28",
53
- color: "var(--kendo-color-primary)",
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
- color: "var(--kendo-color-success)",
58
- });
56
+ const successIcon = getCustomIcon("check", {
57
+ color: "var(--kendo-color-success)",
58
+ });
59
59
  </script>
60
60
  ```
61
61
 
@@ -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.0";
4
+ export const version = "0.16.1";
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.0/docs/fontawesome/CreateFontAwesomeManifest.md",
16
- FontAwesome: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.0/docs/fontawesome/FontAwesome.md",
17
- FontAwesomeCLI: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.0/docs/fontawesome/FontAwesomeCLI.md",
18
- FontAwesomeDeveloperSetup: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.0/docs/fontawesome/FontAwesomeDeveloperSetup.md",
19
- LICENSING: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.0/docs/fontawesome/LICENSING.md",
15
+ CreateFontAwesomeManifest: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.1/docs/fontawesome/CreateFontAwesomeManifest.md",
16
+ FontAwesome: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.1/docs/fontawesome/FontAwesome.md",
17
+ FontAwesomeCLI: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.1/docs/fontawesome/FontAwesomeCLI.md",
18
+ FontAwesomeDeveloperSetup: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.1/docs/fontawesome/FontAwesomeDeveloperSetup.md",
19
+ LICENSING: "https://cdn.jsdelivr.net/npm/@featherk/icons@0.16.1/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
- return { keys, allowPro: true };
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
- return { keys, allowPro: true };
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 };
@@ -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-Yjw62jxG.cjs");
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
- When the project has a ${manifest.fontAwesomeProSourcesDir}/ source project (the
12
- default setup), Pro keys are generated from it only when it is installed.
13
- Otherwise all keys are generated from the project's own installed sources.
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.`;
@@ -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-CSRIDvaR.mjs";
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
- When the project has a ${fontAwesomeProSourcesDir}/ source project (the
10
- default setup), Pro keys are generated from it only when it is installed.
11
- Otherwise all keys are generated from the project's own installed sources.
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
- * In the isolated layout, the `pro` keys are selected, and resolved from
43
- * `fontawesome-pro-sources`, only when that project is installed; otherwise
44
- * the build is Free-only and never reads it. Without the isolated project,
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-Yjw62jxG.cjs");
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 | --pro-in-app]
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 installIntoApp(pins, pro, token, context) {
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, hasAuth } = checkNpmrc(config, ".npmrc");
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 (proInApp && isolated) {
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}, so this app installs Pro in the app itself. Rerun with --pro-in-app.`
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 = installIntoApp(freePins, false, void 0, context);
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"] || values["pro-in-app"]) {
464
- throw new Error("--free-only and --pro-in-app require --manifest.");
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, writeFileSync, mkdirSync, rmSync } from "node:fs";
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-CSRIDvaR.mjs";
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 | --pro-in-app]
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 installIntoApp(pins, pro, token, context) {
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, hasAuth } = checkNpmrc(config, ".npmrc");
336
+ const { fontAwesomeRegistry } = checkNpmrc(config, ".npmrc");
346
337
  const sourceRoot = resolve(appRoot, fontAwesomeProSourcesDir);
347
338
  const isolated = isFontAwesomeIsolated(appRoot);
348
- if (proInApp && isolated) {
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}, so this app installs Pro in the app itself. Rerun with --pro-in-app.`
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 = installIntoApp(freePins, false, void 0, context);
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"] || values["pro-in-app"]) {
462
- throw new Error("--free-only and --pro-in-app require --manifest.");
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-Yjw62jxG.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) {
@@ -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
- * When the project has a `fontawesome-pro-sources/` source project (the
8
- * default setup), the manifest's `pro` keys are generated from it only in
9
- * builds where that project is installed. Otherwise every key comes from the
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-CSRIDvaR.mjs";
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) {
@@ -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` | Destination in this repository |
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.
@@ -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
- wrapped `url("...")` string suitable for assigning directly to CSS
11
- `background-image` (UTF‑8 and base64 variants respectively).
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
- backgrounds or masks in styles.
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("--search-icon", `url("${searchIconUrl}")`);
34
+ document.documentElement.style.setProperty(
35
+ "--search-icon",
36
+ `url("${searchIconUrl}")`,
37
+ );
34
38
  ```
35
39
 
36
40
  ```css
37
41
  .button::after {
38
- content: "";
39
- display: inline-block;
40
- width: 1em;
41
- height: 1em;
42
- background: no-repeat center/contain var(--search-icon);
43
- /* Alternatively, to tint using current text color:
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
- margin-left: 0.25rem;
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 { getCustomIcon, getIconCssUrl, getIconCssUrlBase64 } from "@featherk/icons";
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("--search-icon", `url("${searchIconUrlBase64}")`);
85
+ document.documentElement.style.setProperty(
86
+ "--search-icon",
87
+ `url("${searchIconUrlBase64}")`,
88
+ );
78
89
  ```
79
-
package/docs/ICONS.md CHANGED
@@ -211,4 +211,4 @@
211
211
  |rating_star_selected|switch_left|switch_off|switch_on|switch_right| |
212
212
  <!-- markdownlint-enable MD033-->
213
213
 
214
- > Generated: 2026-10-15T21:01:16.022Z
214
+ > Generated: 2026-10-16T17:15:34.562Z
@@ -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 | 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 |
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 token-scoped install step in CI), builds include the Pro icons. Where it isn't installed, builds include only the Free icons.
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
- ```vue
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 `--pro-in-app` exception. Never put a Pro token in a command or commit it.
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. An application set up with `--pro-in-app` has no such directory, so every build includes its `pro` keys from the application's own packages. 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.
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/`. An application that installed Pro into its own dependencies keeps that layout with `--pro-in-app`.
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
- ```vue
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 or `--pro-in-app` setups), it generates every manifest key from the application's installed packages.
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` and `--pro-in-app` exceptions, see [Font Awesome Pro Licensing and Setup](LICENSING.md).
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. No paid installation has been performed as part of implementing this setup.
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 Heart. These pins are requested examples, not verified downloads. If entitlement, releases, or exports are unavailable, Dev must stop installation/generation and return to UX/Design for approval before changing the manifest or dependencies; never substitute silently.
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 the `.npmrc` it will install with: the application's for `--pro-in-app`, and `fontawesome-pro-sources/.npmrc` for the default layout. It refuses any of the following:
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
- The layouts cannot be mixed in one application. The default setup refuses an application whose `.npmrc` already routes `@fortawesome` to the Pro registry, and `--pro-in-app` refuses an application that has `fontawesome-pro-sources/`.
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
- In the default layout, a Pro build 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.
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. In every layout, supply the token only to the install step that skips lifecycle scripts, never to the whole job. With no token and no interactive terminal, the command fails instead of prompting.
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
- For the [default layout](#default-isolated-pro-sources), leave the application's existing `npm ci` step unchanged and add this step after it:
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
- Isolated-source resolution uses synthetic tests. Free generation and Pro-unavailable UI can be checked without secrets. Real paid exports, license notices, and enabled Pro rendering remain unverified until an authorized installation succeeds. Pro+ collections requiring Kits remain outside this no-Kit implementation.
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).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featherk/icons",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "main": "dist/featherk-icons.umd.js",
5
5
  "module": "dist/featherk-icons.es.js",
6
6
  "types": "dist/index.d.ts",