feat(admin): replicate reference post-page settings page 1:1
- rewrite post_list.page schema (JS+PHP 2.0.0) with the reference field set: three cover types with option fieldsets (image 20-200% / slide CFS_Module::slide full config with nested dependsOn / video 0-200%), hide-time, p_indent, breadcrumbs (home-text as switcher), prevnext, authordesc, maxheight slider, yiyan block, copyright, button toptext, front/after content, related posts - migrate share_s to share page basic group and post_rewards_* to users features rewards group (runtime keys unchanged) - remap get_post_page_settings() to reference keys, normalize slide cover option, hardcode non-reference runtime flags (reading progress, favorites, author card), drop dual-path legacy aliases - wire slide option into aksrt_render_slider (effect/direction/spaceBetween/ speed/interval/loop/autoplay/nav/pagination, scale vs fixed-height modes), clamp image scale 20-200 and video scale 0-200 with 16:9 fallback, wire p_indent container class + CSS, resync frontend-tags fallback and FacadeBulk fallback, remap PostMetaBox cover keys - add post-page reference contract test; update stale cover-height and user-features contract tests Validation: node --test 464/464 pass, audit-admin-contracts errors=0, vite build ok, build-public-assets ok, php -l clean.
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 「文章页面」后台设置页契约(对齐参考主题 zibll 1:1):
|
||||
* 1) PHP schema(SchemaPostList.php page section 2.0.0)字段键、顺序、默认值与
|
||||
* JS schema(assets/admin/src/schema/sections/post-list/page.js)一致;
|
||||
* 2) 参考主题字段全集存在:三类封面(article_image_cover / article_slide_cover /
|
||||
* article_video_cover + option fieldset)、post_single_hide_time_s、
|
||||
* post_p_indent_s、breadcrumbs_single_s、breadcrumbs_home_text(switcher)、
|
||||
* post_prevnext_s、post_authordesc_s、article_maxheight_kg/maxheight、
|
||||
* 一言三项、post_copyright_s/post_copyright、post_button_toptext、
|
||||
* post_front_content/after_content、post_related_*;
|
||||
* 3) 幻灯片 fieldset 全字段及嵌套依赖(direction/scale_height/auto_height 组合)
|
||||
* 对齐参考主题 CFS_Module::slide;
|
||||
* 4) 旧 AKSRT 私有/异名字段(阅读进度条、面包屑末项文本、作者卡片配置、收藏开关、
|
||||
* share_s 与 post_rewards_*、旧封面键)已彻底移除,无双路兼容;
|
||||
* 5) 运行时(PostDisplay::get_post_page_settings)只读取新键:幻灯片配置归一化并
|
||||
* 接线 aksrt_render_slider,p_indent 接线容器类,breadcrumbs_home_text 为
|
||||
* switcher 布尔语义(true = 用「首页」替代网站名称)。
|
||||
*/
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
const php = fs.readFileSync(path.join(root, 'src/Admin/Schema/SchemaPostList.php'), 'utf8');
|
||||
const js = fs.readFileSync(path.join(root, 'assets/admin/src/schema/sections/post-list/page.js'), 'utf8');
|
||||
const runtime = fs.readFileSync(path.join(root, 'src/Settings/PostDisplay.php'), 'utf8');
|
||||
const facadeBulk = fs.readFileSync(path.join(root, 'src/Settings/FacadeBulk.php'), 'utf8');
|
||||
const metaBox = fs.readFileSync(path.join(root, 'src/Core/PostMetaBox.php'), 'utf8');
|
||||
const frontendTags = fs.readFileSync(path.join(root, 'inc/helpers/aksrt-frontend-tags.php'), 'utf8');
|
||||
const singleRender = fs.readFileSync(path.join(root, 'inc/helpers/aksrt-single-render.php'), 'utf8');
|
||||
const contentCss = fs.readFileSync(path.join(root, 'assets/css/frontend/single-post/content.css'), 'utf8');
|
||||
const shareJs = fs.readFileSync(path.join(root, 'assets/admin/src/schema/sections/post-list/share.js'), 'utf8');
|
||||
const sharePhp = php;
|
||||
const featuresJs = fs.readFileSync(path.join(root, 'assets/admin/src/schema/sections/users/features.js'), 'utf8');
|
||||
const usersPhp = fs.readFileSync(path.join(root, 'src/Admin/Schema/SchemaUsers.php'), 'utf8');
|
||||
|
||||
/** Extract a PHP section body by its section key (balanced brackets). */
|
||||
function phpSection(src, sectionKey) {
|
||||
const start = src.indexOf(`'${sectionKey}' => [`);
|
||||
assert.notEqual(start, -1, `PHP schema has a ${sectionKey} section`);
|
||||
const open = src.indexOf('[', start);
|
||||
let depth = 0;
|
||||
for (let i = open; i < src.length; i++) {
|
||||
const ch = src[i];
|
||||
if (ch === "'" || ch === '"') {
|
||||
const quote = ch;
|
||||
i++;
|
||||
while (i < src.length) {
|
||||
if (src[i] === '\\') { i += 2; continue; }
|
||||
if (src[i] === quote) break;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch === '[') depth++;
|
||||
else if (ch === ']') {
|
||||
depth--;
|
||||
if (depth === 0) return src.slice(open, i + 1);
|
||||
}
|
||||
}
|
||||
throw new Error(`unbalanced ${sectionKey} section`);
|
||||
}
|
||||
|
||||
const pagePhp = phpSection(php, 'page');
|
||||
|
||||
// 参考主题 admin-options.php 4934–5249 的字段顺序(含 fieldset 父字段与子字段)。
|
||||
const PAGE_FIELD_SEQUENCE = [
|
||||
'article_image_cover',
|
||||
'article_image_cover_option',
|
||||
'scale', // article_image_cover_option.scale
|
||||
'article_slide_cover',
|
||||
'article_slide_cover_option',
|
||||
// article_slide_cover_option(CFS_Module::slide 全字段)
|
||||
'direction', 'loop', 'button', 'pagination', 'effect', 'scale_height', 'scale',
|
||||
'auto_height', 'max_height', 'min_height', 'pc_height', 'm_height',
|
||||
'spacebetween', 'speed', 'autoplay', 'interval',
|
||||
'article_video_cover',
|
||||
'article_video_cover_option',
|
||||
'scale', // article_video_cover_option.scale
|
||||
'post_single_hide_time_s',
|
||||
'post_p_indent_s',
|
||||
'breadcrumbs_single_s',
|
||||
'breadcrumbs_home_text',
|
||||
'post_prevnext_s',
|
||||
'post_authordesc_s',
|
||||
'article_maxheight_kg',
|
||||
'article_maxheight',
|
||||
'yiyan_single_content_header',
|
||||
'yiyan_single_content_footer',
|
||||
'yiyan_single_box',
|
||||
'post_copyright_s',
|
||||
'post_copyright',
|
||||
'post_button_toptext',
|
||||
'post_front_content',
|
||||
'post_after_content',
|
||||
'post_related_s',
|
||||
'post_related_type',
|
||||
'related_title',
|
||||
'post_related_n',
|
||||
'post_related_orderby',
|
||||
];
|
||||
|
||||
// 旧 AKSRT 私有/异名字段:已迁移(share_s / post_rewards_*)或无参考对应项被移除。
|
||||
const LEGACY_KEYS = [
|
||||
'post_reading_progress',
|
||||
'post_author_card_limit',
|
||||
'post_author_card_orderby',
|
||||
'post_author_card_style',
|
||||
'post_favorite_enabled',
|
||||
'post_wechat_share',
|
||||
'post_article_image_cover',
|
||||
'post_article_slide_cover',
|
||||
'post_article_video_cover',
|
||||
];
|
||||
|
||||
test('PHP page section 字段键与参考主题一致且顺序相同', () => {
|
||||
// 字段定义均为 ['key' => '...', 'label' => ...] 开头;dependsOn 内的
|
||||
// ['key' => '...', 'value'/'not' => ...] 不是字段定义,须排除。
|
||||
const found = [];
|
||||
const re = /'key'\s*=>\s*'([a-z0-9_]+)',\s*'label'/g;
|
||||
let m;
|
||||
while ((m = re.exec(pagePhp)) !== null) found.push(m[1]);
|
||||
assert.deepEqual(found, PAGE_FIELD_SEQUENCE);
|
||||
});
|
||||
|
||||
test('PHP page section 版本升级至 2.0.0 且为单一 post_page 组', () => {
|
||||
assert.match(pagePhp, /'version'\s*=>\s*'2\.0\.0'/);
|
||||
assert.match(pagePhp, /'groups'\s*=>\s*\[\s*\['key'\s*=>\s*'post_page',\s*'title'\s*=>\s*'文章页面'/);
|
||||
});
|
||||
|
||||
test('PHP page section 默认值对齐参考主题', () => {
|
||||
// 三类封面开关。
|
||||
assert.match(pagePhp, /'article_image_cover',\s*'label'\s*=>\s*'图片封面',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(pagePhp, /'article_slide_cover',\s*'label'\s*=>\s*'幻灯片封面',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(pagePhp, /'article_video_cover',\s*'label'\s*=>\s*'视频封面',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
// 图片封面比例:20-200 step5,默认 35。
|
||||
assert.match(pagePhp, /'scale',\s*'label'\s*=>\s*'图片长宽比例',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*35,\s*'min'\s*=>\s*20,\s*'max'\s*=>\s*200,\s*'step'\s*=>\s*5/);
|
||||
// 视频封面比例:0-200,默认 0(为 0 则不固定长宽比例)。
|
||||
assert.match(pagePhp, /'scale',\s*'label'\s*=>\s*'固定长宽比例',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*0,\s*'min'\s*=>\s*0,\s*'max'\s*=>\s*200/);
|
||||
// 面包屑「首页」替代开关(switcher,默认 true)。
|
||||
assert.match(pagePhp, /'breadcrumbs_home_text',\s*'label'\s*=>\s*'面包屑导航用“首页”替代网站名称',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
// 段落缩进 / 隐藏时间。
|
||||
assert.match(pagePhp, /'post_p_indent_s',\s*'label'\s*=>\s*'内容段落缩进',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(pagePhp, /'post_single_hide_time_s',\s*'label'\s*=>\s*'隐藏时间',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
// 内容高度限制:slider 600-3000 step100。
|
||||
assert.match(pagePhp, /'article_maxheight_kg',\s*'label'\s*=>\s*'内容高度限制',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(pagePhp, /'article_maxheight',\s*'label'\s*=>\s*'限制的最大高度',\s*'type'\s*=>\s*'slider',\s*'default'\s*=>\s*1000,\s*'min'\s*=>\s*600,\s*'max'\s*=>\s*3000,\s*'step'\s*=>\s*100/);
|
||||
// 版权声明。
|
||||
assert.match(pagePhp, /'post_copyright_s',\s*'label'\s*=>\s*'版权声明',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(pagePhp, /'post_copyright',\s*'label'\s*=>\s*'版权提示内容',\s*'type'\s*=>\s*'textarea',\s*'default'\s*=>\s*'文章版权归作者所有,未经允许请勿转载。'/);
|
||||
assert.match(pagePhp, /'post_button_toptext',\s*'label'\s*=>\s*'文章页脚文案',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'喜欢就支持一下吧'/);
|
||||
// 相关文章:image_select 三样式 + 数量 4-12 step2 + 排序默认 views。
|
||||
assert.match(pagePhp, /'post_related_type',\s*'label'\s*=>\s*'显示样式',\s*'type'\s*=>\s*'image_select',\s*'default'\s*=>\s*'img'/);
|
||||
assert.match(pagePhp, /'post_related_n',\s*'label'\s*=>\s*'显示数量',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*6,\s*'min'\s*=>\s*4,\s*'max'\s*=>\s*12,\s*'step'\s*=>\s*2/);
|
||||
assert.match(pagePhp, /'post_related_orderby',\s*'label'\s*=>\s*'排序方式',\s*'type'\s*=>\s*'select',\s*'default'\s*=>\s*'views'/);
|
||||
});
|
||||
|
||||
test('PHP slide fieldset 全字段及嵌套依赖对齐 CFS_Module::slide', () => {
|
||||
// 幻灯片默认值(pagination: true, pc_height: 380, m_height: 180 为参考主题默认)。
|
||||
assert.match(pagePhp, /'direction'\s*=>\s*'horizontal',\s*'loop'\s*=>\s*true,\s*'button'\s*=>\s*false,\s*'pagination'\s*=>\s*true,\s*'effect'\s*=>\s*'slide'/);
|
||||
assert.match(pagePhp, /'pc_height'\s*=>\s*380,\s*'m_height'\s*=>\s*180,\s*'spacebetween'\s*=>\s*15,\s*'speed'\s*=>\s*0,\s*'autoplay'\s*=>\s*true,\s*'interval'\s*=>\s*4/);
|
||||
// 嵌套依赖:scale_height 需要 direction != vertical。
|
||||
assert.match(pagePhp, /'scale_height',\s*'label'\s*=>\s*'按比例自动高度',\s*'type'\s*=>\s*'switch',\s*'default'\s*=>\s*true,\s*'dependsOn'\s*=>\s*\['key'\s*=>\s*'direction',\s*'not'\s*=>\s*'vertical'\]/);
|
||||
// scale 需要 direction != vertical 且 scale_height 开启。
|
||||
assert.match(pagePhp, /'scale',\s*'label'\s*=>\s*'长宽比例'[\s\S]*?'dependsOn'\s*=>\s*\['all'\s*=>\s*\[\['key'\s*=>\s*'direction',\s*'not'\s*=>\s*'vertical'\],\s*\['key'\s*=>\s*'scale_height',\s*'value'\s*=>\s*true\]\]\]/);
|
||||
// auto_height 需要 direction != vertical 且 scale_height 关闭。
|
||||
assert.match(pagePhp, /'auto_height',\s*'label'\s*=>\s*'自动高度'[\s\S]*?'dependsOn'\s*=>\s*\['all'\s*=>\s*\[\['key'\s*=>\s*'direction',\s*'not'\s*=>\s*'vertical'\],\s*\['key'\s*=>\s*'scale_height',\s*'value'\s*=>\s*false\]\]\]/);
|
||||
// max/min_height 需要 auto_height 开启 + direction != vertical + scale_height 关闭。
|
||||
assert.match(pagePhp, /'max_height',\s*'label'\s*=>\s*'最大高度'[\s\S]*?'dependsOn'\s*=>\s*\['all'\s*=>\s*\[\['key'\s*=>\s*'auto_height',\s*'value'\s*=>\s*true\],\s*\['key'\s*=>\s*'direction',\s*'not'\s*=>\s*'vertical'\],\s*\['key'\s*=>\s*'scale_height',\s*'value'\s*=>\s*false\]\]\]/);
|
||||
// interval 依赖 autoplay。
|
||||
assert.match(pagePhp, /'interval',\s*'label'\s*=>\s*'停顿时间'[\s\S]*?'dependsOn'\s*=>\s*\['key'\s*=>\s*'autoplay',\s*'value'\s*=>\s*true\]/);
|
||||
// 五种切换动画。
|
||||
for (const effect of ['slide', 'fade', 'cube', 'coverflow', 'flip']) {
|
||||
assert.ok(pagePhp.includes(`'value' => '${effect}'`), `缺少切换动画 ${effect}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('PHP page section 不含旧私有/异名字段(无双路)', () => {
|
||||
for (const legacy of LEGACY_KEYS) {
|
||||
assert.ok(!pagePhp.includes(`'${legacy}'`), `page section 残留旧字段: ${legacy}`);
|
||||
}
|
||||
// share_s / post_rewards_* 已迁移至分享设置页与用户功能页。
|
||||
assert.ok(!pagePhp.includes(`'share_s'`), 'page section 残留 share_s');
|
||||
assert.ok(!pagePhp.includes(`'post_rewards_`), 'page section 残留 post_rewards_*');
|
||||
});
|
||||
|
||||
test('JS schema 与 PHP 字段键一致(ui_only 一言行除外)', () => {
|
||||
const keys = [];
|
||||
const re = /key:\s*'([a-z0-9_]+)',\s*label:/g;
|
||||
let m;
|
||||
while ((m = re.exec(js)) !== null) keys.push(m[1]);
|
||||
assert.deepEqual(keys, PAGE_FIELD_SEQUENCE);
|
||||
for (const legacy of LEGACY_KEYS) {
|
||||
assert.ok(!keys.includes(legacy), `JS schema 残留旧字段: ${legacy}`);
|
||||
}
|
||||
assert.ok(!js.includes(`key: 'share_s'`), 'JS page schema 残留 share_s');
|
||||
assert.ok(!/key:\s*'post_rewards_/.test(js), 'JS page schema 残留 post_rewards_*');
|
||||
// 参考主题视频封面配置教程链接以 ui_only description 承载。
|
||||
assert.match(js, /ui_only:\s*true/);
|
||||
assert.match(js, /https:\/\/www\.zibll\.com\/1900\.html/);
|
||||
});
|
||||
|
||||
test('JS schema 默认值与依赖对齐参考主题', () => {
|
||||
assert.match(js, /article_image_cover:\s*true/);
|
||||
assert.match(js, /article_image_cover_option:\s*\{\s*scale:\s*35\s*\}/);
|
||||
assert.match(js, /article_slide_cover:\s*true/);
|
||||
assert.match(js, /article_video_cover:\s*true/);
|
||||
assert.match(js, /article_video_cover_option:\s*\{\s*scale:\s*0\s*\}/);
|
||||
assert.match(js, /post_single_hide_time_s:\s*false/);
|
||||
assert.match(js, /post_p_indent_s:\s*false/);
|
||||
assert.match(js, /breadcrumbs_single_s:\s*true/);
|
||||
assert.match(js, /breadcrumbs_home_text:\s*true/);
|
||||
assert.match(js, /post_prevnext_s:\s*true/);
|
||||
assert.match(js, /post_authordesc_s:\s*true/);
|
||||
assert.match(js, /article_maxheight_kg:\s*false/);
|
||||
assert.match(js, /article_maxheight:\s*1000/);
|
||||
assert.match(js, /post_copyright_s:\s*true/);
|
||||
assert.match(js, /post_copyright:\s*'文章版权归作者所有,未经允许请勿转载。'/);
|
||||
assert.match(js, /post_button_toptext:\s*'喜欢就支持一下吧'/);
|
||||
assert.match(js, /post_related_s:\s*true/);
|
||||
assert.match(js, /post_related_type:\s*'img'/);
|
||||
assert.match(js, /related_title:\s*'相关推荐'/);
|
||||
assert.match(js, /post_related_n:\s*6/);
|
||||
assert.match(js, /post_related_orderby:\s*'views'/);
|
||||
// 幻灯片嵌套依赖(dependsOn {key, not} / {all: [...]} 形式)。
|
||||
assert.match(js, /key:\s*'scale_height',[\s\S]*?dependsOn:\s*\{\s*key:\s*'direction',\s*not:\s*'vertical'\s*\}/);
|
||||
assert.match(js, /key:\s*'scale',[\s\S]*?dependsOn:\s*\{\s*all:\s*\[\{\s*key:\s*'direction',\s*not:\s*'vertical'\s*\},\s*\{\s*key:\s*'scale_height',\s*value:\s*true\s*\}\]\s*\}/);
|
||||
assert.match(js, /key:\s*'auto_height',[\s\S]*?dependsOn:\s*\{\s*all:\s*\[\{\s*key:\s*'direction',\s*not:\s*'vertical'\s*\},\s*\{\s*key:\s*'scale_height',\s*value:\s*false\s*\}\]\s*\}/);
|
||||
assert.match(js, /key:\s*'interval',[\s\S]*?dependsOn:\s*\{\s*key:\s*'autoplay',\s*value:\s*true\s*\}/);
|
||||
});
|
||||
|
||||
test('share_s 迁移至分享设置页 basic 组(键不变,无双路)', () => {
|
||||
assert.match(sharePhp, /\['key' => 'basic', 'title' => '分享按钮', 'fields' => \[\s*\['key' => 'share_s', 'label' => '分享按钮', 'type' => 'switcher', 'default' => true, 'help' => '关闭后,在文章页面将不显示分享按钮,论坛及商城不受影响'\]/);
|
||||
assert.match(shareJs, /key: 'basic',/);
|
||||
assert.match(shareJs, /share_s: true/);
|
||||
assert.match(shareJs, /key: 'share_s', label: '分享按钮', type: 'switch', default: true, help: '关闭后,在文章页面将不显示分享按钮,论坛及商城不受影响'/);
|
||||
});
|
||||
|
||||
test('post_rewards_* 迁移至用户功能页 rewards 组(对齐参考主题 8977 行)', () => {
|
||||
assert.match(usersPhp, /\['key' => 'rewards', 'title' => '打赏', 'fields' => \[/);
|
||||
assert.match(usersPhp, /'post_rewards_s', 'label' => '用户打赏功能', 'type' => 'switcher', 'default' => true/);
|
||||
assert.match(usersPhp, /'post_rewards_text', 'label' => '打赏按钮文案', 'type' => 'input', 'default' => '赞赏'/);
|
||||
assert.match(featuresJs, /post_rewards_s:\s*true/);
|
||||
assert.match(featuresJs, /post_rewards_text:\s*'赞赏'/);
|
||||
assert.match(featuresJs, /key: 'post_rewards_s', label: '用户打赏功能', type: 'switch', default: true/);
|
||||
});
|
||||
|
||||
test('旧字段在 schema 与运行时中均已移除(无双路)', () => {
|
||||
for (const legacy of LEGACY_KEYS) {
|
||||
assert.ok(!php.includes(legacy), `PHP schema 残留旧字段: ${legacy}`);
|
||||
assert.ok(!runtime.includes(legacy), `PostDisplay 残留旧字段: ${legacy}`);
|
||||
assert.ok(!js.includes(legacy), `page.js 残留旧字段: ${legacy}`);
|
||||
assert.ok(!metaBox.includes(legacy), `PostMetaBox 残留旧字段: ${legacy}`);
|
||||
}
|
||||
// 面包屑末项正文无参考配置:schema 字段移除,运行时硬编码为常开。
|
||||
assert.ok(!pagePhp.includes(`'breadcrumbs_single_text'`), 'page section 残留 breadcrumbs_single_text');
|
||||
assert.ok(!js.includes(`key: 'breadcrumbs_single_text'`), 'page.js 残留 breadcrumbs_single_text');
|
||||
assert.match(runtime, /'breadcrumbs_single_text'\s*=>\s*true/);
|
||||
// aksrt-frontend-tags 不再有 breadcrumbs_home_text 文本兼容(switcher 布尔语义)。
|
||||
assert.ok(!frontendTags.includes("breadcrumbs_home'] = (string) $settings['breadcrumbs_home_text'"), 'frontend-tags 残留 breadcrumbs_home_text 文本兼容');
|
||||
});
|
||||
|
||||
test('运行时只读取新键并接线封面/缩进/版权/一言', () => {
|
||||
// 三类封面 + option fieldset。
|
||||
assert.match(runtime, /\$settings\['article_image_cover'\]/);
|
||||
assert.match(runtime, /\$settings\['article_image_cover_option'\]/);
|
||||
assert.match(runtime, /\$settings\['article_slide_cover'\]/);
|
||||
assert.match(runtime, /\$settings\['article_slide_cover_option'\]/);
|
||||
assert.match(runtime, /\$settings\['article_video_cover'\]/);
|
||||
assert.match(runtime, /\$settings\['article_video_cover_option'\]/);
|
||||
// 图片封面比例 clamp 20-200(参考主题默认 35)。
|
||||
assert.match(runtime, /max\(20, min\(200, \(int\) \(\$image_cover_option\['scale'\] \?\? 35\)\)\)/);
|
||||
// 视频封面比例 clamp 0-200(0 = 不固定长宽比例)。
|
||||
assert.match(runtime, /max\(0, min\(200, \(int\) \(\$video_cover_option\['scale'\] \?\? 0\)\)\)/);
|
||||
// 幻灯片配置归一化(CFS_Module::slide 全字段)。
|
||||
assert.match(runtime, /normalize_slide_cover_option\(\$slide_option_raw\)/);
|
||||
for (const key of ['direction', 'loop', 'button', 'pagination', 'effect', 'scale_height', 'scale', 'auto_height', 'max_height', 'min_height', 'pc_height', 'm_height', 'spacebetween', 'speed', 'autoplay', 'interval']) {
|
||||
assert.ok(runtime.includes(`'${key}'`), `normalize_slide_cover_option 缺少 ${key}`);
|
||||
}
|
||||
// 面包屑「首页」替代语义:true → 「首页」,false → 网站名称。
|
||||
assert.match(runtime, /!isset\(\$settings\['breadcrumbs_home_text'\]\) \|\| !empty\(\$settings\['breadcrumbs_home_text'\]\)/);
|
||||
assert.match(runtime, /get_bloginfo\('name'\)/);
|
||||
// 段落缩进 / 高度限制 / 版权 / 页脚文案 / 插入内容 / 一言 / 相关文章。
|
||||
assert.match(runtime, /\$settings\['post_p_indent_s'\]/);
|
||||
assert.match(runtime, /\$settings\['article_maxheight_kg'\]/);
|
||||
assert.match(runtime, /\$settings\['article_maxheight'\]/);
|
||||
assert.match(runtime, /\$settings\['post_copyright_s'\]/);
|
||||
assert.match(runtime, /\$settings\['post_copyright'\]/);
|
||||
assert.match(runtime, /\$settings\['post_button_toptext'\]/);
|
||||
assert.match(runtime, /\$settings\['post_front_content'\]/);
|
||||
assert.match(runtime, /\$settings\['post_after_content'\]/);
|
||||
assert.match(runtime, /\$settings\['yiyan_single_content_header'\]/);
|
||||
assert.match(runtime, /\$settings\['yiyan_single_content_footer'\]/);
|
||||
assert.match(runtime, /\$settings\['yiyan_single_box'\]/);
|
||||
assert.match(runtime, /\$settings\['post_related_s'\]/);
|
||||
assert.match(runtime, /\$settings\['post_related_type'\]/);
|
||||
assert.match(runtime, /\$settings\['post_related_n'\]/);
|
||||
assert.match(runtime, /\$settings\['post_related_orderby'\]/);
|
||||
// 阅读进度/收藏/作者卡片无参考配置:常量默认(无双路)。
|
||||
assert.match(runtime, /'reading_progress'\s*=>\s*true/);
|
||||
assert.match(runtime, /'favorite_enabled'\s*=>\s*true/);
|
||||
assert.match(runtime, /'author_card_limit'\s*=>\s*6/);
|
||||
});
|
||||
|
||||
test('前台链路:幻灯片配置接线渲染器,p_indent 接线容器与 CSS', () => {
|
||||
// 幻灯片配置接入 aksrt_render_slider(effect/direction/spaceBetween/speed/interval)。
|
||||
assert.match(singleRender, /article_slide_cover_option/);
|
||||
assert.match(singleRender, /'effect'\s*=>\s*\(string\) \(\$slide_option\['effect'\] \?\? 'slide'\)/);
|
||||
assert.match(singleRender, /'direction'\s*=>\s*\(string\) \(\$slide_option\['direction'\] \?\? 'horizontal'\)/);
|
||||
assert.match(singleRender, /'spaceBetween'\s*=>\s*\(int\) \(\$slide_option\['spacebetween'\] \?\? 15\)/);
|
||||
assert.match(singleRender, /'interval'\s*=>\s*max\(1, \(int\) \(\$slide_option\['interval'\] \?\? 4\)\) \* 1000/);
|
||||
assert.match(singleRender, /'show_nav'\s*=>\s*!empty\(\$slide_option\['button'\]\)/);
|
||||
assert.match(singleRender, /'show_pagination'\s*=>\s*!empty\(\$slide_option\['pagination'\]\)/);
|
||||
// 固定高度模式(scale_height)与比例高度模式(scale + 50px 标题预留)双分支。
|
||||
assert.match(singleRender, /!empty\(\$slide_option\['scale_height'\]\)/);
|
||||
assert.match(singleRender, /\$slider_args\['pc_height'\] = \(\(int\) \(\$slide_option\['pc_height'\] \?\? 380\)\) \. 'px'/);
|
||||
assert.match(singleRender, /\$slider_args\['scale_ratio'\] = max\(10, \(int\) \(\$slide_option\['scale'\] \?\? 35\)\) \/ 100/);
|
||||
// 图片封面比例 clamp 20-200;视频封面 0 → 16:9(56.25)回退。
|
||||
assert.match(singleRender, /max\(20, min\(200, \(int\) \$ctx\['img_scale'\]\)\)/);
|
||||
assert.match(singleRender, /max\(0, min\(200, \(int\) \$ctx\['video_scale'\]\)\)/);
|
||||
assert.match(singleRender, /\$video_scale > 0 \? \(string\) \$video_scale : '56\.25'/);
|
||||
// p_indent 容器类 + CSS 规则(首行缩进 2em)。
|
||||
assert.match(singleRender, /p-indent/);
|
||||
assert.match(contentCss, /\.wp-posts-content\.p-indent p\s*\{\s*text-indent:\s*2em;/);
|
||||
// 前端回退数组包含新键。
|
||||
assert.match(frontendTags, /'p_indent'\s*=>\s*false/);
|
||||
assert.match(frontendTags, /'article_image_cover_scale'\s*=>\s*35/);
|
||||
assert.match(frontendTags, /'article_slide_cover_option'\s*=>\s*\[\]/);
|
||||
assert.match(frontendTags, /'article_video_cover_scale'\s*=>\s*0/);
|
||||
// PostMetaBox 读取新封面键(文章级封面字段可见性)。
|
||||
assert.match(metaBox, /!empty\(\$settings\['article_image_cover'\]\)/);
|
||||
assert.match(metaBox, /!empty\(\$settings\['article_slide_cover'\]\)/);
|
||||
assert.match(metaBox, /!empty\(\$settings\['article_video_cover'\]\)/);
|
||||
// FacadeBulk 独立回退与新键同步。
|
||||
assert.match(facadeBulk, /'breadcrumbs_home_replace'/);
|
||||
assert.match(facadeBulk, /'article_slide_cover_option'/);
|
||||
});
|
||||
Reference in New Issue
Block a user