Slide-mode images rendered at intrinsic ratio, top-aligned inside the swiper chain (--pc-height:auto left .swiper-wrapper content-sized), so the taller box showed a gap at the bottom and never center-cropped like the image cover. The video cover had the same problem through video-player.js (height:auto, capped at 70vh). - aksrt_render_slider scale mode emits --pc-height/--m-height 100% so the wrapper/slide/img chain fills the ratio box and object-fit: cover center-crops inside it (same pattern as the .scale-height widgets) - video-player.js renders the video at height:100% + object-fit:cover; with an undimensioned container height:100% degrades to auto, matching the previous behavior - drop the dead .single-cover padding-bottom rules (every producer owns its height inline, and the rule squeezed the absolutely positioned slide inner) and the orphaned --single-cover-scale var in tokens.css/compat-vars.css/main.css/InlineStyleBuilder - rebuild public bundles; extend the single-cover-height contract
152 lines
5.3 KiB
JavaScript
152 lines
5.3 KiB
JavaScript
'use strict';
|
|
|
|
// 文章详情页顶部封面高度契约:单图 / 多图(轮播) / 视频三种模式
|
|
// 必须共用同一高度公式 padding-bottom: calc(比例% + 50px)。
|
|
|
|
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 read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
|
|
|
|
const singleRender = read('inc/helpers/aksrt-single-render.php');
|
|
const sliderHelper = read('inc/helpers/aksrt-slider.php');
|
|
|
|
test('single cover: image mode keeps the calc(scale% + 50px) height', () => {
|
|
assert.match(
|
|
singleRender,
|
|
/single-cover imgbox-container" style="padding-bottom:calc\(<\?php echo esc_attr\(\(string\) \$img_scale\); \?>% \+ 50px\);"/,
|
|
'单图封面必须输出 calc(img_scale% + 50px) 内联高度'
|
|
);
|
|
});
|
|
|
|
test('single cover: video mode aligns with the image-mode height formula', () => {
|
|
assert.match(
|
|
singleRender,
|
|
/single-cover--video imgbox-container" style="padding-bottom:calc\(<\?php echo esc_attr\(\(string\) \$video_scale\); \?>% \+ 50px\);"/,
|
|
'视频封面必须输出 calc(video_scale% + 50px) 内联高度'
|
|
);
|
|
// 不得回退到裸比例高度。
|
|
assert.doesNotMatch(
|
|
singleRender,
|
|
/padding-bottom:<\?php echo esc_attr\(\(string\) \$video_scale\); \?>%;"/,
|
|
'视频封面禁止输出不带 +50px 的裸比例高度'
|
|
);
|
|
});
|
|
|
|
test('single cover: slide mode reserves the same +50px via the slider helper', () => {
|
|
assert.match(
|
|
singleRender,
|
|
/'scale_extra'\s*=>\s*'50px'/,
|
|
'多图封面必须向 aksrt_render_slider 传入 scale_extra=50px'
|
|
);
|
|
assert.match(
|
|
sliderHelper,
|
|
/'scale_extra'\s*=>\s*''/,
|
|
'slider helper 需声明 scale_extra 默认参数'
|
|
);
|
|
// wrapper 的 padding-bottom 必须由比例 + 附加量组合而成。
|
|
assert.match(
|
|
sliderHelper,
|
|
/\$scale_padding = 'calc\(' \. \$scale_padding \. ' \+ ' \. \$scale_extra \. '\)';/,
|
|
'scale 模式必须把 scale_extra 合成 calc 表达式'
|
|
);
|
|
});
|
|
|
|
test('single cover: the dead static slide fallback is gone', () => {
|
|
assert.doesNotMatch(
|
|
singleRender,
|
|
/function_exists\('aksrt_render_slider'\)/,
|
|
'aksrt_render_slider 由 bootstrap 无条件加载,不得保留 function_exists 双路判断'
|
|
);
|
|
assert.doesNotMatch(
|
|
singleRender,
|
|
/single-cover--slide imgbox-container" style="padding-bottom/,
|
|
'多图封面只允许经由 slider helper 输出,禁止保留静态 fallback 分支'
|
|
);
|
|
});
|
|
|
|
test('slider scale mode: completes the definite height chain for cover cropping', () => {
|
|
assert.doesNotMatch(
|
|
sliderHelper,
|
|
/--scale-ratio/,
|
|
'--scale-ratio 无任何 CSS 消费方,禁止输出'
|
|
);
|
|
// wrapper 决定盒子高度;pc/m-height 100% 让 .swiper-wrapper/.swiper-slide
|
|
// 铺满比例盒,使 object-fit: cover 在确定的盒内居中裁切(对齐单图封面)。
|
|
assert.match(
|
|
sliderHelper,
|
|
/\$height_style = '--pc-height:100%;--m-height:100%;';/
|
|
);
|
|
assert.match(
|
|
sliderHelper,
|
|
/esc_attr\(\$height_style \. \(\$args\['scale_height'\] \? 'position:absolute;inset:0;width:100%;height:100%;' : ''\)\)/,
|
|
'内层 .new-swiper 必须绝对定位铺满 wrapper'
|
|
);
|
|
});
|
|
|
|
test('video cover: the player video fills and center-crops like the image cover', () => {
|
|
const player = read('assets/js/video-player.js');
|
|
assert.match(
|
|
player,
|
|
/\.aksrt-video video\{display:block;width:100%;height:100%;object-fit:cover;\}/,
|
|
'视频必须铺满封面比例盒并居中裁切'
|
|
);
|
|
assert.doesNotMatch(
|
|
player,
|
|
/max-height:70vh/,
|
|
'封面盒高度由比例盒决定,不得再套 70vh 截断'
|
|
);
|
|
});
|
|
|
|
test('single cover css owns no fallback padding and the scale var is gone', () => {
|
|
for (const file of [
|
|
'assets/css/frontend/single-post/cover.css',
|
|
'assets/css/main.css',
|
|
'assets/css/main.min.css',
|
|
'assets/css/core/tokens.css',
|
|
'assets/css/frontend/compat-vars.css',
|
|
'assets/css/build/public.css',
|
|
'assets/css/build/public.min.css',
|
|
]) {
|
|
const css = read(file);
|
|
assert.doesNotMatch(
|
|
css,
|
|
/\.single-cover\s*\{[^}]*padding-bottom/,
|
|
`${file} 的 .single-cover 不得声明 padding-bottom(高度归内联样式)`
|
|
);
|
|
assert.doesNotMatch(
|
|
css,
|
|
/--single-cover-scale/,
|
|
`${file} 不得再包含孤儿变量 --single-cover-scale`
|
|
);
|
|
}
|
|
assert.doesNotMatch(
|
|
read('src/Frontend/InlineStyleBuilder.php'),
|
|
/--single-cover-scale/,
|
|
'运行时 CSS 变量不得再输出孤儿 --single-cover-scale'
|
|
);
|
|
});
|
|
|
|
test('dead cover css is removed from every stylesheet surface', () => {
|
|
for (const file of [
|
|
'assets/css/frontend/single-post/cover.css',
|
|
'assets/css/main.css',
|
|
'assets/css/main.min.css',
|
|
'assets/css/build/public.css',
|
|
'assets/css/build/public.min.css',
|
|
'assets/css/frontend/enhancements/components/base.css',
|
|
]) {
|
|
const css = read(file);
|
|
assert.doesNotMatch(css, /\.single-cover-slide[,{ ]/, `${file} 不得再包含死的 .single-cover-slide 规则`);
|
|
assert.doesNotMatch(css, /\.single-cover-slider\b/, `${file} 不得再包含死的 .single-cover-slider 规则`);
|
|
}
|
|
assert.doesNotMatch(
|
|
read('assets/js/core/misc.js'),
|
|
/initSlideCovers/,
|
|
'misc.js 的 initSlideCovers(无标记生产方)已删除'
|
|
);
|
|
});
|