import fs from "fs"; import path from "path"; import { optimize } from "svgo"; import { fileURLToPath } from "url"; import { dirname } from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const mapSvgAttributes = (svgContent) => svgContent .replace(/fill-rule/g, "fillRule") .replace(/clip-rule/g, "clipRule"); const generateIconComponent = ( name, svgContent, description = "", usage = [], isDeprecated = false, aliases = [], appendIconSuffix = true ) => { const componentName = appendIconSuffix ? `${name}Icon` : name; return `import * as React from 'react'; interface IconProps extends React.SVGAttributes { children?: never; color?: string; } /** * @name ${componentName} ${aliases.length ? `* @alias ${aliases.join(", ")}` : ""} * * @description * ${description} * * ${isDeprecated ? "@deprecated\n * " : ""} * @usage * ${usage.map((item) => `- ${item}`).join("\n * ")} * * @accessibility * Asegurarse de incluir un atributo \`aria-label\` o \`aria-hidden="true"\` si el ícono es decorativo. * * @returns {JSX.Element} Componente SVG. */ const ${componentName} = React.forwardRef( ({ ...props }, forwardedRef) => { return ( ${mapSvgAttributes(svgContent).replace( " { const exports = components .map(({ name }) => prefix ? `export { ${name} as ${prefix}${name} } from "./${name}";` : `export { ${name} } from "./${name}";` ) .join("\n"); fs.writeFileSync(path.resolve(outputDir, "index.ts"), exports, "utf-8"); }; const processIcons = async ({ inputDir, outputDir, prefix = "", iconMetadata, deprecatedIcons, appendIconSuffix = true, }) => { fs.mkdirSync(outputDir, { recursive: true }); const files = fs.readdirSync(inputDir); const components = await Promise.all( files.map(async (file) => { const filePath = path.resolve(inputDir, file); if (fs.lstatSync(filePath).isDirectory()) return null; const svgContent = fs.readFileSync(filePath, "utf-8"); const { data } = await optimize(svgContent, { plugins: [] }); const baseName = file.replace(".svg", ""); const componentBaseName = baseName.replace(/(^\w|-\w)/g, clearAndUpper); const componentName = appendIconSuffix ? `${componentBaseName}Icon` : componentBaseName; const metadata = iconMetadata[componentBaseName] || {}; const description = metadata.description || ""; const usage = metadata.usage || []; const aliases = metadata.aliases || []; const isDeprecated = deprecatedIcons.includes(componentBaseName); const componentContent = generateIconComponent( componentBaseName, data, description, usage, isDeprecated, aliases, appendIconSuffix ); fs.writeFileSync( path.resolve(outputDir, `${componentName}.tsx`), componentContent, "utf-8" ); return { name: componentName, aliases }; }) ); generateIndexFile(components.filter(Boolean), outputDir, prefix); }; const clearAndUpper = (text) => text.replace(/-/, "").toUpperCase(); (async () => { const iconSets = [ { inputDir: path.resolve(__dirname, "../src/svgs/fc"), outputDir: path.resolve(__dirname, "../src/fc"), prefix: "Fc", iconMetadataPath: "../jsons/IconsList/flatColorIconsList.json", }, { inputDir: path.resolve(__dirname, "../src/svgs/fa"), outputDir: path.resolve(__dirname, "../src/fa"), prefix: "Fa", iconMetadataPath: "../jsons/IconsList/fontAwesomeIconsList.json", }, { inputDir: path.resolve(__dirname, "../src/svgs/rx"), outputDir: path.resolve(__dirname, "../src/rx"), prefix: "Rx", iconMetadataPath: "../jsons/IconsList/radixIconsList.json", }, { inputDir: path.resolve(__dirname, "../src/svgs/tfi"), outputDir: path.resolve(__dirname, "../src/tfi"), prefix: "Tfi", iconMetadataPath: "../jsons/IconsList/themifyIconsList.json", }, { inputDir: path.resolve(__dirname, "../src/svgs/hi/solid"), outputDir: path.resolve(__dirname, "../src/hi/solid"), iconMetadataPath: "../jsons/IconsList/heroiconsList.json", }, { inputDir: path.resolve(__dirname, "../src/svgs/hi/outline"), outputDir: path.resolve(__dirname, "../src/hi/outline"), iconMetadataPath: "../jsons/IconsList/heroiconsList.json", isOutline: true, }, ]; const deprecatedIcons = JSON.parse( fs.readFileSync( path.resolve(__dirname, "../jsons/IconsList/deprecated.json"), "utf-8" ) ); for (const { inputDir, outputDir, iconMetadataPath, prefix } of iconSets) { const iconMetadataFullPath = path.resolve(__dirname, iconMetadataPath); if (!fs.existsSync(iconMetadataFullPath)) { console.error( `Error: El archivo de metadatos no existe en ${iconMetadataFullPath}` ); continue; } const iconMetadata = JSON.parse( fs.readFileSync(iconMetadataFullPath, "utf-8") ); await processIcons({ inputDir, outputDir, iconMetadata, deprecatedIcons, prefix, }); } const hiSolidComponents = fs .readdirSync(path.resolve(__dirname, "../src/hi/solid")) .filter((file) => file.endsWith(".tsx")) .map((file) => ({ name: file.replace(".tsx", "") })); const hiOutlineComponents = fs .readdirSync(path.resolve(__dirname, "../src/hi/outline")) .filter((file) => file.endsWith(".tsx")) .map((file) => ({ name: file.replace(".tsx", "") })); const hiIndexExports = hiSolidComponents .map(({ name }) => `export { ${name} as Hi${name} } from "./solid";`) .concat( hiOutlineComponents.map( ({ name }) => `export { ${name} as HiOutline${name} } from "./outline";` ) ) .join("\n"); fs.writeFileSync( path.resolve(__dirname, "../src/hi/index.ts"), hiIndexExports, "utf-8" ); })();