227 lines
6.1 KiB
JavaScript
227 lines
6.1 KiB
JavaScript
|
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<SVGElement> {
|
||
|
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<SVGSVGElement, IconProps>(
|
||
|
({ ...props }, forwardedRef) => {
|
||
|
return (
|
||
|
${mapSvgAttributes(svgContent).replace(
|
||
|
"<svg",
|
||
|
"<svg {...props} ref={forwardedRef}"
|
||
|
)}
|
||
|
);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
${componentName}.displayName = '${componentName}';
|
||
|
|
||
|
export { ${componentName} };
|
||
|
`;
|
||
|
};
|
||
|
|
||
|
const generateIndexFile = (components, outputDir, prefix = "") => {
|
||
|
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"
|
||
|
);
|
||
|
})();
|