Files
dusuniot/src/components/elementor/slim.ts
T
bigcode ce59229801 v0.10.14: H13.5 counter 统计条(9084925)完成
- image-box 支持 title_typography_*/description_typography_*(36px/700/#ED6C00 标题、
  18px 描述)、image_space(图标下距 6px)、text_align、title_color 落样式;
  对应键进 slim 白名单
- 六列图标宽 30% 仅存 post-18 生成 CSS(DB 无 image_size),scoped 补规则
  (efe1577/d48a588/46684e1/17330e2/a7cd0a1/e6b1413)
- 双端节内相对几何/计算样式 JSON 逐字节一致:sec h 208→235 与原站全等,
  列边框 #E0E5F9(globals ee1917e)、末列四边;H0-H13.5 全页高度回归零差异
2026-11-01 22:55:21 +08:00

230 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* # 模块 Elementor 文档瘦身
* WordPress 导入的 Elementor JSON 包含大量桌面/平板/移动端响应式字段与空值,
* 整份文档会随 TanStack Router 脱水序列化进 SSR HTML(首页曾达 391KB),
* 严重影响 SEO 与首字节体积。本模块只保留渲染器实际读取的字段。
*/
/** # 成员变量 渲染器(Renderer.tsx)实际读取的 settings 字段白名单 **/
const SETTING_KEYS = new Set([
// 通用布局/背景/边框
"__globals__",
"align",
"background_background",
"background_color",
"background_color_b",
"background_color_stop_b",
"background_image",
// section 级背景定位/平铺(H11 底图 bottom center + no-repeat)
"background_position",
"background_repeat",
// 背景尺寸(initial → 100% auto,H13 列背景楼体图)
"background_size",
// icon-list 视图(inline = 横排链接条,H13)
"view",
"border_border",
"border_color",
"border_radius",
"border_width",
"content_width",
"custom_height",
"padding",
"layout",
"height",
"size",
"space",
"color",
"text_color",
"title_color",
"button_text_color",
"button_background_hover_color",
"hover_color",
"text_padding",
// image-box 系列:图定位(position 默认 top)与标题标签(title_size 默认 h3)
"position",
"title_size",
// image-box 行布局(H11):图宽 image_size%、标题底距、内容垂直对齐
"image_size",
"title_bottom_space",
"content_vertical_alignment",
// image-box 图标间距/文本对齐/标题与描述排版(H13.5 counter 条)
"image_space",
"text_align",
"title_typography_typography",
"title_typography_font_size",
"title_typography_font_size_mobile",
"title_typography_font_size_tablet",
"title_typography_font_weight",
"description_typography_typography",
"description_typography_font_size",
"description_typography_font_size_mobile",
"description_typography_font_size_tablet",
"gradient_angle",
"color_a",
"color_b",
"header_size",
// 组件自带盒间距与列 margin(heading/text-editor 的 _padding;内层列 margin)
"_padding",
"margin",
// Typography 组合字段(typography_typography=custom 时逐键采用)
"typography_typography",
"typography_font_family",
"typography_font_size",
"typography_font_size_tablet",
"typography_font_size_mobile",
"typography_font_weight",
"typography_line_height",
"typography_letter_spacing",
"typography_word_spacing",
"typography_text_transform",
"typography_font_style",
"typography_text_decoration",
// 列结构
"_column_size",
"_inline_size",
// section 间隙档位(决定子列默认 populated padding:no 0 / default 10 / …)
"gap",
// 各 widget 数据
"heading_title",
"title",
"title_text",
"description",
"description_text",
"selected_icon",
"url",
"width",
"text",
"editor",
"html",
"source_code",
"image",
"link",
"prefix",
"suffix",
"ending_number",
"icon_list",
"social_icon_list",
"slides",
"slides_height",
"tabs",
"tabs_align_horizontal",
"tab_active_color",
"video_url",
"youtube_url",
"map",
"posts_per_page",
"cards_posts_per_page",
"post_type",
"eael_ticker_tag_text",
// EAEL Infobox / flip-box / 高级标签页 / 数据表 / 评价等(Renderer 对应组件读取)
"custom_css",
"_css_classes",
"eael_infobox_title",
"eael_infobox_text",
"eael_infobox_title_tag",
"eael_infobox_image",
"eael_infobox_img_type",
"eael_infobox_img_margin",
"eael_infobox_title_margin",
"eael_infobox_title_margin_mobile",
"eael_infobox_title_typography_typography",
"eael_infobox_title_typography_font_size",
"hover_animation",
// widget 高级盒模型(如 eael-info-box 边框卡:_border_* + _padding/_margin)
"_margin",
// widget 宽度模式(auto → 按内容宽横排,如 H7 图标行)
"_element_width",
// widget 容器背景(如 H4 标题下的橙线图)
"_background_image",
"_background_position",
"_background_repeat",
// section 背景遮罩(.elementor-background-overlay,H11 电路板图+渐变)
"background_overlay_background",
"background_overlay_color",
"background_overlay_color_b",
"background_overlay_opacity",
"background_overlay_gradient_angle",
"_border_border",
"_border_color",
"_border_width",
"_border_radius",
"title_text_a",
"description_text_a",
"button_text",
"background_a_image",
"eael_adv_tabs_tab",
"eael_data_table_header_cols_data",
"eael_data_table_content_rows",
"eael_testimonial_name",
"eael_testimonial_company_title",
"eael_testimonial_description",
]);
/** # 函数 收窄对象型 settings 值(渲染器只读 url/alt/target 等少数字段)
* 参数 key settings 键名;val 原始值
* 返回值 收窄后的值;非命中键原样返回
*/
function slimSettingValue(key: string, val: unknown): unknown {
if (!val || typeof val !== "object" || Array.isArray(val)) return val;
const v = val as Record<string, unknown>;
if (key === "image" || key === "background_image" || key === "background_a_image" || key === "eael_infobox_image") {
// 渲染器只读 url / alt
return { url: v.url, alt: v.alt };
}
if (key === "link") {
// 渲染器只读 url / target / is_external(is_external=on → target=_blank,与原站 link_attributes 一致)
return { url: v.url, target: v.target, is_external: v.is_external };
}
return val;
}
/** # 函数 递归瘦身单个 Elementor 元素
* 参数 el 原始元素(section/column/widget 通用结构)
* 返回值 仅含 id/elType/widgetType/isInner/白名单 settings/elements 的新对象
*/
function slimElement(el: unknown): unknown {
if (!el || typeof el !== "object") return el;
const src = el as Record<string, unknown>;
const out: Record<string, unknown> = {};
if (src.id != null) out.id = src.id;
if (src.elType != null) out.elType = src.elType;
if (src.widgetType != null) out.widgetType = src.widgetType;
if (src.isInner) out.isInner = true;
const st = src.settings;
if (st && typeof st === "object" && !Array.isArray(st)) {
const slim: Record<string, unknown> = {};
for (const key of Object.keys(st as Record<string, unknown>)) {
if (SETTING_KEYS.has(key)) slim[key] = slimSettingValue(key, (st as Record<string, unknown>)[key]);
}
if (Object.keys(slim).length > 0) out.settings = slim;
}
if (Array.isArray(src.elements) && src.elements.length > 0) {
out.elements = src.elements.map(slimElement);
}
return out;
}
/** # 函数 瘦身整份 Elementor 文档(数组或 {elements:[]} 包装均支持)
* 参数 doc 原始文档(来自 meta.elementor)
* 返回值 瘦身后的文档;非对象/数组输入原样返回
*/
export function slimElementorDoc(doc: unknown): unknown {
if (Array.isArray(doc)) return doc.map(slimElement);
if (doc && typeof doc === "object" && Array.isArray((doc as Record<string, unknown>).elements)) {
const wrapped = doc as Record<string, unknown>;
return { elements: (wrapped.elements as unknown[]).map(slimElement) };
}
return doc;
}
/** # 函数 瘦身内容 meta:替换 meta.elementor 为瘦身版(原 meta 其余字段保留)
* 参数 meta 原始 meta JSON(可能为 null)
* 返回值 elementor 已瘦身的 meta;无 elementor 时原样返回
*/
export function slimMetaElementor<T>(meta: T): T {
if (!meta || typeof meta !== "object") return meta;
const m = meta as Record<string, unknown>;
if (!m.elementor) return meta;
return { ...m, elementor: slimElementorDoc(m.elementor) } as T;
}