vite-svg-sprite-wrapper
Version:
Creating one sprite file on the fly
228 lines (226 loc) • 7.67 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
default: () => src_default,
defaultOptions: () => defaultOptions,
resolveOptions: () => resolveOptions
});
module.exports = __toCommonJS(src_exports);
var import_node_fs = require("fs");
var import_node_path = require("path");
var import_node_process = require("process");
var import_fast_glob = __toESM(require("fast-glob"), 1);
var import_picocolors = __toESM(require("picocolors"), 1);
var import_picomatch = __toESM(require("picomatch"), 1);
var import_svg_sprite = __toESM(require("svg-sprite"), 1);
var import_vite = require("vite");
var defaultOptions = {
icons: "src/assets/images/svg/*.svg",
outputDir: "src/public/images",
sprite: {},
generateType: false,
typeName: "SvgIcons",
typeFileName: "svg-icons",
typeOutputDir: ""
};
function resolveOptions(options) {
return Object.assign({}, defaultOptions, options);
}
var root = (0, import_node_process.cwd)();
var isSvg = /\.svg$/;
function normalizePaths(root2, path) {
return (Array.isArray(path) ? path : [path]).map((path2) => (0, import_node_path.resolve)(root2, path2)).map(import_vite.normalizePath);
}
function generateConfig(outputDir, options) {
return {
dest: (0, import_vite.normalizePath)((0, import_node_path.resolve)(root, outputDir)),
mode: {
symbol: {
sprite: "../sprite.svg"
}
},
svg: {
xmlDeclaration: false
},
shape: {
transform: [
{
svgo: {
// @ts-expect-error [need to fix type for plugins property]
plugins: [
{ name: "preset-default" },
{
name: "removeAttrs",
params: {
attrs: ["*:(data-*|style|fill):*"]
}
},
{
name: "addAttributesToSVGElement",
params: {
attributes: [
{ fill: "currentColor" }
]
}
},
"removeXMLNS"
]
}
}
]
},
...options.sprite
};
}
async function generateSvgSprite(options) {
const {
icons,
outputDir,
generateType,
typeName,
typeFileName
} = options;
const spriter = new import_svg_sprite.default(generateConfig(outputDir, options));
const rootDir = icons.replace(/(\/(\*+))+\.(.+)/g, "");
const entries = await (0, import_fast_glob.default)([icons]);
for (const entry of entries) {
if (isSvg.test(entry)) {
const relativePath = entry.replace(`${rootDir}/`, "");
spriter.add(
entry,
relativePath,
(0, import_node_fs.readFileSync)(entry, { encoding: "utf-8" })
);
}
}
const { result, data } = await spriter.compileAsync();
if (generateType) {
const shapeIds = data.symbol.shapes.map(({ base }) => {
return `'${base}'`;
});
const fileComment = "/* this file was generated by vite-svg-sprite-wrapper */\n";
const fileContent = `export type ${typeName} = ${shapeIds.join(" | ")}
`;
const typeOutputDir = options.typeOutputDir || (0, import_node_path.dirname)(icons);
if (!(0, import_node_fs.existsSync)(typeOutputDir))
(0, import_node_fs.mkdirSync)(typeOutputDir, { recursive: true });
(0, import_node_fs.writeFileSync)(
(0, import_vite.normalizePath)(`${(0, import_node_path.resolve)(root, typeOutputDir)}/${typeFileName}.d.ts`),
fileComment + fileContent
);
}
if (!(0, import_node_fs.existsSync)(outputDir))
(0, import_node_fs.mkdirSync)(outputDir, { recursive: true });
const sprite = result.symbol.sprite;
(0, import_node_fs.writeFileSync)(
sprite.path,
sprite.contents.toString()
);
return sprite.path.replace(root, "");
}
function ViteSvgSpriteWrapper(options = {}) {
const resolved = resolveOptions(options);
const { icons } = resolved;
let timer;
let config;
function clear() {
clearTimeout(timer);
}
function schedule(fn) {
clear();
timer = setTimeout(fn, 200);
}
const formatConsole = (msg) => `${import_picocolors.default.cyan("[vite-plugin-svg-sprite]")} ${msg}`;
const successGeneration = (res) => {
config.logger.info(formatConsole(`Sprite generated ${import_picocolors.default.green(res)}`));
};
const failGeneration = (err) => {
config.logger.info(formatConsole(`${import_picocolors.default.red("Sprite error")} ${import_picocolors.default.dim(err)}`));
};
return [
{
name: "vite-plugin-svg-sprite:build",
apply: "build",
configResolved(_config) {
config = _config;
},
enforce: "pre",
async buildStart() {
await generateSvgSprite(resolved).then((path) => {
const name = (0, import_node_path.basename)(path);
const source = (0, import_node_fs.readFileSync)(`${root}${path}`);
this.emitFile({
name,
source,
type: "asset"
});
successGeneration(path);
}).catch(failGeneration);
}
},
{
name: "vite-plugin-svg-sprite:serve",
apply: "serve",
configResolved(_config) {
config = _config;
},
enforce: "pre",
async buildStart() {
await generateSvgSprite(resolved).then(successGeneration).catch(failGeneration);
},
config: () => ({ server: { watch: { disableGlobbing: false } } }),
configureServer({ watcher, hot }) {
const iconsPath = normalizePaths(root, icons);
const shouldReload = (0, import_picomatch.default)(iconsPath);
const checkReload = (path) => {
if (shouldReload(path)) {
schedule(() => {
generateSvgSprite(resolved).then((res) => {
hot.send({ type: "full-reload", path: "*" });
successGeneration(res);
}).catch(failGeneration);
});
}
};
watcher.add(iconsPath);
watcher.on("add", checkReload);
watcher.on("change", checkReload);
watcher.on("unlink", checkReload);
}
}
];
}
var src_default = ViteSvgSpriteWrapper;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defaultOptions,
resolveOptions
});