vite-plugin-mdicon2svg
Version:
Vite plugin to transform md-icon to svgs
92 lines • 3.36 kB
JavaScript
import fastGlob from 'fast-glob';
import { existsSync } from 'node:fs';
import { writeFile, readFile, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import { CodePointsMap } from 'mwc3-back-helpers';
export const MD_ICON_REGEX = /(<md-icon[^>]*?>)\s*([0-9a-z_]+)\s*(<\/md-icon\s*>)/g;
const CACHE_DIR = '.mdicon2svg';
export let cache;
export async function readdir(glob) {
return await fastGlob(glob, { dot: true });
}
export async function loadCache() {
const cachePath = join(CACHE_DIR, 'cache.json');
if (!existsSync(cachePath)) {
return undefined;
}
return JSON.parse((await readFile(cachePath)).toString());
}
export async function saveCache(cache) {
if (!existsSync(CACHE_DIR)) {
await mkdir(CACHE_DIR, { recursive: true });
}
await writeFile(join(CACHE_DIR, 'cache.json'), JSON.stringify(cache));
}
export function setCache(newCache) {
cache = newCache;
}
export function stripCommentsFromContent(content) {
const pattern = /(?<!:)\/\/.*|\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->/g;
return content.replace(pattern, '');
}
/**
* This function returns a *distinct* list.
*/
export function findIconsInContent(content, includeComments = false) {
let icons = [];
if (!includeComments) {
content = stripCommentsFromContent(content);
}
const matches = content.matchAll(MD_ICON_REGEX);
for (const match of matches) {
const name = match[2];
// Not a valid icon name, passing
if (!(name in CodePointsMap)) {
continue;
}
const fill = match[1].toLowerCase().includes('fill');
if (icons.findIndex((i) => i.name == name && i.fill == fill) >= 0) {
continue;
}
icons.push({ name, fill });
}
return icons;
}
export async function findIconsInFiles(glob, includeComments = false) {
const files = await readdir(glob);
let icons = [];
const result = await Promise.all(files.map((filepath) => new Promise(async (resolve, _reject) => {
const content = (await readFile(filepath)).toString();
resolve(findIconsInContent(content, includeComments));
})));
return unifyIconData(result.flat());
}
function unifyIconData(iconData) {
const data = [];
for (const icon of iconData) {
if (data.some((i) => i.name == icon.name && i.fill == icon.fill)) {
continue;
}
data.push(icon);
}
return data;
}
export function dataIsEqual(data1, data2) {
return (data1.length == data2.length &&
data1.every((icon) => data2.findIndex((i) => icon.name === i.name && icon.fill === i.fill) >=
0));
}
function generateSvgFetchUrl(iconName, variant, fill = false) {
return `https://fonts.gstatic.com/s/i/short-term/release/materialsymbols${variant}/${iconName}${fill ? '/fill1' : '/default'}/24px.svg`;
}
export async function fetchSvg(iconName, variant, fill = false) {
const res = await fetch(generateSvgFetchUrl(iconName, variant, fill));
return await res.text();
}
export function nameToConstant(iconName, fill = false) {
return iconName.toUpperCase() + (fill ? '_FILL' : '');
}
export function getCachedSvg(iconName, variant, fill = false) {
return cache[variant]?.find((icon) => icon.name === iconName && icon.fill === fill)?.svg;
}
//# sourceMappingURL=utils.js.map