Files
lucide/docs/scripts/writeIconDetails.mts
T
Eric FennisClaude Opus 5.5github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
7bf67d3b1c feat(metadata|docs|site): reuse metadata from a base icon with $extends: (#4360)
* feat(metadata): reuse metadata from a base icon with `$extends:`

Icon metadata can reference a base icon with an inline `$extends:<icon-name>`
marker in `tags`, `categories` or `contributors`. The marker is replaced in
place with the base icon's resolved values at build time.

- Resolve markers in `readAllMetadata` and `getIconMetaData`, failing on
  unknown icons, self references and circular chains
- Accept markers in `icon.schema.json`
- `pnpm checkIcons` fails on duplicate markers and on literals a marker
  already provides, and runs in CI
- Docs read the resolved metadata index instead of the raw icon JSON
- Use `$extends:alarm-clock` in `alarm-clock-minus`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(metadata): reuse metadata from a base icon with `$extends:`

Icon metadata can reference a base icon with an inline `$extends:<icon-name>`
marker in `tags`, `categories` or `contributors`. The marker is replaced in
place with the base icon's resolved values at build time.

- Resolve markers in `readAllMetadata` and `getIconMetaData`, failing on
  unknown icons, self references and circular chains
- Accept markers in `icon.schema.json`
- `pnpm checkIcons` fails on duplicate markers and on literals a marker
  already provides, and runs in CI
- Docs read the resolved metadata index instead of the raw icon JSON
- Use `$extends:alarm-clock` in `alarm-clock-minus`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix comments

* Format code

* Update tools/build-helpers/src/resolveMetadataExtends.ts

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix resolving icon metadata

* feat(metadata): reuse metadata from a base icon with `$extends:`

Icon metadata can reference a base icon with an inline `$extends:<icon-name>`
marker in `tags`, `categories` or `contributors`. The marker is replaced in
place with the base icon's resolved values at build time.

- Resolve markers in `readAllMetadata` and `getIconMetaData`, failing on
  unknown icons, self references and circular chains
- Accept markers in `icon.schema.json`
- `pnpm checkIcons` fails on duplicate markers and on literals a marker
  already provides, and runs in CI
- Docs read the resolved metadata index instead of the raw icon JSON
- Use `$extends:alarm-clock` in `alarm-clock-minus`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix comments

* Format code

* Update tools/build-helpers/src/resolveMetadataExtends.ts

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix resolving icon metadata

* Fix comments

* Format code

* Update tools/build-helpers/src/resolveMetadataExtends.ts

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-29 17:29:58 +01:00

76 lines
2.2 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import { getIconMetaData } from '@lucide/build-icons';
import { toCamelCase } from '@lucide/helpers';
const currentDir = process.cwd();
const ICONS_DIR = path.resolve(currentDir, '../icons');
const iconMetaData = await getIconMetaData(ICONS_DIR);
const iconDetailsDirectory = path.resolve(currentDir, '.vitepress/data', 'iconDetails');
if (fs.existsSync(iconDetailsDirectory)) {
fs.rmSync(iconDetailsDirectory, { recursive: true, force: true });
}
if (!fs.existsSync(iconDetailsDirectory)) {
fs.mkdirSync(iconDetailsDirectory);
}
const indexFile = path.resolve(iconDetailsDirectory, `index.ts`);
const writeIconFiles = Object.entries(iconMetaData).map(async ([iconName, metaData]) => {
const location = path.resolve(iconDetailsDirectory, `${iconName}.ts`);
const {
tags,
categories,
contributors,
aliases,
deprecated,
deprecationReason,
toBeRemovedInVersion,
} = metaData;
const contents = `\
import iconNode from '../iconNodes/${iconName}.node.json' with { type: 'json' };
import releaseData from '../releaseMetadata/${iconName}.json' with { type: 'json' };
import popularity from '../iconPopularity/${iconName}.json' with { type: 'json' };
import { IconMetaData, IconNode } from '~/.vitepress/theme/types';
const metaData: IconMetaData = ${JSON.stringify({ tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion })};
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData;
const iconDetails = {
name: '${iconName}',
iconNode: iconNode as IconNode,
contributors,
tags,
categories,
aliases,
deprecated,
popularity,
deprecationReason,
toBeRemovedInVersion,
...releaseData,
};
export default iconDetails;
`;
await fs.promises.writeFile(location, contents, 'utf-8');
await fs.promises.appendFile(
indexFile,
`export { default as ${toCamelCase(iconName)} } from './${iconName}';\n`,
'utf-8',
);
});
Promise.all(writeIconFiles)
.then(() => {
console.log('Successfully write', writeIconFiles.length, 'iconDetails files.');
})
.catch((error) => {
throw new Error(`Something went wrong generating iconNode files,\n ${error}`);
});