IOweb/node_modules/@iconify/tools/lib/optimise/global-style.mjs
2026-07-03 15:07:38 -05:00

156 lines
4.6 KiB
JavaScript

import { allValidTags, animateTags } from '../svg/data/tags.mjs';
import { parseSVG } from '../svg/parse.mjs';
import { parseSVGStyle } from '../svg/parse-style.mjs';
import '../css/parse.mjs';
import '../css/parser/tokens.mjs';
import '../css/parser/error.mjs';
import '../css/parser/strings.mjs';
import '../css/parser/text.mjs';
import '../css/parser/export.mjs';
import '../css/parser/tree.mjs';
function getClassList(value) {
return value?.split(/\s+/);
}
const tempDataAttrbiute = "data-gstyle-temp";
function cleanupGlobalStyle(svg) {
const backup = svg.toString();
let containsTempAttr = false;
const animatedClasses = /* @__PURE__ */ new Set();
parseSVG(svg, (item) => {
if (!animateTags.has(item.tagName)) {
return;
}
const $element = item.$element;
if ($element.attr("attributeName") !== "class") {
return;
}
["from", "to", "values"].forEach((attr) => {
const value = $element.attr(attr);
if (typeof value !== "string") {
return;
}
value.split(";").forEach((item2) => {
getClassList(item2).forEach((className) => {
animatedClasses.add(className);
});
});
});
});
const removeClasses = /* @__PURE__ */ new Set();
try {
parseSVGStyle(svg, (styleItem) => {
const returnValue = styleItem.value;
if (styleItem.type !== "global") {
return returnValue;
}
const selectorTokens = styleItem.selectorTokens;
for (let i = 0; i < selectorTokens.length; i++) {
const selectorToken = selectorTokens[i];
if (selectorToken.type !== "selector") {
return returnValue;
}
}
const selectors = styleItem.selectors;
const matches = [];
for (let i = 0; i < selectors.length; i++) {
const selector = styleItem.selectors[i];
const firstChar = selector.charAt(0);
let matchType;
if (firstChar === ".") {
matchType = "class";
} else if (firstChar === "#") {
matchType = "id";
} else if (allValidTags.has(selector)) {
matchType = "tag";
} else {
return returnValue;
}
const valueMatch = matchType === "tag" ? selector : selector.slice(1);
if (matchType === "class" && animatedClasses.has(valueMatch)) {
return returnValue;
}
matches.push({
type: matchType,
value: valueMatch
});
}
const isMatch = (tagName, $element) => {
for (let i = 0; i < matches.length; i++) {
const { type, value } = matches[i];
switch (type) {
case "id":
if ($element.attr("id") === value) {
return true;
}
break;
case "tag":
if (tagName === value) {
return true;
}
break;
case "class": {
const className = $element.attr("class");
if (className && getClassList(className).includes(value)) {
return true;
}
}
}
}
return false;
};
parseSVG(svg, (svgItem) => {
const tagName = svgItem.tagName;
const $element = svgItem.$element;
if (!isMatch(tagName, $element)) {
return;
}
const addedAttributes = new Set(
$element.attr(tempDataAttrbiute)?.split(/\s+/)
);
const prop = styleItem.prop;
if ($element.attr(prop) !== void 0) {
if (addedAttributes.has(prop)) {
throw new Error("Duplicate attribute");
}
}
$element.attr(prop, styleItem.value);
addedAttributes.add(prop);
$element.attr(
tempDataAttrbiute,
Array.from(addedAttributes).join(" ")
);
containsTempAttr = true;
});
matches.forEach((match) => {
if (match.type === "class") {
removeClasses.add(match.value);
}
});
});
parseSVG(svg, (svgItem) => {
const $element = svgItem.$element;
const classList = getClassList($element.attr("class"));
if (!classList) {
return;
}
const filtered = classList.filter(
(item) => !removeClasses.has(item)
);
if (!filtered.length) {
$element.removeAttr("class");
} else {
$element.attr("class", filtered.join(" "));
}
});
if (containsTempAttr) {
parseSVG(svg, (item) => {
item.$element.removeAttr(tempDataAttrbiute);
});
}
} catch {
svg.load(backup);
}
}
export { cleanupGlobalStyle };