import glob from "fast-glob"; import path from "path"; import fs from "fs/promises"; import svgson from "svgson"; import { mkdir_to } from "../lib/builderator.js"; export const description = "Builds the sprite.svg sheet for icons based on the files in static/icons and what you use." export const options = [ ["--all-icons ", "glob pattern with all .svg icons", "./static/icons/*.svg"], ["--sprite-sheet ", "output sprite sheet with all icons", "./public/icon-sprites.svg"], ["--icons-index ", "index.json file, be sure you know what you're doing", "./public/icons/index.json"], ["--prod-list ", "JSON array file listing the icons to include for production"] ]; const load_svgs = async (svg_files) => { const results = []; // why use a for loop? because map don't async for(let fname of svg_files) { const name = path.basename(fname, ".svg"); const contents = (await fs.readFile(fname)).toString(); const parsed = await svgson.parse(contents); results.push({name, contents, parsed }); } return results; } const symbolize = (svgs) => { const symbols = svgs.map(({name, parsed }) => { return { name: 'symbol', type: 'element', attributes: { id: name, viewBox: '0 0 24 24' }, children: parsed.children, } }); return symbols; } const sprite_sheet = async (symbols) => { const svg_doc = { name: 'svg', type: 'element', attributes: { xmlns: 'http://www.w3.org/2000/svg', version: '1.1', }, children: [ { name: 'defs', type: 'element', children: symbols, }, ], } const xml_meta = `\n`; const svg_xml = await svgson.stringify(svg_doc); return [xml_meta, svg_xml].join(""); } export const main = async (opts) => { // list the svg files let svg_files; if(opts.prodList) { svg_files = JSON.parse(await fs.readFile(opts.prodList)); } else { svg_files = glob.sync(opts.allIcons); } // load all of the icons from their svgs const svg_contents = await load_svgs(svg_files); // convert to linkable symbols const symbols = symbolize(svg_contents); // craft the svg doc const svg_doc = await sprite_sheet(symbols); // write out the sprite sheet await fs.writeFile(opts.spriteSheet, svg_doc); mkdir_to(opts.iconsIndex); // write out the json sprite list const sprite_list = svg_contents.map(({name}) => name); await fs.writeFile(opts.iconsIndex, JSON.stringify(sprite_list)); if(!opts.dontExit) { process.exit(0); } }