mirror of
https://github.com/kremalicious/blog.git
synced 2024-11-22 09:56:51 +01:00
generate react icon components
This commit is contained in:
parent
8a2606185b
commit
0aafe28f85
@ -6,7 +6,9 @@ import fs from 'node:fs/promises'
|
|||||||
import ps from 'node:path/posix'
|
import ps from 'node:path/posix'
|
||||||
import ora from 'ora'
|
import ora from 'ora'
|
||||||
import chalk from 'chalk'
|
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.
|
// Current directory.
|
||||||
const currentDir = ps.resolve('.')
|
const currentDir = ps.resolve('.')
|
||||||
@ -31,15 +33,21 @@ export async function generateIcons(distDir: string) {
|
|||||||
// clean the distribution directory
|
// clean the distribution directory
|
||||||
await fs.rm(distDir, { force: true, recursive: true })
|
await fs.rm(distDir, { force: true, recursive: true })
|
||||||
await fs.mkdir(distDir, { recursive: true })
|
await fs.mkdir(distDir, { recursive: true })
|
||||||
|
await fs.mkdir(`${distDir}/react`, { recursive: true })
|
||||||
|
|
||||||
// copy the attribute typings file
|
// copy the attribute typings file
|
||||||
await fs.copyFile(
|
await fs.copyFile(
|
||||||
ps.resolve(currentDir, 'scripts/create-icons/Props.d.ts'),
|
ps.resolve(currentDir, 'scripts/create-icons/Props.d.ts'),
|
||||||
ps.resolve(distDir, '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 contentOfIndexJS = '// @ts-nocheck\n'
|
||||||
|
let contentOfIndexReactJS = '// @ts-nocheck\n'
|
||||||
|
|
||||||
for (const src of srcDirs) {
|
for (const src of srcDirs) {
|
||||||
for (let filepath of await fs.readdir(src, { encoding: 'utf8' })) {
|
for (let filepath of await fs.readdir(src, { encoding: 'utf8' })) {
|
||||||
@ -83,16 +91,33 @@ export async function generateIcons(distDir: string) {
|
|||||||
'utf8'
|
'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
|
// add the astro component export to the main entry `index.ts` file
|
||||||
contentOfIndexJS += `\nexport { default as ${baseName} } from './${baseName}.astro'`
|
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 })
|
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')
|
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(
|
spinner.succeed(
|
||||||
`${chalk.bold('[create-icons]')} Generated ${
|
`${chalk.bold('[create-icons]')} Generated ${
|
||||||
icons.length
|
icons.length
|
||||||
|
@ -1,43 +1,5 @@
|
|||||||
import { optimize as optimizeSVGNative } from 'svgo'
|
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)
|
|
||||||
---
|
|
||||||
<style is:global>
|
|
||||||
.icon {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
stroke: currentcolor;
|
|
||||||
stroke-width: var(--border-width);
|
|
||||||
stroke-linecap: round;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
fill: none;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<svg {width} {height} {...props} class="icon">{title ? (<title>{title}</title>) : ''}${innerSVG}</svg>`
|
|
||||||
|
|
||||||
export const toInnerSvg = (input: string) =>
|
export const toInnerSvg = (input: string) =>
|
||||||
optimizeSVGNative(input, {
|
optimizeSVGNative(input, {
|
||||||
plugins: [
|
plugins: [
|
||||||
|
37
scripts/create-icons/toAstroComponent.ts
Normal file
37
scripts/create-icons/toAstroComponent.ts
Normal file
@ -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)
|
||||||
|
---
|
||||||
|
<style is:global>
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
stroke: currentcolor;
|
||||||
|
stroke-width: var(--border-width);
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
fill: none;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<svg width={width} height={height} {...props} class="icon">{title ? (<title>{title}</title>) : ''}${innerSVG}</svg>`
|
35
scripts/create-icons/toReactComponent.ts
Normal file
35
scripts/create-icons/toReactComponent.ts
Normal file
@ -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 <svg width={width} height={height} fill="none" viewBox="0 0 24 24" {...props} style={style}>{title ? (<title>{title}</title>) : ''}${innerSVG}</svg>
|
||||||
|
}
|
||||||
|
`
|
Loading…
Reference in New Issue
Block a user