import fs from 'fs'; import path from 'path'; import { parseSync } from 'svgson'; import { shuffleArray, readSvgDirectory, getCurrentDirPath, minifySvg, toPascalCase, } from '../tools/build-helpers/helpers.ts'; const currentDir = getCurrentDirPath(import.meta.url); const ICONS_DIR = path.resolve(currentDir, '../icons'); const BASE_URL = 'https://lucide.dev/api/gh-icon'; const changedFilesPathString = process.env.CHANGED_FILES; if (changedFilesPathString == null) { console.error('CHANGED_FILES env variable is not set'); process.exit(1); } const changedFiles = changedFilesPathString .split(' ') .filter((file) => file.includes('.svg')) .filter((file, idx, arr) => arr.indexOf(file) === idx); if (changedFiles.length === 0) { console.log('No changed icons found'); process.exit(0); } const getImageTagsByFiles = (files: string[], getBaseUrl: (file: string) => string, width?: number) => files.map((file) => { const svgContent = fs.readFileSync(path.join(process.cwd(), file), 'utf-8'); const strippedAttrsSVG = svgContent.replace(/]*>/, ''); const minifiedSvg = minifySvg(strippedAttrsSVG); const base64 = Buffer.from(minifiedSvg).toString('base64'); const url = getBaseUrl(file); const widthAttr = width ? `width="${width}"` : ''; return `${file}`; }); const svgFiles = await readSvgDirectory(ICONS_DIR); const svgFilePaths = svgFiles.map((file) => `icons/${file}`); const iconsFilteredByName = (search: string) => svgFilePaths.filter((file) => file.includes(search)); const cohesionRandomImageTags = getImageTagsByFiles( shuffleArray(svgFilePaths).slice(0, changedFiles.length), () => `${BASE_URL}/stroke-width/2`, ).join(''); const cohesionSquaresImageTags = getImageTagsByFiles( shuffleArray(iconsFilteredByName('square')).slice(0, changedFiles.length), () => `${BASE_URL}/stroke-width/2`, ).join(''); const changeFiles1pxStrokeImageTags = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/stroke-width/1`, ).join(''); const changeFiles2pxStrokeImageTags = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/stroke-width/2`, ).join(''); const changeFiles3pxStrokeImageTags = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/stroke-width/3`, ).join(''); const changeFilesLowDPIImageTags16 = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/dpi/16`, ).join(' '); const changeFilesLowDPIImageTags24 = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/dpi/24`, ).join(' '); const changeFilesLowDPIImageTags32 = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/dpi/32`, ).join(' '); const changeFilesLowDPIImageTags48 = getImageTagsByFiles( changedFiles, () => `${BASE_URL}/dpi/48`, ).join(' '); const changeFilesXRayImageTags = getImageTagsByFiles( changedFiles, (file) => { const iconName = path.basename(file, '.svg'); return `${BASE_URL}/${iconName}`; }, 400, ).join(' '); const changeFilesDiffImageTags = getImageTagsByFiles( changedFiles, (file) => { const iconName = path.basename(file, '.svg'); return `${BASE_URL}/diff/${iconName}`; }, 400, ).join(' '); const readyToUseCode = changedFiles .map((changedFile) => { const svgContent = fs.readFileSync(path.join(process.cwd(), changedFile), 'utf-8'); const name = path.basename(changedFile, '.svg'); return `const ${toPascalCase(name)}Icon = createLucideIcon('${toPascalCase(name)}', [ ${parseSync(svgContent) .children.map(({ name, attributes }) => JSON.stringify([name, attributes])) .join(',\n ')} ])`; }) .join('\n\n'); const commentMarkup = `\ ### Added or changed icons ${changeFiles2pxStrokeImageTags}
Preview cohesion ${cohesionSquaresImageTags}
${changeFiles2pxStrokeImageTags}
${cohesionRandomImageTags}
Preview stroke widths ${changeFiles1pxStrokeImageTags}
${changeFiles2pxStrokeImageTags}
${changeFiles3pxStrokeImageTags}
DPI Preview

16px (shadcn/ui)

${changeFilesLowDPIImageTags16}

24px (default)

${changeFilesLowDPIImageTags24}

32px (shadcn/ui + retina)

${changeFilesLowDPIImageTags32}

48px (default + retina)

${changeFilesLowDPIImageTags48}
Icon X-rays ${changeFilesXRayImageTags}
Icon Diffs ${changeFilesDiffImageTags}
Icons as code Works for: \`lucide-react\`, \`lucide-react-native\`, \`lucide-preact\`, \`lucide-vue-next\` \`\`\`ts ${readyToUseCode} \`\`\`
`; console.log(commentMarkup);