@maizzle/framework
Version:
Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.
155 lines (154 loc) • 5.18 kB
JavaScript
//#region src/plugins/postcss/resolveProps.ts
/** Check if a rule's selector includes :root */
function isRootRule(rule) {
const sel = rule.selector;
return sel === ":root" || sel.includes(":root");
}
/** Check if a rule is inside @layer (not @media or other at-rules) */
function isInLayer(rule) {
return rule.parent?.type === "atrule" && rule.parent.name === "layer";
}
/**
* Parse the first var() call in a string by counting parens.
* Returns null if no var() found.
*/
function findVar(value, startFrom = 0) {
const idx = value.indexOf("var(", startFrom);
if (idx === -1) return null;
let depth = 1;
let i = idx + 4;
let commaIdx = -1;
while (i < value.length && depth > 0) {
const ch = value.charCodeAt(i);
if (ch === 40) depth++;
else if (ch === 41) {
if (--depth === 0) break;
} else if (ch === 44 && depth === 1 && commaIdx === -1) commaIdx = i;
i++;
}
if (depth !== 0) return null;
const name = commaIdx === -1 ? value.slice(idx + 4, i).trim() : value.slice(idx + 4, commaIdx).trim();
const fallback = commaIdx === -1 ? void 0 : value.slice(commaIdx + 1, i);
return {
start: idx,
end: i + 1,
name,
fallback
};
}
/**
* Resolve all var() references in a value string.
* Iterates until no resolvable var() remain.
*/
function resolveValue(value, localVars, rootVars, propertyDefaults) {
let result = value;
let safety = 10;
while (safety-- > 0) {
const v = findVar(result);
if (!v) break;
const resolved = localVars.get(v.name) ?? rootVars.get(v.name) ?? propertyDefaults?.get(v.name);
if (resolved !== void 0) result = result.slice(0, v.start) + resolved + result.slice(v.end);
else if (v.fallback !== void 0) result = result.slice(0, v.start) + v.fallback.trim() + result.slice(v.end);
else {
if (!findVar(result, v.end)) break;
const tail = resolveValue(result.slice(v.end), localVars, rootVars, propertyDefaults);
result = result.slice(0, v.end) + tail;
break;
}
}
return result;
}
var resolveProps_default = () => {
return {
postcssPlugin: "postcss-resolve-props",
Once(root) {
const propertyDefaults = /* @__PURE__ */ new Map();
root.walkAtRules("property", (rule) => {
const name = rule.params.trim();
if (!name.startsWith("--")) return;
rule.walkDecls("initial-value", (decl) => {
propertyDefaults.set(name, decl.value);
});
});
/**
* Pass 1: collect :root vars (top-level and inside @layer). Skip
* :root inside @media — those are for dark mode and should
* stay.
*/
const rootVars = /* @__PURE__ */ new Map();
root.walkRules((rule) => {
if (!isRootRule(rule)) return;
/**
* Allow :root at top level or inside @layer (Tailwind theme vars).
* Skip :root inside @media or other non-layer at-rules.
*/
if (rule.parent?.type !== "root" && !isInLayer(rule)) return;
rule.each((node) => {
if (node.type === "decl" && node.prop.startsWith("--")) rootVars.set(node.prop, node.value);
});
});
if (rootVars.size > 0) {
let changed = true;
let iterations = 5;
while (changed && iterations-- > 0) {
changed = false;
for (const [name, value] of rootVars) {
if (!value.includes("var(")) continue;
const resolved = resolveValue(value, rootVars, rootVars, propertyDefaults);
if (resolved !== value) {
rootVars.set(name, resolved);
changed = true;
}
}
}
}
root.walkRules((rule) => {
/**
* Skip :root inside @media — those vars are for dark mode etc. and
* must stay in the <style> tag as-is. Allow :root at top
* level and inside @layer (processed in pass 3).
*/
if (isRootRule(rule)) {
if (rule.parent?.type !== "root" && !isInLayer(rule)) return;
}
const localVars = /* @__PURE__ */ new Map();
const localDecls = [];
let hasVarRefs = false;
rule.walk((node) => {
if (node.type !== "decl") return;
if (node.prop.startsWith("--")) localDecls.push(node);
else if (node.value.includes("var(")) hasVarRefs = true;
});
if (!hasVarRefs && localDecls.length === 0) return;
for (const decl of localDecls) {
const value = decl.value.includes("var(") ? resolveValue(decl.value, localVars, rootVars, propertyDefaults) : decl.value;
localVars.set(decl.prop, value);
}
if (hasVarRefs) rule.walk((node) => {
if (node.type !== "decl") return;
if (node.prop.startsWith("--")) return;
if (!node.value.includes("var(")) return;
const resolved = resolveValue(node.value, localVars, rootVars, propertyDefaults);
if (resolved !== node.value) {
const cleaned = resolved.replace(/ +/g, " ").trim();
if (cleaned) node.value = cleaned;
else node.remove();
}
});
for (const decl of localDecls) decl.remove();
});
root.walkAtRules("property", (rule) => {
rule.remove();
});
root.walkRules((rule) => {
if (!isRootRule(rule)) return;
if (rule.parent?.type !== "root" && !isInLayer(rule)) return;
if (rule.nodes?.length === 0) rule.remove();
});
}
};
};
const postcss = true;
//#endregion
export { resolveProps_default as default, postcss };
//# sourceMappingURL=resolveProps.js.map