Skip to content

Commit

Permalink
Refactor @comet/admin-icons generator to accept a broader variation…
Browse files Browse the repository at this point in the history
… 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:
```
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16">
  <g clip-path="url(#a)">
    <path fill="#242424" fill-rule="evenodd" d="M7.529.401a.5.5 0 0 1 .275.082l.076.06 3.647 3.574a.5.5 0 0 1-.63.772l-.07-.058-3.501-3.43-5.99.015.003 5.968 7.474 7.475 5.994-5.994-1.578-1.681a.5.5 0 0 1-.038-.64l.06-.067a.5.5 0 0 1 .64-.038l.067.06 1.91 2.034a.5.5 0 0 1 .046.628l-.056.068-6.69 6.69a.5.5 0 0 1-.639.058l-.069-.057L.486 7.945a.5.5 0 0 1-.14-.274l-.007-.08L.335.918a.5.5 0 0 1 .41-.492l.09-.008L7.528.4ZM5 4a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z" clip-rule="evenodd"/>
  </g>
  <defs>
    <clipPath id="a">
      <path fill="#fff" d="M0 0h16v16H0z"/>
    </clipPath>
  </defs>
</svg>
```
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 <phillip.lechenauer@vivid-planet.com>
  • Loading branch information
Flips2001 and Phillip Lechenauer authored Feb 22, 2024
1 parent 7db02cf commit b628f8e
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions packages/admin/admin-icons/generate-icons.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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();
Expand All @@ -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 <path> 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) => {
Expand All @@ -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";
Expand All @@ -96,7 +101,7 @@ const writeComponent = async (icon: Icon, pathData: string) => {
export const ${icon.componentName} = React.forwardRef<SVGSVGElement, SvgIconProps>((props, ref) => {
return (
<SvgIcon {...props} ref={ref} viewBox="0 0 16 16">
<path d="${pathData}" />
${svgString}
</SvgIcon>
);
});
Expand Down

0 comments on commit b628f8e

Please sign in to comment.