Last active
October 24, 2024 13:52
-
-
Save kevinleedrum/5dc78d3b24e5b9ff85c5ebf07cf8b056 to your computer and use it in GitHub Desktop.
vite-plugin-icon-sprite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { promises as fs } from 'fs'; | |
import path from 'path'; | |
/** Monitors /static/icons and builds both a type definition file and a spritesheet from the SVG files **/ | |
export default function IconSpritePlugin() { | |
async function generateIconSprite() { | |
const iconsDir = path.join(process.cwd(), 'static', 'icons'); | |
const files = await fs.readdir(iconsDir); | |
let symbols = ''; | |
let iconNameType = 'export type IconName =\n'; | |
for (const file of files) { | |
if (!file.endsWith('.svg')) continue; | |
let svgContent = await fs.readFile(path.join(iconsDir, file), 'utf8'); | |
// The id is the filename without the extension | |
const id = file.replace('.svg', ''); | |
svgContent = svgContent | |
.replace(/id="[^"]+"/, '') | |
.replace('<svg', `<symbol id="${id}"`) | |
.replace('</svg>', '</symbol>'); | |
symbols += svgContent + '\n'; | |
// Add the id to the IconName type union | |
iconNameType += ` | '${id}'\n`; | |
} | |
const sprite = `<svg width="0" height="0" style="display: none">\n\n${symbols}</svg>`; | |
await fs.writeFile(path.join(process.cwd(), 'static', 'icon-sprite.svg'), sprite); | |
await writeChangesToType(iconNameType); | |
} | |
async function writeChangesToType(iconNameType) { | |
const iconNameTypePath = path.join(process.cwd(), 'src', 'types', 'IconName.ts'); | |
const currentContent = await fs.readFile(iconNameTypePath, 'utf8'); | |
if (currentContent === iconNameType) return; | |
await fs.writeFile(iconNameTypePath, iconNameType); | |
} | |
return { | |
name: 'icon-sprite-plugin', | |
buildStart() { | |
return generateIconSprite(); | |
}, | |
configureServer(server) { | |
server.watcher.add(path.join(process.cwd(), 'static', 'icons', '*.svg')); | |
server.watcher.on('change', async (changedPath) => { | |
if (changedPath.endsWith('.svg')) return generateIconSprite(); | |
}); | |
}, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment