@stephansama/vite-iconify-svgmap
Version:
Vite plugin for generating iconify svg sprite maps in memory
81 lines (80 loc) • 3.04 kB
JavaScript
import { a as getState, i as NAME_REGEX, n as iconifySvgmap, o as name, r as writeSprites } from "../src-CsllISxW.mjs";
import fs from "node:fs";
import path from "node:path";
//#region src/svelte.ts
const EMPTY_SPRITE = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none"></svg>`;
const JSON_EXTENSION_REGEX = /\.json$/;
/**
* Vite plugins for sveltekit. add after `sveltekit()`:
*
* ```js
* plugins: [sveltekit(), iconifySvgmap()];
* ```
*
* Sveltekit prerenders in a worker thread during its server build's
* `writeBundle` and runs the adapter in `closeBundle`:
*
* - When the client build is written, an empty placeholder sprite is added for
* every installed icon pack so the prerender crawler does not fail on `<use
* href>` links to sprites that do not exist yet
* - After prerendering the real sprites replace the placeholders (unused ones are
* removed), before the adapter copies the client output
*/
function iconifySvgmapSvelteKit(options = {}) {
const state = getState();
return [iconifySvgmap(options), {
apply: "build",
name: `${name}:sveltekit`,
writeBundle: {
async handler(outputOptions) {
if (!outputOptions.dir) return;
if (!Boolean(this.environment?.config.build.ssr)) {
await writePlaceholders(outputOptions.dir);
return;
}
const clientDirectory = path.resolve(outputOptions.dir, "..", "client");
const written = new Set(await writeSprites(clientDirectory));
for (const placeholder of state.placeholders) if (!written.has(placeholder)) await fs.promises.rm(placeholder, { force: true });
state.placeholders.clear();
if (written.size > 0) this.info(`wrote ${written.size} svg sprite(s)`);
},
order: "post",
sequential: true
}
}];
async function writePlaceholders(clientDirectory) {
const spriteDirectory = path.join(clientDirectory, state.spriteDir);
await fs.promises.mkdir(spriteDirectory, { recursive: true });
for (const pack of listInstalledPacks(state.root)) {
const filename = path.join(spriteDirectory, `${pack}.svg`);
if (fs.existsSync(filename)) continue;
await fs.promises.writeFile(filename, EMPTY_SPRITE);
state.placeholders.add(filename);
}
}
}
/** Icon packs resolvable from `root`, following node's module resolution */
function listInstalledPacks(root) {
const packs = /* @__PURE__ */ new Set();
let directory = path.resolve(root);
while (true) {
const modules = path.join(directory, "node_modules");
for (const pack of readDirectory(path.join(modules, "@iconify-json"))) if (NAME_REGEX.test(pack)) packs.add(pack);
for (const file of readDirectory(path.join(modules, "@iconify", "json", "json"))) {
const pack = file.replace(JSON_EXTENSION_REGEX, "");
if (NAME_REGEX.test(pack)) packs.add(pack);
}
const parent = path.dirname(directory);
if (parent === directory) return packs;
directory = parent;
}
}
function readDirectory(directory) {
try {
return fs.readdirSync(directory);
} catch {
return [];
}
}
//#endregion
export { iconifySvgmapSvelteKit as default };