mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-08-29 08:48:22 +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/public/og/**
|
||||
!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": {
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"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:lib": "node ./scripts/buildLib.mjs",
|
||||
"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.mts",
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lucide/build-icons": "workspace:*",
|
||||
"@lucide/helpers": "workspace:*",
|
||||
"@lucide/rollup-plugins": "workspace:*",
|
||||
"minimist": "^1.2.8",
|
||||
"@types/node": "^22.20.1",
|
||||
"prettier": "^2.3.2",
|
||||
"rollup": "^4.9.2",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import plugins from '@lucide/rollup-plugins';
|
||||
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 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 { 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`;
|
||||
|
||||
if (existsSync(iconsDirectory)) {
|
||||
try {
|
||||
unlinkSync(iconsDirectory);
|
||||
} catch (error) {}
|
||||
unlinkSync(iconsDirectory);
|
||||
}
|
||||
|
||||
if (!existsSync(iconsDirectory)) {
|
||||
@@ -1,12 +1,13 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG.mjs';
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
import { toCamelCase } from '@lucide/helpers';
|
||||
|
||||
export default ({ componentName, iconName, children, getSvg, deprecated }) => {
|
||||
const svgContents = getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
export default defineExportTemplate(
|
||||
async ({ componentName, iconName, children, getSvg, deprecated, deprecationReason }) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `
|
||||
return `
|
||||
import type { IconNode } from '../types';
|
||||
|
||||
/**
|
||||
@@ -17,10 +18,11 @@ import type { IconNode } from '../types';
|
||||
* @see https://lucide.dev/guide/packages/lucide - Documentation
|
||||
*
|
||||
* @returns {Array}
|
||||
* ${deprecated ? '@deprecated' : ''}
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
const ${toCamelCase(componentName)}: IconNode = ${JSON.stringify(children)};
|
||||
|
||||
export default ${toCamelCase(componentName)};
|
||||
`;
|
||||
};
|
||||
},
|
||||
);
|
||||
@@ -1,11 +1,12 @@
|
||||
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 }) => {
|
||||
acc[name] = parsedSvg.children.map(({ name, attributes }) => [name, attributes]);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}, {} as Record<string, [string, Record<string, unknown> | undefined][]>);
|
||||
|
||||
const iconNodesStringified = JSON.stringify(iconNodes, null, 2);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import { basename } from 'path';
|
||||
import { readSvg } from '@lucide/helpers';
|
||||
import { type INode, parseSync } from 'svgson';
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export default async function readSVGs(svgFiles, iconsDirectory) {
|
||||
const svgReadPromises = svgFiles.map(async (svgFile) => {
|
||||
export default function readSVGs(svgFiles: string[], iconsDirectory: string) {
|
||||
const SVGReadPromises = svgFiles.map(async (svgFile) => {
|
||||
const name = basename(svgFile, '.svg');
|
||||
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 './aliases';
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"allowJs": true,
|
||||
"lib": ["esnext", "dom"],
|
||||
"resolveJsonModule": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
},
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -406,9 +406,9 @@ importers:
|
||||
'@lucide/rollup-plugins':
|
||||
specifier: workspace:*
|
||||
version: link:../../tools/rollup-plugins
|
||||
minimist:
|
||||
specifier: ^1.2.8
|
||||
version: 1.2.8
|
||||
'@types/node':
|
||||
specifier: ^22.20.1
|
||||
version: 22.20.1
|
||||
prettier:
|
||||
specifier: ^2.3.2
|
||||
version: 2.8.8
|
||||
|
||||
@@ -34,11 +34,12 @@ interface CliArguments {
|
||||
useDefaultExports?: boolean;
|
||||
pretty?: boolean;
|
||||
output: string | undefined;
|
||||
input: string | undefined;
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||
|
||||
Reference in New Issue
Block a user