From 4bef27dd62df1e4caf92dbfea57d07f7483429ae Mon Sep 17 00:00:00 2001 From: Phillip <69114037+Flips2001@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:13:46 +0100 Subject: [PATCH] Refactor `@comet/admin-icons` generator to accept a broader variation of SVGs (#1732) COM-366 Change the icon generator to accept icons with more than one path, as well as circles etc. and more complex structures like: ``` ``` The new icons have the same structure as the input svg files but without the `fill` prop. All other props are kept. I tested resizing and coloring, both work. --------- Co-authored-by: Phillip Lechenauer --- packages/admin/admin-icons/generate-icons.ts | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/admin/admin-icons/generate-icons.ts b/packages/admin/admin-icons/generate-icons.ts index da4d50d87f..9ba85f7d09 100644 --- a/packages/admin/admin-icons/generate-icons.ts +++ b/packages/admin/admin-icons/generate-icons.ts @@ -1,6 +1,6 @@ import { Presets, SingleBar } from "cli-progress"; import { ESLint } from "eslint"; -import { XMLParser } from "fast-xml-parser"; +import { XMLBuilder, XMLParser } from "fast-xml-parser"; import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "fs"; import { pascalCase, pascalCaseTransformMerge } from "pascal-case"; import * as path from "path"; @@ -48,9 +48,12 @@ const main = async () => { bar.increment(1, { title: `Generate icons ${icon.name}`, }); - const pathData = getPathData(icon); + const svgData = getSVGData(icon); - return writeComponent(icon, pathData); + const builder = new XMLBuilder({ ignoreAttributes: false }); + const svgString = builder.build(svgData); + + return writeComponent(icon, svgString); }), ); bar.stop(); @@ -60,15 +63,17 @@ const main = async () => { const getComponentName = (fileName: string) => pascalCase(fileName.split(".")[0], { transform: pascalCaseTransformMerge }); -const getPathData = (icon: Icon) => { +const getSVGData = (icon: Icon) => { const fileContents = readFileSync(icon.path); - const parsedXml = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: "" }).parse(fileContents.toString()); - - if (parsedXml?.svg?.path?.d === undefined) { - throw new Error(`The file ${icon.name} must contain a element with a d attribute`); - } + const parsedXml = new XMLParser({ + ignoreAttributes: false, + updateTag(_, __, attrs) { + delete attrs["@_fill"]; + return true; + }, + }).parse(fileContents.toString()); - return parsedXml.svg.path.d; + return parsedXml.svg; }; const getFormattedText = async (text: string) => { @@ -81,7 +86,7 @@ const getFormattedText = async (text: string) => { return results[0].output; }; -const writeComponent = async (icon: Icon, pathData: string) => { +const writeComponent = async (icon: Icon, svgString: string) => { const component = await getFormattedText(` import { SvgIcon, SvgIconProps } from "@mui/material"; import * as React from "react"; @@ -96,7 +101,7 @@ const writeComponent = async (icon: Icon, pathData: string) => { export const ${icon.componentName} = React.forwardRef((props, ref) => { return ( - + ${svgString} ); });