From 3c3ddac8be653002209edf81cc5aee35c176ca77 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Aug 2026 16:23:44 +0800 Subject: [PATCH] fix(frontend): align article list metadata and pagination --- assets/css/frontend/post-card.css | 31 ++++++++++++++++++- assets/js/core/ajax-list.js | 4 +-- inc/helpers/homepage/content.php | 24 +++----------- src/Core/ScriptsPart1c.php | 4 +-- .../post-visual-contract.test.cjs | 23 ++++++++++++++ 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/assets/css/frontend/post-card.css b/assets/css/frontend/post-card.css index 87a21329..06a8697e 100644 --- a/assets/css/frontend/post-card.css +++ b/assets/css/frontend/post-card.css @@ -24,6 +24,33 @@ transition: 0.2s; } +.posts-item.flex, +.posts-item .flex, +.posts-mini .flex { + display: flex; +} + +.posts-item .flex.xx, +.posts-mini .flex.xx { + flex-direction: column; +} + +.posts-item .flex.ac, +.posts-mini .flex.ac { + align-items: center; +} + +.posts-item .flex.jsb, +.posts-mini .flex.jsb { + justify-content: space-between; +} + +.posts-item .flex1, +.posts-mini .flex1 { + flex: 1; + overflow: hidden; +} + .posts-item .post-graphic:not(.order1) { margin-right: 20px; } @@ -157,10 +184,12 @@ .posts-item .item-meta svg.icon, .posts-mini .item-meta svg.icon { + display: inline-block; width: 1em; height: 1em; - margin-right: 3px; + margin-right: 2px; fill: currentColor; + overflow: hidden; vertical-align: -0.15em; } diff --git a/assets/js/core/ajax-list.js b/assets/js/core/ajax-list.js index 6f12bb31..c36e7797 100644 --- a/assets/js/core/ajax-list.js +++ b/assets/js/core/ajax-list.js @@ -358,8 +358,8 @@ if (!link) return; // Ignore if inside a component that opts out. if (link.closest("[data-aksrt-ajax-list='off']")) return; - // Native pagination core may own .aksrt-pagination-ajax buttons. - if (link.closest(".aksrt-pagination-ajax") && !link.classList.contains("ajax-next")) return; + // The canonical pagination engine exclusively owns these controls. + if (link.closest("[data-aksrt-pagination], .aksrt-comment-pagination")) return; var href = link.getAttribute("href") || link.getAttribute("ajax-href") || link.getAttribute("data-aksrt-ajax-url"); if (!href && !link.getAttribute("data-aksrt-ajax-url")) return; diff --git a/inc/helpers/homepage/content.php b/inc/helpers/homepage/content.php index 2885c81b..8106a15b 100644 --- a/inc/helpers/homepage/content.php +++ b/inc/helpers/homepage/content.php @@ -273,25 +273,11 @@ if (!function_exists('aksrt_homepage_render_pagination')) { } $contract = aksrt_homepage_get_latest_panel_contract(); - ?> -
- - - - -
- $contract['query_context'], + 'render_config' => $contract['render_config_array'], + 'current_page' => $current_page, + ]); } } diff --git a/src/Core/ScriptsPart1c.php b/src/Core/ScriptsPart1c.php index 0bd50c24..37dfd8b9 100644 --- a/src/Core/ScriptsPart1c.php +++ b/src/Core/ScriptsPart1c.php @@ -227,9 +227,9 @@ trait ScriptsPart1c { wp_enqueue_script( 'aksrt-svg-icon', $base_uri . '/assets/js/svg-icon.js', - [], + ['jquery'], (string) filemtime($svg_icon_js), - false // load in so icons are available early + true // load after exists ); } diff --git a/tests/widget-system/post-visual-contract.test.cjs b/tests/widget-system/post-visual-contract.test.cjs index 7157e2e7..9b5b1b6a 100644 --- a/tests/widget-system/post-visual-contract.test.cjs +++ b/tests/widget-system/post-visual-contract.test.cjs @@ -183,6 +183,24 @@ test('post-card CSS owns the exact desktop and 767/640 responsive matrix', () => assert.doesNotMatch(css, /\.aksrt-|post-card-cms|grid-cms/); }); +test('article metadata owns its flex and SVG contracts on every list route', () => { + const css = read('assets/css/frontend/post-card.css'); + const scripts = read('src/Core/ScriptsPart1c.php'); + const svgEnqueue = scripts.slice( + scripts.indexOf("'aksrt-svg-icon',"), + scripts.indexOf("'aksrt-svg-icon-helper',") + ); + + assert.match(svgEnqueue, /\['jquery'\]/); + assert.match(svgEnqueue, /true\s*\/\/ load after exists/); + assert.match(css, /\.posts-item\.flex,[\s\S]*?\.posts-mini \.flex\s*\{[^}]*display:\s*flex;/); + assert.match(css, /\.posts-item \.flex\.xx,[\s\S]*?\.posts-mini \.flex\.xx\s*\{[^}]*flex-direction:\s*column;/); + assert.match(css, /\.posts-item \.flex\.ac,[\s\S]*?\.posts-mini \.flex\.ac\s*\{[^}]*align-items:\s*center;/); + assert.match(css, /\.posts-item \.flex\.jsb,[\s\S]*?\.posts-mini \.flex\.jsb\s*\{[^}]*justify-content:\s*space-between;/); + assert.match(css, /\.posts-item \.flex1,[\s\S]*?\.posts-mini \.flex1\s*\{[^}]*flex:\s*1;[^}]*overflow:\s*hidden;/); + assert.match(css, /\.posts-item \.item-meta svg\.icon,[\s\S]*?\.posts-mini \.item-meta svg\.icon\s*\{[^}]*display:\s*inline-block;[^}]*margin-right:\s*2px;/); +}); + test('related posts, author page and widgets use their dedicated renderers', () => { const related = read('inc/helpers/aksrt-single-render.php'); const relatedCard = read('inc/helpers/aksrt-single-components.php'); @@ -210,8 +228,10 @@ test('related posts, author page and widgets use their dedicated renderers', () test('AJAX pagination can recover, caps auto loading and rehydrates appended media', () => { const php = read('inc/helpers/template-tags/pagination-permissions.php'); + const homepage = read('inc/helpers/homepage/content.php'); const admin = read('src/Admin/Admin.php'); const js = read('assets/js/core/pagination.js'); + const ajaxList = read('assets/js/core/ajax-list.js'); const media = read('assets/js/core/misc.js'); assert.match(php, /class="text-center theme-pagination ajax-pag"/); @@ -226,6 +246,9 @@ test('AJAX pagination can recover, caps auto loading and rehydrates appended med assert.match(js, /successfulAutoLoads >= iasMax/); assert.match(js, /AksrtFrontend\.rehydrate\(target, "ajax"\)/); assert.match(js, /classList\.add\("lazyload"\)/); + assert.match(homepage, /aksrt_render_pagination\(\$query,[\s\S]*?'query_context'\s*=>\s*\$contract\['query_context'\]/); + assert.doesNotMatch(homepage, /href="javascript:;" class="ajax-next aksrt-load-more-btn"/); + assert.match(ajaxList, /if \(link\.closest\("\[data-aksrt-pagination\], \.aksrt-comment-pagination"\)\) return;/); assert.match(media, /thumb-dplayer-playing/); assert.match(media, /data-post-thumb-slider/); assert.match(media, /data-post-thumb-video/);