mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-02 03:19:31 +08:00
119 lines
3.7 KiB
Text
119 lines
3.7 KiB
Text
import { warnOnce } from '@unocss/core';
|
|
|
|
function encodeSvgForCss(svg) {
|
|
let useSvg = svg.startsWith("<svg>") ? svg.replace("<svg>", "<svg >") : svg;
|
|
if (!useSvg.includes(" xmlns:xlink=") && useSvg.includes(" xlink:")) {
|
|
useSvg = useSvg.replace("<svg ", '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ');
|
|
}
|
|
if (!useSvg.includes(" xmlns=")) {
|
|
useSvg = useSvg.replace("<svg ", '<svg xmlns="http://www.w3.org/2000/svg" ');
|
|
}
|
|
return useSvg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/{/g, "%7B").replace(/}/g, "%7D").replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
}
|
|
|
|
const COLLECTION_NAME_PARTS_MAX = 3;
|
|
function createPresetIcons(lookupIconLoader) {
|
|
return function presetIcons(options = {}) {
|
|
const {
|
|
scale = 1,
|
|
mode = "auto",
|
|
prefix = "i-",
|
|
warn = false,
|
|
collections: customCollections,
|
|
extraProperties = {},
|
|
customizations = {},
|
|
autoInstall = false,
|
|
layer = "icons",
|
|
unit
|
|
} = options;
|
|
const loaderOptions = {
|
|
addXmlNs: true,
|
|
scale,
|
|
customCollections,
|
|
autoInstall,
|
|
warn: void 0,
|
|
customizations: {
|
|
...customizations,
|
|
additionalProps: { ...extraProperties },
|
|
trimCustomSvg: true,
|
|
async iconCustomizer(collection, icon, props) {
|
|
await customizations.iconCustomizer?.(collection, icon, props);
|
|
if (unit) {
|
|
if (!props.width)
|
|
props.width = `${scale}${unit}`;
|
|
if (!props.height)
|
|
props.height = `${scale}${unit}`;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
let iconLoader;
|
|
return {
|
|
name: "@unocss/preset-icons",
|
|
enforce: "pre",
|
|
options,
|
|
layers: { icons: -30 },
|
|
rules: [[
|
|
/^([a-z0-9:-]+)(?:\?(mask|bg|auto))?$/,
|
|
async ([full, body, _mode = mode]) => {
|
|
let collection = "";
|
|
let name = "";
|
|
let svg;
|
|
iconLoader = iconLoader || await lookupIconLoader(options);
|
|
const usedProps = {};
|
|
if (body.includes(":")) {
|
|
[collection, name] = body.split(":");
|
|
svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
|
|
} else {
|
|
const parts = body.split(/-/g);
|
|
for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
|
|
collection = parts.slice(0, i).join("-");
|
|
name = parts.slice(i).join("-");
|
|
svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
|
|
if (svg)
|
|
break;
|
|
}
|
|
}
|
|
if (!svg) {
|
|
if (warn)
|
|
warnOnce(`failed to load icon "${full}"`);
|
|
return;
|
|
}
|
|
const url = `url("data:image/svg+xml;utf8,${encodeSvgForCss(svg)}")`;
|
|
if (_mode === "auto")
|
|
_mode = svg.includes("currentColor") ? "mask" : "bg";
|
|
if (_mode === "mask") {
|
|
return {
|
|
"--un-icon": url,
|
|
"mask": "var(--un-icon) no-repeat",
|
|
"mask-size": "100% 100%",
|
|
"-webkit-mask": "var(--un-icon) no-repeat",
|
|
"-webkit-mask-size": "100% 100%",
|
|
"background-color": "currentColor",
|
|
...usedProps
|
|
};
|
|
} else {
|
|
return {
|
|
"background": `${url} no-repeat`,
|
|
"background-size": "100% 100%",
|
|
"background-color": "transparent",
|
|
...usedProps
|
|
};
|
|
}
|
|
},
|
|
{ layer, prefix }
|
|
]]
|
|
};
|
|
};
|
|
}
|
|
function combineLoaders(loaders) {
|
|
return (...args) => {
|
|
for (const loader of loaders) {
|
|
const result = loader(...args);
|
|
if (result)
|
|
return result;
|
|
}
|
|
};
|
|
}
|
|
|
|
export { combineLoaders, createPresetIcons };
|