vite-plugin-mdicon2svg
Version:
Vite plugin to transform md-icon to svgs
139 lines • 6.34 kB
JavaScript
import virtual from '@rollup/plugin-virtual';
import { createFilter } from '@rollup/pluginutils';
import { Variant } from 'mwc3-back-helpers';
import { log, setDebug } from './logger.js';
import { removeSymbolsLink } from './transformation.js';
import { MD_ICON_REGEX, cache, dataIsEqual, fetchSvg, findIconsInContent, findIconsInFiles, getCachedSvg, loadCache, nameToConstant, saveCache, setCache, stripCommentsFromContent, } from './utils.js';
export async function mdicon2svg(options = {}) {
// Defaults
options.include ??= 'src/**/*.{js,ts,jsx,tsx}';
options.variant ??= Variant.OUTLINED;
options.devMode ??= false;
options.includeComments ??= false;
options.debug ??= false;
setDebug(options.debug);
const filter = createFilter(options.include, options.exclude);
setCache((await loadCache()) ?? {
// No cache yet default
variant: options.variant,
});
// Will hold the content of current module version.
const icons = {};
let virtualVersion = 1;
let config;
let command;
let lastFoundIcons = [];
async function updateVersion(data) {
// Here we should download missing svgs from the cache
cache[options.variant] ??= [];
const missingSvgs = data.filter((icon) => {
return !(cache[options.variant].findIndex((i) => i.name == icon.name && i.fill == icon.fill && i.svg) >= 0);
});
await Promise.all(missingSvgs.map((missing) => new Promise(async (resolve, _reject) => {
log('=== DOWNLOADING MISSING SVG');
missing.svg = await fetchSvg(missing.name, options.variant, missing.fill);
// Push the data if the icon is not already in the cache
if (cache[options.variant].findIndex((i) => missing.name == i.name && missing.fill == i.fill) === -1) {
cache[options.variant].push(missing);
}
resolve(null);
})));
await saveCache(cache);
// We update the virtual module version
virtualVersion++;
lastFoundIcons = data;
}
return [
{
name: 'mdicon2svg-leader',
configResolved(resolvedConfig) {
config = resolvedConfig;
command = config.command;
},
async buildStart() {
if (command === undefined || command == 'build') {
log('=== BUILDSTART HOOK');
const icons = await findIconsInFiles(options.include, options.includeComments);
if (!dataIsEqual(icons, lastFoundIcons)) {
await updateVersion(icons);
}
// Fill in the svgs for easy access in subroutines
for (const icon of icons) {
icon.svg = getCachedSvg(icon.name, options.variant, icon.fill);
}
}
},
async transformIndexHtml(html) {
// Run only in dev mode
if (command === undefined || (command == 'serve' && options.devMode)) {
log('=== TRANSFORMINDEXHTML HOOK');
const icons = await findIconsInFiles(options.include, options.includeComments);
if (!dataIsEqual(icons, lastFoundIcons)) {
await updateVersion(icons);
}
// Fill in the svgs for easy access in subroutines
for (const icon of icons) {
icon.svg = getCachedSvg(icon.name, options.variant, icon.fill);
}
}
else if (command == 'build') {
return removeSymbolsLink(html);
}
},
transform(code, id) {
if ((command === undefined || command == 'build' || options.devMode) &&
filter(id)) {
if (!options.includeComments) {
code = stripCommentsFromContent(code);
}
const icons = findIconsInContent(code);
code = code.replace(MD_ICON_REGEX, (_, opening, icon, closing) => {
return (opening +
'${' +
nameToConstant(icon, opening.toLowerCase().includes('fill')) +
'}' +
closing);
});
if (icons.length > 0) {
log('=== TRANSFORM HOOK');
// Here we should check if virtual module needs a
// refresh. Question to ask is does the virtual module
// contains all the icons found in the last check?
return (`import {${icons.map((icon) => nameToConstant(icon.name, icon.fill))}} from 'virtual:icons${virtualVersion}';` +
'\n' +
code);
}
}
},
},
{
name: 'resolve-icons-module',
async resolveId(id) {
log('=== RESOLVEID HOOK');
if (command == 'serve' && !options.devMode) {
return;
}
if (id.startsWith('virtual:icons')) {
const index = id.replace(/[a-zA-Z:]/g, '');
if (!icons[`icons${index}`]) {
icons[`icons${index}`] =
`import {html} from 'lit-html';` +
'\n' +
lastFoundIcons
.map((icon) => `export const ${nameToConstant(icon.name, icon.fill)} = ` +
'html`' +
icon.svg +
'`;')
.join('\n');
// TODO: Should probably flush the previous cached versions
// console.log(icons);
}
return `\0${id}`;
}
},
},
// Virtual module that will hold the icon values
virtual(icons),
];
}
//# sourceMappingURL=index.js.map