/** * # 模块 原站页面生成 CSS 翻译(post-.css → data-el 选择器) * 供 import-page-css / import-product-css 等导入脚本共用。 */ /** # 函数 把选择器中的 elementor-element- 改写为 data-el 属性选择器 * 规则保留条件:含文档 id,或引用 .ele-<自定类>(页面自定义类);其余丢弃 * 参数 sel 原选择器;ids 文档元素 id 集合;pid 页面(模板)post id */ export function translateSelector(sel: string, ids: Set, pid: number): string | null { const idIn = [...sel.matchAll(/elementor-element-(\w+)/g)].map((m) => m[1]); const hasDocId = idIn.some((id) => ids.has(id)); const hasCustomCls = /\.ele-[a-z][\w-]*/i.test(sel) && !/elementor-element-/.test(sel); if (!hasDocId && !hasCustomCls) return null; let out = sel; for (const id of new Set(idIn)) { if (!ids.has(id)) continue; out = out.split(`.elementor-element.elementor-element-${id}`).join(`[data-el="${id}"]`); out = out.split(`.elementor-element-${id}`).join(`[data-el="${id}"]`); } // 剥页面作用域前缀(.elementor- 空格相连)与多余空白 out = out.replace(new RegExp(`\\.elementor-${pid}\\s*`, "g"), ""); return out.replace(/\s+/g, " ").trim(); } /** # 函数 解析 CSS 顶层规则(含 @media 嵌套块),只保留命中文档 id/自定类的规则 * 参数 css 原始 CSS 文本;ids 文档元素 id 集合;pid 页面 post id */ export function filterCssForIds(css: string, ids: Set, pid: number): string { let out = ""; let i = 0; const n = css.length; while (i < n) { // 跳过注释 if (css.startsWith("/*", i)) { const end = css.indexOf("*/", i + 2); i = end === -1 ? n : end + 2; continue; } const brace = css.indexOf("{", i); if (brace === -1) break; const sel = css.slice(i, brace).trim(); let depth = 1; let j = brace + 1; while (j < n && depth > 0) { if (css[j] === "{") depth++; else if (css[j] === "}") depth--; j++; } const body = css.slice(brace + 1, j - 1); if (sel.startsWith("@media") || sel.startsWith("@supports")) { const inner = filterCssForIds(body, ids, pid); if (inner) out += `${sel}{${inner}}\n`; } else if (sel.startsWith("@keyframes") || sel.startsWith("@font-face")) { out += `${sel}{${body}}\n`; } else { const parts = sel.split(",").map((p) => translateSelector(p, ids, pid)).filter((p): p is string => !!p); if (parts.length) out += `${parts.join(",")}{${body}}\n`; } i = j; } return out; } /** # 函数 从文档(数组或 {elements} 包装)提取全部元素 id 集合 */ export function collectDocIds(el: unknown, out: Set = new Set()): Set { if (Array.isArray(el)) { for (const x of el) collectDocIds(x, out); return out; } if (!el || typeof el !== "object") return out; const e = el as { id?: unknown; elements?: unknown[] }; if (typeof e.id === "string") out.add(e.id); for (const c of Array.isArray(e.elements) ? e.elements : []) collectDocIds(c, out); return out; }