mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-08-29 09:28:23 +02:00
fix(@lucide/lab): Fix lab build (#4618)
* chore(lab): Adjust build scripts * add check workflow * Potential fix for pull request finding 'CodeQL / Workflow does not contain permissions' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * update gitignore --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
30
.github/workflows/lucide-lab.yml
vendored
Normal file
30
.github/workflows/lucide-lab.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: Lucide Lab checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- packages/lab/**
|
||||||
|
- packages/shared/**
|
||||||
|
- tools/build-icons/**
|
||||||
|
- tools/rollup-plugins/**
|
||||||
|
- pnpm-lock.yaml
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: 'pnpm'
|
||||||
|
node-version-file: 'package.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm --filter @lucide/lab build
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -61,4 +61,3 @@ docs/.vercel
|
|||||||
docs/.nitro
|
docs/.nitro
|
||||||
docs/public/og/**
|
docs/public/og/**
|
||||||
!docs/public/og/general.png
|
!docs/public/og/general.png
|
||||||
.gitignore
|
|
||||||
|
|||||||
2
packages/lab/.gitignore
vendored
Normal file
2
packages/lab/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
icons
|
||||||
|
icon-nodes.json
|
||||||
@@ -27,17 +27,17 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||||
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundle && pnpm build:lib",
|
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundle && pnpm build:lib",
|
||||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts --withAliases --exportModuleNameCasing=camel --renderUniqueKey --aliasNamesOnly --aliasesFileExtension=.ts --exportFileName=index.ts",
|
"build:icons": "build-icons --input=../../lab --output=./src --templateSrc=./scripts/exportTemplate.mts --iconFileExtension=.ts --exportModuleNameCasing=camel --renderUniqueKey --exportFileName=index.ts",
|
||||||
"build:lib": "node ./scripts/buildLib.mjs",
|
"build:lib": "node ./scripts/buildLib.mts",
|
||||||
"build:bundle": "rollup -c rollup.config.mjs",
|
"build:bundle": "rollup -c rollup.config.mjs",
|
||||||
"clean": "rm -f src/icons/*.ts && rm -rf dist",
|
"clean": "rm -f src/icons/*.ts && rm -rf dist && rm -rf icons && rm -f icon-nodes.json",
|
||||||
"version": "pnpm version --git-tag-version=false"
|
"version": "pnpm version --git-tag-version=false"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lucide/build-icons": "workspace:*",
|
"@lucide/build-icons": "workspace:*",
|
||||||
"@lucide/helpers": "workspace:*",
|
"@lucide/helpers": "workspace:*",
|
||||||
"@lucide/rollup-plugins": "workspace:*",
|
"@lucide/rollup-plugins": "workspace:*",
|
||||||
"minimist": "^1.2.8",
|
"@types/node": "^22.20.1",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"rollup": "^4.9.2",
|
"rollup": "^4.9.2",
|
||||||
"rollup-plugin-dts": "^6.1.0",
|
"rollup-plugin-dts": "^6.1.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import plugins from '@lucide/rollup-plugins';
|
import plugins from '@lucide/rollup-plugins';
|
||||||
import dts from 'rollup-plugin-dts';
|
import dts from 'rollup-plugin-dts';
|
||||||
import pkg from './package.json' assert { type: 'json' };
|
import pkg from './package.json' with { type: 'json' };
|
||||||
|
|
||||||
const outputFileName = 'lucide-lab';
|
const outputFileName = 'lucide-lab';
|
||||||
const outputDir = 'dist';
|
const outputDir = 'dist';
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import getArgumentOptions from 'minimist';
|
|
||||||
import { parseSync } from 'svgson';
|
|
||||||
|
|
||||||
import { readSvgDirectory, getCurrentDirPath } from '@lucide/helpers';
|
|
||||||
import readSvgs from './readSvgs.mjs';
|
|
||||||
import generateIconNodes from './generateIconNodes.mjs';
|
|
||||||
import copyIcons from './copyIcons.mjs';
|
|
||||||
|
|
||||||
import pkg from '../package.json' assert { type: 'json' };
|
|
||||||
|
|
||||||
const cliArguments = getArgumentOptions(process.argv.slice(2));
|
|
||||||
const createDirectory = (dir) => {
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
fs.mkdirSync(dir);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const currentDir = getCurrentDirPath(import.meta.url);
|
|
||||||
|
|
||||||
const PACKAGE_DIR = path.resolve(currentDir, '../');
|
|
||||||
const ICONS_DIR = path.join(PACKAGE_DIR, '../../icons');
|
|
||||||
|
|
||||||
const license = `@license ${pkg.name} v${pkg.version} - ${pkg.license}`;
|
|
||||||
|
|
||||||
const svgFiles = await readSvgDirectory(ICONS_DIR);
|
|
||||||
const svgs = await readSvgs(svgFiles, ICONS_DIR);
|
|
||||||
|
|
||||||
const parsedSvgs = svgs.map(({ name, contents }) => ({
|
|
||||||
name,
|
|
||||||
contents,
|
|
||||||
parsedSvg: parseSync(contents),
|
|
||||||
}));
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
generateIconNodes(parsedSvgs, PACKAGE_DIR),
|
|
||||||
copyIcons(parsedSvgs, PACKAGE_DIR, license),
|
|
||||||
]);
|
|
||||||
20
packages/lab/scripts/buildLib.mts
Normal file
20
packages/lab/scripts/buildLib.mts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
import { readSvgDirectory, getCurrentDirPath } from '@lucide/helpers';
|
||||||
|
import readSvgs from './readSvgs.mts';
|
||||||
|
import generateIconNodes from './generateIconNodes.mts';
|
||||||
|
import copyIcons from './copyIcons.mts';
|
||||||
|
|
||||||
|
import pkg from '../package.json' with { type: 'json' };
|
||||||
|
|
||||||
|
const currentDir = getCurrentDirPath(import.meta.url);
|
||||||
|
|
||||||
|
const PACKAGE_DIR = path.resolve(currentDir, '../');
|
||||||
|
const ICONS_DIR = path.join(PACKAGE_DIR, '../../lab');
|
||||||
|
|
||||||
|
const license = `@license ${pkg.name} v${pkg.version} - ${pkg.license}`;
|
||||||
|
|
||||||
|
const svgFiles = await readSvgDirectory(ICONS_DIR);
|
||||||
|
const svgs = await readSvgs(svgFiles, ICONS_DIR);
|
||||||
|
|
||||||
|
await Promise.all([generateIconNodes(svgs, PACKAGE_DIR), copyIcons(svgs, PACKAGE_DIR, license)]);
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
import { writeFile } from 'fs/promises';
|
import { writeFile } from 'fs/promises';
|
||||||
import { existsSync, unlinkSync, mkdirSync } from 'fs';
|
import { existsSync, unlinkSync, mkdirSync } from 'fs';
|
||||||
|
import { type SVGFile } from './readSvgs.mts';
|
||||||
|
|
||||||
export default async function copyIcons(parsedSvgs, packageDir, license) {
|
export default async function copyIcons(
|
||||||
|
parsedSvgs: SVGFile[],
|
||||||
|
packageDir: string,
|
||||||
|
license: string,
|
||||||
|
) {
|
||||||
const iconsDirectory = `${packageDir}/icons`;
|
const iconsDirectory = `${packageDir}/icons`;
|
||||||
|
|
||||||
if (existsSync(iconsDirectory)) {
|
if (existsSync(iconsDirectory)) {
|
||||||
try {
|
unlinkSync(iconsDirectory);
|
||||||
unlinkSync(iconsDirectory);
|
|
||||||
} catch (error) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!existsSync(iconsDirectory)) {
|
if (!existsSync(iconsDirectory)) {
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||||
import base64SVG from '@lucide/build-icons/utils/base64SVG.mjs';
|
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||||
import { toCamelCase } from '@lucide/helpers';
|
import { toCamelCase } from '@lucide/helpers';
|
||||||
|
|
||||||
export default ({ componentName, iconName, children, getSvg, deprecated }) => {
|
export default defineExportTemplate(
|
||||||
const svgContents = getSvg();
|
async ({ componentName, iconName, children, getSvg, deprecated, deprecationReason }) => {
|
||||||
const svgBase64 = base64SVG(svgContents);
|
const svgContents = await getSvg();
|
||||||
|
const svgBase64 = base64SVG(svgContents);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
import type { IconNode } from '../types';
|
import type { IconNode } from '../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,10 +18,11 @@ import type { IconNode } from '../types';
|
|||||||
* @see https://lucide.dev/guide/packages/lucide - Documentation
|
* @see https://lucide.dev/guide/packages/lucide - Documentation
|
||||||
*
|
*
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
* ${deprecated ? '@deprecated' : ''}
|
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||||
*/
|
*/
|
||||||
const ${toCamelCase(componentName)}: IconNode = ${JSON.stringify(children)};
|
const ${toCamelCase(componentName)}: IconNode = ${JSON.stringify(children)};
|
||||||
|
|
||||||
export default ${toCamelCase(componentName)};
|
export default ${toCamelCase(componentName)};
|
||||||
`;
|
`;
|
||||||
};
|
},
|
||||||
|
);
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import { writeFile } from '@lucide/helpers';
|
import { writeFile } from '@lucide/helpers';
|
||||||
|
import { type SVGFile } from './readSvgs.mts';
|
||||||
|
|
||||||
export default async function generateIconNodes(parsedSvgs, packageDir) {
|
export default async function generateIconNodes(parsedSvgs: SVGFile[], packageDir: string) {
|
||||||
const iconNodes = parsedSvgs.reduce((acc, { name, parsedSvg }) => {
|
const iconNodes = parsedSvgs.reduce((acc, { name, parsedSvg }) => {
|
||||||
acc[name] = parsedSvg.children.map(({ name, attributes }) => [name, attributes]);
|
acc[name] = parsedSvg.children.map(({ name, attributes }) => [name, attributes]);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {} as Record<string, [string, Record<string, unknown> | undefined][]>);
|
||||||
|
|
||||||
const iconNodesStringified = JSON.stringify(iconNodes, null, 2);
|
const iconNodesStringified = JSON.stringify(iconNodes, null, 2);
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
import { basename } from 'path';
|
import { basename } from 'path';
|
||||||
import { readSvg } from '@lucide/helpers';
|
import { readSvg } from '@lucide/helpers';
|
||||||
|
import { type INode, parseSync } from 'svgson';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an object in the format: `{ <name>: <contents> }`.
|
* Build an object in the format: `{ <name>: <contents> }`.
|
||||||
@@ -8,13 +9,23 @@ import { readSvg } from '@lucide/helpers';
|
|||||||
* @param {Function} getSvg - A function that returns the contents of an SVG file given a filename.
|
* @param {Function} getSvg - A function that returns the contents of an SVG file given a filename.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export default async function readSVGs(svgFiles, iconsDirectory) {
|
export default function readSVGs(svgFiles: string[], iconsDirectory: string) {
|
||||||
const svgReadPromises = svgFiles.map(async (svgFile) => {
|
const SVGReadPromises = svgFiles.map(async (svgFile) => {
|
||||||
const name = basename(svgFile, '.svg');
|
const name = basename(svgFile, '.svg');
|
||||||
const contents = await readSvg(svgFile, iconsDirectory);
|
const contents = await readSvg(svgFile, iconsDirectory);
|
||||||
|
|
||||||
return { name, contents };
|
return {
|
||||||
|
name,
|
||||||
|
contents,
|
||||||
|
parsedSvg: parseSync(contents),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(svgReadPromises);
|
return Promise.all(SVGReadPromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SVGFile = {
|
||||||
|
name: string;
|
||||||
|
contents: string;
|
||||||
|
parsedSvg: INode;
|
||||||
|
};
|
||||||
@@ -1,2 +1 @@
|
|||||||
export * from './icons';
|
export * from './icons';
|
||||||
export * from './aliases';
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"lib": ["esnext", "dom"],
|
"lib": ["esnext", "dom"],
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
},
|
},
|
||||||
|
|||||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -406,9 +406,9 @@ importers:
|
|||||||
'@lucide/rollup-plugins':
|
'@lucide/rollup-plugins':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../tools/rollup-plugins
|
version: link:../../tools/rollup-plugins
|
||||||
minimist:
|
'@types/node':
|
||||||
specifier: ^1.2.8
|
specifier: ^22.20.1
|
||||||
version: 1.2.8
|
version: 22.20.1
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^2.3.2
|
specifier: ^2.3.2
|
||||||
version: 2.8.8
|
version: 2.8.8
|
||||||
|
|||||||
@@ -34,11 +34,12 @@ interface CliArguments {
|
|||||||
useDefaultExports?: boolean;
|
useDefaultExports?: boolean;
|
||||||
pretty?: boolean;
|
pretty?: boolean;
|
||||||
output: string | undefined;
|
output: string | undefined;
|
||||||
|
input: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cliArguments = getArgumentOptions(process.argv.slice(2)) as unknown as CliArguments;
|
const cliArguments = getArgumentOptions(process.argv.slice(2)) as unknown as CliArguments;
|
||||||
|
|
||||||
const ICONS_DIR = path.resolve(process.cwd(), '../../icons');
|
const ICONS_DIR = path.resolve(process.cwd(), cliArguments.input || '../../icons');
|
||||||
const OUTPUT_DIR = path.resolve(process.cwd(), cliArguments.output || '../build');
|
const OUTPUT_DIR = path.resolve(process.cwd(), cliArguments.output || '../build');
|
||||||
|
|
||||||
if (!fs.existsSync(OUTPUT_DIR)) {
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user