diff --git a/bin/config.ts b/bin/config.ts index f41a5e0..6a413e4 100644 --- a/bin/config.ts +++ b/bin/config.ts @@ -1,4 +1,12 @@ -export const iconPackages = [ +type IconPackage = { + id: string; + variant?: string; + iconsDir: string; + getVariantFromIconName?: (iconName: string) => string; + normaliseAttributes?: (svg: string) => string; +}; + +export const iconPackages: IconPackage[] = [ { id: "lucide", variant: "regular", @@ -50,4 +58,11 @@ export const iconPackages = [ variant: "regular", iconsDir: "../node_modules/feather-icons/dist/icons", }, + ...["free", "flag"].map((variant) => ({ + id: `core-ui`, + variant, + iconsDir: `../node_modules/@coreui/icons/svg/${variant}`, + normaliseAttributes: (svg: string) => + svg.replace(/fill="var\(--ci-primary-color, currentColor\)"/g, ""), + })), ]; diff --git a/bin/generateIconSets.ts b/bin/generateIconSets.ts index 0840084..f465a44 100644 --- a/bin/generateIconSets.ts +++ b/bin/generateIconSets.ts @@ -14,6 +14,7 @@ iconPackages.forEach( iconsDir, variant, getVariantFromIconName, + normaliseAttributes, }: (typeof iconPackages)[number]) => { const files = getFilesByExtension(iconsDir, ".svg"); @@ -21,8 +22,9 @@ iconPackages.forEach( for (const file of files) { const svg = readFile(iconsDir, file); - const attributes = svg.match(/]*)>/)?.[1]; - const elements = svg.match(/]*>([\s\S]*)<\/svg>/)?.[1]; + const svgNormalised = normaliseAttributes?.(svg) || svg; + const attributes = svgNormalised.match(/]*)>/)?.[1]; + const elements = svgNormalised.match(/]*>([\s\S]*)<\/svg>/)?.[1]; if (!attributes || !elements) { throw new Error(`Failed to parse the SVG: ${file}`); diff --git a/package-lock.json b/package-lock.json index 3b0d738..93e95b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "all-icons-plugin", "version": "0.0.0", "dependencies": { + "@coreui/icons": "^3.0.1", "@material-design-icons/svg": "^0.14.13", "@penpot/plugin-styles": "^0.10.0", "@phosphor-icons/core": "^2.1.1", @@ -41,6 +42,12 @@ "vite": "^5.4.8" } }, + "node_modules/@coreui/icons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@coreui/icons/-/icons-3.0.1.tgz", + "integrity": "sha512-u9UKEcRMyY9pa4jUoLij8pAR03g5g6TLWV33/Mx2ix8sffyi0eO4fLV8DSTQljDCw938zt7KYog5cVKEAJUxxg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", diff --git a/package.json b/package.json index 810cb8e..55a2dff 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "generate-data": "tsx ./bin/generateIconSets.ts" }, "dependencies": { + "@coreui/icons": "^3.0.1", "@material-design-icons/svg": "^0.14.13", "@penpot/plugin-styles": "^0.10.0", "@phosphor-icons/core": "^2.1.1", diff --git a/src/App.tsx b/src/App.tsx index 03732a6..0eadf74 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,8 +10,8 @@ import { iconLibraries, defaultIconSetSettings, getIconSetsByVariant, - DEFAULT_ICON_SIZE, DATA_KEY_ICON_SETS_SETTINGS, + getNormalisedIconSize, } from "./icons"; import Select from "./Select"; import LinkTag from "./LinkTag"; @@ -19,6 +19,7 @@ import { toSortedBy } from "./sort"; import { Bug, ChevronDown, ChevronRight, Lightbulb } from "lucide-react"; import { sendMessage } from "./window"; import { filterByPhrase } from "./search"; +import { parseAttributes } from "./dataStructure"; function App() { const url = new URL(window.location.href); @@ -112,19 +113,23 @@ function App() { svg: { attributes, elements }, }, ]) => { + const parsedAttributes = + parseAttributes(`${attributes} ${customSvgAttributes}`) || {}; + const svg = `${elements}`; const icon = ( - + + ); + const size = getNormalisedIconSize( + parseInt(parsedAttributes.width, 10), + parseInt(parsedAttributes.height, 10), ); return ( handleIconButtonClick(name, svg)} + onClick={() => handleIconButtonClick(name, svg, size)} onMouseEnter={() => setHoveredIcon({ name, library })} onMouseLeave={() => setHoveredIcon(null)} > @@ -135,8 +140,12 @@ function App() { ); } - function handleIconButtonClick(name: string, svg: string) { - sendMessage("insert-icon", { name, svg, size: DEFAULT_ICON_SIZE }); + function handleIconButtonClick( + name: string, + svg: string, + size: { width: number; height: number }, + ) { + sendMessage("insert-icon", { name, svg, size }); } function toggleShowIcons(id: string) { diff --git a/src/Icon.css b/src/Icon.css new file mode 100644 index 0000000..1f45759 --- /dev/null +++ b/src/Icon.css @@ -0,0 +1,3 @@ +svg { + height: auto; +} diff --git a/src/Icon.tsx b/src/Icon.tsx index c495399..3237d68 100644 --- a/src/Icon.tsx +++ b/src/Icon.tsx @@ -1,12 +1,12 @@ -import { parseAttributes } from "./dataStructure"; +import "./Icon.css"; type IconProps = { - attributes: string; + attributes: Record; elements: string; }; export default function Icon({ attributes, elements }: IconProps) { - const { class: className, ...rest } = parseAttributes(attributes) || {}; + const { class: className, ...rest } = attributes || {}; return ( = @@ -207,3 +223,15 @@ export function getVariantOptions(icons: IconSetVariant[]) { value: variant, })); } + +export function getNormalisedIconSize( + originalWidth: number, + originalHeight: number, +) { + const ratio = + originalWidth && originalHeight ? originalWidth / originalHeight : 1; + const width = DEFAULT_ICON_SIZE; + const height = Math.round(width / ratio); + + return { width, height }; +} diff --git a/src/plugin.ts b/src/plugin.ts index 7e8d198..e06acb0 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -22,10 +22,12 @@ type InsertIconPluginEvent = { content: { name: string; svg: string; - size: number; + size: IconSize; }; }; +type IconSize = { width: number; height: number }; + type SetDataPluginEvent = { type: "set-plugin-data"; content: PluginData; @@ -71,18 +73,18 @@ penpot.ui.onMessage(({ type, content }) => { function insertIcon({ name, svg, - size, + size: { width, height }, }: { name: string; svg: string; - size: number; + size: IconSize; }) { const icon = penpot.createShapeFromSvg(svg); if (icon) { icon.name = name; icon.x = penpot.viewport.center.x; icon.y = penpot.viewport.center.y; - icon.resize(size, size); + icon.resize(width, height); } } diff --git a/tests/icon.spec.ts b/tests/icon.spec.ts index 2a10d31..6beb770 100644 --- a/tests/icon.spec.ts +++ b/tests/icon.spec.ts @@ -5,12 +5,18 @@ const testIcons = [ { name: "a-arrow-down", svg: ' ', - size: 24, + size: { + width: 24, + height: 24, + }, }, { name: "pickaxe", svg: ' ', - size: 24, + size: { + width: 24, + height: 24, + }, }, ];