const fs = require("fs") const path = require("path") const svgSprite = require("svg-sprite") const { optimize } = require("svgo") const { JSDOM } = require("jsdom") // Generate 's for referencing sprites in css function generateAtlasViews(svgFile, symbolId) { const dom = new JSDOM(svgFile) const document = dom.window.document const svg = document.querySelector("svg") const symbols = document.querySelectorAll("symbol") const width = 24 const height = 24 let row = 0 let col = 0 const totalCols = Math.floor(Math.sqrt(symbols.length)) for (const symbol of symbols) { const x = col * width const y = row * height let id = symbol.getAttribute("id") symbol.removeAttribute("xmlns") if (symbolId) { id = symbolId(id) symbol.setAttribute("id", id) } // Create elements const svgView = document.createElement("view") svgView.setAttribute("id", `${id}-view`) svgView.setAttribute("viewBox", `${x} ${y} ${width} ${height}`) const svgUse = document.createElement("use") svgUse.setAttribute("width", width) svgUse.setAttribute("height", height) //svgUse.setAttribute("viewBox", "0 -960 960 960") svgUse.setAttribute("x", x) svgUse.setAttribute("y", y) svgUse.setAttribute("href", `#${id}`) // Append elements svg.appendChild(svgView) svg.appendChild(svgUse) // Adjust row/col col++ if (col > totalCols) { col = 0 row++ } } const cWidth = (totalCols + 1) * width const cHeight = (row + 1) * height svg.setAttribute("viewBox", `0 0 ${cWidth} ${cHeight}`) svg.setAttribute("width", `${cWidth}px`) svg.setAttribute("height", `${cHeight}px`) const svgStr = svg.outerHTML.replaceAll("viewbox", "viewBox") // JSDOM will lower-case all attributes return optimize(svgStr, { multipass: true, plugins: [{ name: "removeUnknownsAndDefaults", active: false }], // Prevent changing of ids }).data } async function generateAtlasViewsFromReferences(refs, symbolId) { const spriter = new svgSprite({ mode: { symbol: { dest: "", sprite: "icons.svg" } } }) // Add refs to spriter for (const ref of refs) { const name = (ref.name ?? ref.symbol ?? ref.path.replace(".svg", "")) + ".svg" // Supposed to pass a file path, make a fake one spriter.add(name, null, ref.svg) } // Compile and return atlas const { result } = await spriter.compileAsync() return generateAtlasViews(result.symbol.sprite.contents.toString(), symbolId) } function createDirectoriesForFile(filePath) { fs.mkdirSync(path.dirname(filePath), { recursive: true }) } module.exports = { generateAtlasViews, generateAtlasViewsFromReferences, createDirectoriesForFile }