From 0aafe28f85c6523a7c30ed0cabe6b7f79187d60e Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Thu, 26 Oct 2023 18:59:24 +0100 Subject: [PATCH] generate react icon components --- scripts/create-icons/index.ts | 31 +++++++++++++++++-- scripts/create-icons/svg.ts | 38 ------------------------ scripts/create-icons/toAstroComponent.ts | 37 +++++++++++++++++++++++ scripts/create-icons/toReactComponent.ts | 35 ++++++++++++++++++++++ 4 files changed, 100 insertions(+), 41 deletions(-) create mode 100644 scripts/create-icons/toAstroComponent.ts create mode 100644 scripts/create-icons/toReactComponent.ts diff --git a/scripts/create-icons/index.ts b/scripts/create-icons/index.ts index 0d1724fd..ec824c0b 100644 --- a/scripts/create-icons/index.ts +++ b/scripts/create-icons/index.ts @@ -6,7 +6,9 @@ import fs from 'node:fs/promises' import ps from 'node:path/posix' import ora from 'ora' import chalk from 'chalk' -import { toAstroComponent, toInnerSvg } from './svg.ts' +import { toInnerSvg } from './svg.ts' +import { toAstroComponent } from './toAstroComponent.ts' +import { toReactComponent } from './toReactComponent.ts' // Current directory. const currentDir = ps.resolve('.') @@ -31,15 +33,21 @@ export async function generateIcons(distDir: string) { // clean the distribution directory await fs.rm(distDir, { force: true, recursive: true }) await fs.mkdir(distDir, { recursive: true }) + await fs.mkdir(`${distDir}/react`, { recursive: true }) // copy the attribute typings file await fs.copyFile( ps.resolve(currentDir, 'scripts/create-icons/Props.d.ts'), ps.resolve(distDir, 'Props.d.ts') ) + await fs.copyFile( + ps.resolve(currentDir, 'scripts/create-icons/Props.d.ts'), + ps.resolve(`${distDir}/react`, 'Props.d.ts') + ) - // convert the SVG files into Astro components + // convert the SVG files into Astro & React components let contentOfIndexJS = '// @ts-nocheck\n' + let contentOfIndexReactJS = '// @ts-nocheck\n' for (const src of srcDirs) { for (let filepath of await fs.readdir(src, { encoding: 'utf8' })) { @@ -83,16 +91,33 @@ export async function generateIcons(distDir: string) { 'utf8' ) + // write the react component to a file + await fs.writeFile( + ps.resolve(`${distDir}/react`, `${baseName}.tsx`), + toReactComponent(innerSVG, title), + 'utf8' + ) + // add the astro component export to the main entry `index.ts` file contentOfIndexJS += `\nexport { default as ${baseName} } from './${baseName}.astro'` + // add the react component export to the main entry `react/index.ts` file + contentOfIndexReactJS += `\nexport { Icon as ${baseName} } from './${baseName}.tsx'` + icons.push({ name, baseName, title }) } } - // write the main entry `index.ts` file + // write the main Astro entry `index.ts` file await fs.writeFile(ps.resolve(distDir, 'index.ts'), contentOfIndexJS, 'utf8') + // write the main React entry `react/index.ts` file + await fs.writeFile( + ps.resolve(`${distDir}/react`, 'index.ts'), + contentOfIndexReactJS, + 'utf8' + ) + spinner.succeed( `${chalk.bold('[create-icons]')} Generated ${ icons.length diff --git a/scripts/create-icons/svg.ts b/scripts/create-icons/svg.ts index 77a718e9..141f2318 100644 --- a/scripts/create-icons/svg.ts +++ b/scripts/create-icons/svg.ts @@ -1,43 +1,5 @@ import { optimize as optimizeSVGNative } from 'svgo' -export const toAstroComponent = (innerSVG: string, title: string) => `--- -import type { Props } from './Props.ts'; -export type { Props }; - -let { - size = '24px', - title, - width = size, - height = size, - ...props -}: Props = { - 'fill': 'none', - 'title': '${title}', - 'viewBox': '0 0 24 24', - ...Astro.props -} - -const toAttributeSize = (size: number | string) => - String(size).replace(/(?<=[0-9])x$/, 'em') - -size = toAttributeSize(size) -width = toAttributeSize(width) -height = toAttributeSize(height) ---- - -{title ? ({title}) : ''}${innerSVG}` - export const toInnerSvg = (input: string) => optimizeSVGNative(input, { plugins: [ diff --git a/scripts/create-icons/toAstroComponent.ts b/scripts/create-icons/toAstroComponent.ts new file mode 100644 index 00000000..ad449644 --- /dev/null +++ b/scripts/create-icons/toAstroComponent.ts @@ -0,0 +1,37 @@ +export const toAstroComponent = (innerSVG: string, title: string) => `--- +import type { Props } from './Props.d.ts'; +export type { Props }; + +let { + size = '24px', + title, + width = size, + height = size, + ...props +}: Props = { + 'fill': 'none', + 'title': '${title}', + 'viewBox': '0 0 24 24', + ...Astro.props +} + +const toAttributeSize = (size: number | string) => + String(size).replace(/(?<=[0-9])x$/, 'em') + +size = toAttributeSize(size) +width = toAttributeSize(width) +height = toAttributeSize(height) +--- + +{title ? ({title}) : ''}${innerSVG}` diff --git a/scripts/create-icons/toReactComponent.ts b/scripts/create-icons/toReactComponent.ts new file mode 100644 index 00000000..b1244c55 --- /dev/null +++ b/scripts/create-icons/toReactComponent.ts @@ -0,0 +1,35 @@ +export const toReactComponent = (innerSVG: string, title: string) => ` +import type { Props } from './Props.d.ts'; + +export function Icon(props: Props) { + let { + size = '24px', + title, + width = size, + height = size + }: Props = { + 'title': '${title}', + ...props + } + + const toAttributeSize = (size: number | string) => + String(size).replace(/(?<=[0-9])x$/, 'em') + + size = toAttributeSize(size) + width = toAttributeSize(width) + height = toAttributeSize(height) + + const style = { + 'width': '1em', + 'height': '1em', + 'stroke': 'currentcolor', + 'strokeWidth': 'var(--border-width)', + 'strokeLinecap': 'round', + 'strokeLinejoin': 'round', + 'fill': 'none', + 'verticalAlign': 'baseline' + } + + return {title ? ({title}) : ''}${innerSVG} +} +`