vite-plugin-svg-sprite
Version:
SVG sprite plugin for Vite
102 lines (97 loc) • 4.27 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_path_1 = __importDefault(require("node:path"));
const node_fs_1 = __importDefault(require("node:fs"));
const node_crypto_1 = __importDefault(require("node:crypto"));
const micromatch_1 = __importDefault(require("micromatch"));
const svgo_1 = require("svgo");
const svg_to_symbol_js_1 = require("./svg-to-symbol.js");
const { stringify } = JSON;
const exportTypes = ['vanilla', 'react', 'vue'];
function getHash(content) {
const h = node_crypto_1.default.createHash('sha256');
h.update(content);
return h.digest('hex');
}
function prepareTemplate(props) {
return (options) => {
var _a;
return `
import addSymbol from 'vite-plugin-svg-sprite/runtime/inject.js';
${(_a = props.adapterImport) !== null && _a !== void 0 ? _a : ''}
const id = ${stringify(options.id)};
const name = ${stringify(options.name)};
const symbolXml = ${stringify(options.symbolXml)};
const { dispose } = addSymbol(symbolXml, id);
export const attributes = ${stringify(options.attributes)}
export default ${props.adapter};
if (import.meta.hot) {
import.meta.hot.dispose(dispose);
import.meta.hot.accept();
}
`;
};
}
function getModuleTemplate(type = {}) {
if (type.exportType === 'custom') {
if (!type.adapter) {
throw new Error('Export type is set to "custom", but adapter is not provided. Please add "adapter" option in config.');
}
return prepareTemplate({ adapter: type.adapter });
}
const { exportType = 'vanilla' } = type;
if (!exportTypes.includes(exportType)) {
throw new Error('Unknown export type, supported types: "custom", "react", "vanilla", "vue".');
}
return prepareTemplate({
adapterImport: `import { adapter } from 'vite-plugin-svg-sprite/runtime/adapters/${exportType}.js';`,
adapter: 'adapter(id, name)'
});
}
exports.default = (options) => {
var _a;
const match = (_a = options === null || options === void 0 ? void 0 : options.include) !== null && _a !== void 0 ? _a : '**.svg';
const svgoOptions = options === null || options === void 0 ? void 0 : options.svgo;
const moduleTemplate = getModuleTemplate(options);
const plugin = {
name: 'svg-sprite',
async transform(src, filepath) {
var _a, _b, _c;
if (!micromatch_1.default.isMatch(filepath, match, {
dot: true,
})) {
return undefined;
}
const code = await node_fs_1.default.promises.readFile(filepath, 'utf-8');
const hash = getHash(code).slice(0, 8);
const { name } = node_path_1.default.parse(filepath);
const optimizedSvg = (0, svgo_1.optimize)(code, {
...svgoOptions,
plugins: [
{
name: 'prefixIds',
params: {
prefix: hash,
},
},
...(_a = svgoOptions === null || svgoOptions === void 0 ? void 0 : svgoOptions.plugins) !== null && _a !== void 0 ? _a : [],
],
}).data;
const symbolId = ((_b = options === null || options === void 0 ? void 0 : options.symbolId) !== null && _b !== void 0 ? _b : 'icon-[name]').replace(/\[hash\]/g, hash).replace(/\[name\]/g, name);
const symbolResults = (0, svg_to_symbol_js_1.svgToSymbol)(optimizedSvg, symbolId);
if (!symbolResults) {
throw new Error(`invalid svg file: ${filepath}`);
}
const { symbolXml, attributes } = symbolResults;
return {
code: moduleTemplate({ id: symbolId, name, symbolXml, attributes }),
moduleSideEffects: (_c = options === null || options === void 0 ? void 0 : options.moduleSideEffects) !== null && _c !== void 0 ? _c : true,
map: { mappings: '' },
};
},
};
return plugin;
};