进行了一些小修复

This commit is contained in:
2026-08-26 13:54:49 +08:00
parent ed1a47cf4e
commit d4b7ec1deb
9 changed files with 1763 additions and 80 deletions
+45
View File
@@ -0,0 +1,45 @@
/* source: assets/css/frontend/comments/shell.css */
/* ============================================================
* AKSRT Comments — 补充层
*
* 评论区的全部样式以 vendor 的 legacy 正版样式为准:
* assets/css/main.min.css(含 #comments/#postcomments
* 桌面规则与移动端媒体查询:.mobile-fixed/.virtual-input/.pagenav/
* .tab-nav-theme/.dropdown-menu/.line-form/.placeholder 等)
* + bootstrap 3(.list-unstyled/.list-inline)
*
* 本文件只补 AKSRT 特有标记的样式,禁止复制 legacy 规则——
* 带 #comments id 前缀的副本会覆盖 vendor 正版样式造成 UI 偏差。
* ============================================================ */
/* 身份徽章(AKSRT 渲染于 <name> 内,对应 legacy 的认证/等级徽章位) */
#comments .comment-header .aksrt-identity-chip {
display: inline-flex;
align-items: center;
gap: 3px;
vertical-align: middle;
max-width: 9em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 11px;
}
#comments .comment-header .aksrt-identity-medal {
display: inline-block;
width: auto;
height: 1.1em;
max-width: 6em;
object-fit: contain;
vertical-align: -0.15em;
}
/* source: assets/css/frontend/comments/mobile-item.css */
/* ============================================================
* AKSRT Comments 移动端 — 补充层
*
* 移动端评论样式(.mobile-fixed 弹层、.virtual-input 假输入、
* 头像/缩进/分页的移动端覆盖)全部由 vendor main.min.css 的
* @media (max-width:767px) 提供,此处不复制,避免覆盖正版样式。
* 目前无补充规则,保留文件以维持 enqueue 句柄链。
* ============================================================ */
+1
View File
@@ -0,0 +1 @@
#comments .comment-header .aksrt-identity-chip{display:inline-flex;align-items:center;gap:3px;vertical-align:middle;max-width:9em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}#comments .comment-header .aksrt-identity-medal{display:inline-block;width:auto;height:1.1em;max-width:6em;object-fit:contain;vertical-align:-.15em}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+104 -67
View File
@@ -111,18 +111,6 @@ trait ScriptsPart1b {
}
}
// Print stylesheet — only load on singular pages
if (is_singular()) {
wp_enqueue_style(
'aksrt-print',
$base_uri . '/assets/css/frontend/print.css',
[],
$version,
'print'
);
}
// 4b. 路由判定
$is_home_or_archive = is_home() || is_front_page() || is_archive() || is_search();
// 资源单页(post + _aksrt_is_resource)
@@ -166,6 +154,23 @@ trait ScriptsPart1b {
// CMS route detection.
$is_cms_mode = function_exists('aksrt_is_cms_mode') ? aksrt_is_cms_mode() : false;
$singular_assets = $this->resolve_singular_asset_requirements(
$is_single_post,
$is_single_resource,
$is_paid_content_single
);
if (!empty($singular_assets['needs_print'])) {
$print_path = get_template_directory() . '/assets/css/frontend/print.css';
wp_enqueue_style(
'aksrt-print',
$base_uri . '/assets/css/frontend/print.css',
[],
file_exists($print_path) ? (string) filemtime($print_path) : $version,
'print'
);
}
// 首页/归档/搜索:卡片 + 侧栏
if ($is_home_or_archive && !$is_fixed_homepage) {
$enqueue_module('post-card');
@@ -173,55 +178,78 @@ trait ScriptsPart1b {
$enqueue_module('breadcrumb');
}
// 单篇文章:所有 single 相关样式
if ($is_single_post) {
// Prefer discrete enqueues over CSS @import (cache-bust + parallel load).
$single_parts = [
'legacy-utilities',
'single-post/shell',
'single-post/content',
'single-post/code-blocks',
'single-post/navigation',
'single-post/cover',
'single-post/author-actions',
'single-post/related-toc',
'single-post/hidden-content',
];
$single_dep = $deps[0] ?? $core_dep;
foreach ($single_parts as $part) {
$path = get_template_directory() . '/assets/css/frontend/' . $part . '.css';
if (!file_exists($path)) {
continue;
}
wp_enqueue_style(
'aksrt-' . str_replace('/', '-', $part),
$base_uri . '/assets/css/frontend/' . $part . '.css',
is_string($single_dep) ? [$single_dep] : (array) $deps,
filemtime($path) ?: $version
);
}
// Keep aggregator handle for any third-party deps that target it.
$enqueue_module('single-post');
$enqueue_module('post-card'); // 相关推荐使用 post-card 局部样式
// Comments pack (legacy 1:1 discrete files).
$comment_parts = ['comments/shell', 'comments/mobile-item'];
$comment_dep = $deps[0] ?? $core_dep;
foreach ($comment_parts as $part) {
$path = get_template_directory() . '/assets/css/frontend/' . $part . '.css';
if (!file_exists($path)) {
continue;
}
wp_enqueue_style(
'aksrt-' . str_replace('/', '-', $part),
$base_uri . '/assets/css/frontend/' . $part . '.css',
is_string($comment_dep) ? [$comment_dep] : (array) $deps,
filemtime($path) ?: $version
);
}
$enqueue_module('comments'); // aggregator handle for third-party deps
$enqueue_module('sidebar');
$enqueue_module('breadcrumb');
}
// Normal articles: one small core bundle plus content/settings-driven feature leaves.
if ($is_single_post && !empty($singular_assets['is_article'])) {
$single_filename = file_exists(get_template_directory() . '/assets/css/build/single.min.css')
? 'single.min.css'
: 'single.css';
$single_path = get_template_directory() . '/assets/css/build/' . $single_filename;
wp_enqueue_style(
'aksrt-single-core',
$base_uri . '/assets/css/build/' . $single_filename,
[$core_dep],
file_exists($single_path) ? (string) filemtime($single_path) : $version
);
$single_features = [
'has_code' => 'single-post/code-blocks',
'needs_navigation' => 'single-post/navigation',
'needs_cover' => 'single-post/cover',
'needs_related_toc' => 'single-post/related-toc',
'has_hidden_content' => 'single-post/hidden-content',
];
$single_feature_handles = [];
foreach ($single_features as $requirement => $part) {
if (empty($singular_assets[$requirement])) {
continue;
}
$path = get_template_directory() . '/assets/css/frontend/' . $part . '.css';
if (!file_exists($path)) {
continue;
}
$handle = 'aksrt-' . str_replace('/', '-', $part);
wp_enqueue_style(
$handle,
$base_uri . '/assets/css/frontend/' . $part . '.css',
['aksrt-single-core'],
(string) filemtime($path)
);
$single_feature_handles[] = $handle;
}
// Preserve the public aggregate handle without requesting its @import file.
wp_register_style(
'aksrt-single-post',
false,
array_merge(['aksrt-single-core'], $single_feature_handles),
$version
);
wp_enqueue_style('aksrt-single-post');
if (!empty($singular_assets['needs_post_card'])) {
$enqueue_module('post-card');
}
if (!empty($singular_assets['needs_comments'])) {
$comments_filename = file_exists(get_template_directory() . '/assets/css/build/comments.min.css')
? 'comments.min.css'
: 'comments.css';
$comments_path = get_template_directory() . '/assets/css/build/' . $comments_filename;
wp_enqueue_style(
'aksrt-comments',
$base_uri . '/assets/css/build/' . $comments_filename,
['aksrt-single-post'],
file_exists($comments_path) ? (string) filemtime($comments_path) : $version
);
}
if (!empty($singular_assets['needs_sidebar'])) {
$enqueue_module('sidebar');
}
if (!empty($singular_assets['needs_breadcrumb'])) {
$enqueue_module('breadcrumb');
}
}
// 静态页面 + 用户中心 + 友链等
if ($is_static_page) {
@@ -516,9 +544,8 @@ trait ScriptsPart1b {
}
}
// Unified share-data builder — single payload assembler for every share
// surface (dropdown, copy, WeChat, poster). Loaded on any singular view.
if (is_singular()) {
// Unified share-data builder — only when the article renders share controls.
if (!empty($singular_assets['needs_share'])) {
$share_data_js = get_template_directory() . '/assets/js/share-data-builder.js';
if (file_exists($share_data_js)) {
wp_enqueue_script(
@@ -531,8 +558,8 @@ trait ScriptsPart1b {
}
}
// 单篇文章 — poster-share.js(海报分享按钮)
if (is_singular('post')) {
// Poster generation is part of the article share dropdown.
if (!empty($singular_assets['needs_share'])) {
$poster_js = get_template_directory() . '/assets/js/poster-share.js';
if (file_exists($poster_js)) {
wp_enqueue_script(
@@ -650,7 +677,17 @@ trait ScriptsPart1b {
}
}
$this->enqueue_public_fonts_js_and_data($base_uri, $core_dep, $deps, $is_fixed_homepage, $is_home_or_archive, $is_single_post, $is_single_resource, $version);
$this->enqueue_public_fonts_js_and_data(
$base_uri,
$core_dep,
$deps,
$is_fixed_homepage,
$is_home_or_archive,
$is_single_post,
$is_single_resource,
$version,
$singular_assets
);
}
}
+137 -12
View File
@@ -16,10 +16,136 @@ defined('ABSPATH') || exit;
*/
trait ScriptsPart1c {
/**
* Resolve the assets required by the current singular response.
*
* @return array<string,bool>
*/
private function resolve_singular_asset_requirements(bool $is_single_post, bool $is_single_resource, bool $is_paid_content_single): array {
$requirements = [
'is_article' => false,
'has_code' => false,
'has_toc' => false,
'has_video' => false,
'has_hidden_content' => false,
'needs_cover' => false,
'needs_navigation' => false,
'needs_related_toc' => false,
'needs_post_card' => false,
'needs_sidebar' => false,
'needs_breadcrumb' => false,
'needs_comments' => false,
'needs_comment_tools' => false,
'needs_page_template' => false,
'needs_reward' => false,
'needs_yiyan' => false,
'needs_share' => false,
'needs_print' => false,
];
if (!is_singular()) {
return $requirements;
}
$post_id = (int) get_queried_object_id();
$post = $post_id > 0 ? get_post($post_id) : null;
if (!$post instanceof \WP_Post) {
return $requirements;
}
$is_docs_article = $is_single_post
&& function_exists('aksrt_single_is_docs_page')
&& aksrt_single_is_docs_page($post_id);
$is_article = ($is_single_post || $is_single_resource) && !$is_docs_article;
$settings = function_exists('aksrt_resolve_single_post_display_settings')
? aksrt_resolve_single_post_display_settings($post_id)
: [];
$content = (string) $post->post_content;
$display_content = $content
. (string) ($settings['front_content'] ?? '')
. (string) ($settings['after_content'] ?? '');
$has_code = (bool) preg_match(
'/(?:<!--\s*wp:(?:code|preformatted|aksrt\/enlighter)\b|<pre\b|data-enlighter-language)/i',
$display_content
);
$heading_count = preg_match_all('/<h[1-4]\b/i', $display_content);
$has_hidden_content = $is_paid_content_single || (bool) preg_match(
'/(?:<!--\s*wp:aksrt\/paid-fragment\b|\[(?:aksrt_hide|hide|reply|vip|payshow|hidecontent|content)\b|aksrt-(?:hidden-content|paywall))/i',
$content
);
$comment_settings = class_exists('\\AKSRT\\Settings\\Settings')
? \AKSRT\Settings\Settings::get_comment_display_settings()
: [];
$comments_disabled = $is_docs_article
|| post_password_required($post_id)
|| !empty($comment_settings['close_comments']);
$comments_are_open = !$comments_disabled && comments_open($post_id);
$has_comments = !$comments_disabled && (
$comments_are_open
|| (int) get_comments_number($post_id) > 0
);
$can_use_comment_form = $comments_are_open && (
empty($comment_settings['require_login'])
|| is_user_logged_in()
);
$show_cover = !empty($settings['show_cover']) && (string) ($settings['cover_url'] ?? '') !== '';
$has_video = $is_article && (
($show_cover && (string) ($settings['cover_type'] ?? '') === 'video')
|| str_contains($content, 'data-aksrt-video')
);
$has_yiyan = $is_article && (
!empty($settings['yiyan_header'])
|| !empty($settings['yiyan_footer'])
|| !empty($settings['yiyan_box'])
);
$has_inserted_content = trim((string) ($settings['front_content'] ?? '')) !== ''
|| trim((string) ($settings['after_content'] ?? '')) !== '';
$has_page_break = (bool) preg_match('/<!--\s*nextpage\s*-->/i', $content);
$has_related = $is_article && !empty($settings['related_enabled']);
$layout = function_exists('aksrt_get_post_show_layout')
? (string) aksrt_get_post_show_layout($post_id)
: '';
$requirements['is_article'] = $is_article;
$requirements['has_code'] = $has_code;
$requirements['has_toc'] = $is_article && $heading_count >= 2;
$requirements['has_video'] = $has_video;
$requirements['has_hidden_content'] = $has_hidden_content || $has_yiyan || $has_inserted_content;
$requirements['needs_cover'] = $is_article && (
$show_cover
|| !empty($settings['breadcrumbs'])
|| $is_paid_content_single
);
$requirements['needs_navigation'] = $is_article && $has_page_break;
$requirements['needs_related_toc'] = $is_article && (
!empty($settings['reading_progress'])
|| !empty($settings['maxheight_enabled'])
|| !empty($settings['prevnext'])
|| $has_related
);
$requirements['needs_post_card'] = $has_related;
$requirements['needs_sidebar'] = $is_article
&& get_post_type($post_id) === 'post'
&& $layout !== 'no_sidebar'
&& function_exists('aksrt_is_show_sidebar')
&& aksrt_is_show_sidebar();
$requirements['needs_breadcrumb'] = $is_article && !empty($settings['breadcrumbs']);
$requirements['needs_comments'] = $has_comments;
$requirements['needs_comment_tools'] = $can_use_comment_form;
$requirements['needs_page_template'] = !empty($settings['lightbox']) || !empty($settings['maxheight_enabled']);
$requirements['needs_reward'] = $is_article && !empty($settings['rewards_enabled']);
$requirements['needs_yiyan'] = $has_yiyan;
$requirements['needs_share'] = $is_article && !empty($settings['share_enabled']);
$requirements['needs_print'] = !empty($settings['print_enabled']);
return $requirements;
}
/**
* Fonts / FA / global JS stack / aksrtData (split from enqueue_public).
*/
private function enqueue_public_fonts_js_and_data($base_uri, $core_dep, $deps, $is_fixed_homepage, $is_home_or_archive, $is_single_post, $is_single_resource, $version): void {
private function enqueue_public_fonts_js_and_data($base_uri, $core_dep, $deps, $is_fixed_homepage, $is_home_or_archive, $is_single_post, $is_single_resource, $version, array $singular_assets): void {
$runtime_uri = $base_uri . '/assets';
$runtime_main_path = get_template_directory() . '/assets/js/runtime/main.min.js';
$runtime_version = file_exists($runtime_main_path) ? (string) filemtime($runtime_main_path) : $version;
@@ -96,7 +222,7 @@ trait ScriptsPart1c {
// Code block enhancements (copy button + language label)
$precode_js = get_template_directory() . '/assets/js/precode.js';
if (is_singular() && file_exists($precode_js)) {
if (!empty($singular_assets['has_code']) && file_exists($precode_js)) {
wp_enqueue_script(
'aksrt-precode',
$base_uri . '/assets/js/precode.js',
@@ -108,8 +234,7 @@ trait ScriptsPart1c {
// Input field enhancements (auto-resize, counter, validation)
$input_expand_js = get_template_directory() . '/assets/js/input-expand.js';
$needs_input_enhancements = is_singular()
|| (bool) get_query_var('aksrt_sign')
$needs_input_enhancements = (bool) get_query_var('aksrt_sign')
|| (bool) get_query_var('aksrt_user_center')
|| (bool) get_query_var('aksrt_author_identifier');
if ($needs_input_enhancements && file_exists($input_expand_js)) {
@@ -124,7 +249,7 @@ trait ScriptsPart1c {
// Section navs: article TOC / scrollspy
$section_navs_js = get_template_directory() . '/assets/js/section-navs.js';
if (is_singular() && file_exists($section_navs_js)) {
if (!empty($singular_assets['has_toc']) && file_exists($section_navs_js)) {
wp_enqueue_script(
'aksrt-section-navs',
$base_uri . '/assets/js/section-navs.js',
@@ -136,7 +261,7 @@ trait ScriptsPart1c {
// Video player (MP4/HLS/FLV)
$video_player_js = get_template_directory() . '/assets/js/video-player.js';
if (is_singular() && file_exists($video_player_js)) {
if (!empty($singular_assets['has_video']) && file_exists($video_player_js)) {
wp_enqueue_script(
'aksrt-video-player',
$base_uri . '/assets/js/video-player.js',
@@ -148,7 +273,7 @@ trait ScriptsPart1c {
// Reward (打赏)
$reward_js = get_template_directory() . '/assets/js/reward.js';
if (($is_single_post || $is_single_resource) && file_exists($reward_js)) {
if (!empty($singular_assets['needs_reward']) && file_exists($reward_js)) {
wp_enqueue_script(
'aksrt-reward',
$base_uri . '/assets/js/reward.js',
@@ -160,7 +285,7 @@ trait ScriptsPart1c {
// Yiyan (一言轮播)
$yiyan_js = get_template_directory() . '/assets/js/yiyan.js';
if (($is_single_post || $is_single_resource) && file_exists($yiyan_js)) {
if (!empty($singular_assets['needs_yiyan']) && file_exists($yiyan_js)) {
wp_enqueue_script(
'aksrt-yiyan',
$base_uri . '/assets/js/yiyan.js',
@@ -242,7 +367,7 @@ trait ScriptsPart1c {
// Comment toolbar (smilie/code/image/quick shortcodes) — post form.
$load_comment_tools = (is_singular() && comments_open());
$load_comment_tools = !empty($singular_assets['needs_comment_tools']);
if ($load_comment_tools) {
$comment_tools_path = get_template_directory() . '/assets/js/comment-tools.js';
wp_enqueue_script(
@@ -265,7 +390,7 @@ trait ScriptsPart1c {
// Comment actions client (like / edit / delete / moderate / pin).
// Submit path lives in assets/js/core/comments.js (REST).
if (is_singular() && (comments_open() || (int) get_comments_number() > 0)) {
if (!empty($singular_assets['needs_comments'])) {
$comment_ajax_path = get_template_directory() . '/assets/js/comment-ajax.js';
if (file_exists($comment_ajax_path)) {
wp_enqueue_script(
@@ -278,7 +403,7 @@ trait ScriptsPart1c {
}
}
if (is_singular()) {
if (!empty($singular_assets['needs_page_template'])) {
$page_template_path = get_template_directory() . '/assets/js/page-template.js';
if (file_exists($page_template_path)) {
wp_enqueue_script(
@@ -292,7 +417,7 @@ trait ScriptsPart1c {
}
// Post/resource share functionality
if ($is_single_post || $is_single_resource) {
if (!empty($singular_assets['needs_share'])) {
$weixin_share_path = get_template_directory() . '/assets/js/weixin-share.js';
if (file_exists($weixin_share_path)) {
wp_enqueue_script(
@@ -434,3 +434,62 @@ test('public user home stays param-free and swaps panels via REST fragments', ()
assert.match(authorJs, /data-uh-sub/);
assert.match(authorJs, /AksrtFrontend\.rehydrate\(panel, 'ajax'\)/);
});
test('single articles enqueue only content and settings driven assets', () => {
const enqueue = read('src/Core/ScriptsPart1b.php');
const runtime = read('src/Core/ScriptsPart1c.php');
const builder = read('tools/build-public-assets.mjs');
const singleStart = enqueue.indexOf('// Normal articles: one small core bundle');
const staticPageStart = enqueue.indexOf('// 静态页面 + 用户中心', singleStart);
const singleBlock = enqueue.slice(singleStart, staticPageStart);
assert.ok(singleStart >= 0 && staticPageStart > singleStart);
assert.match(builder, /'single\.css': \[[\s\S]*?single-post\/shell\.css'[\s\S]*?single-post\/content\.css'[\s\S]*?single-post\/author-actions\.css'/);
assert.match(builder, /'comments\.css': \[[\s\S]*?comments\/shell\.css'[\s\S]*?comments\/mobile-item\.css'/);
assert.match(singleBlock, /build\/single\.min\.css/);
assert.match(singleBlock, /wp_register_style\([\s\S]*?'aksrt-single-post'[\s\S]*?array_merge\(\['aksrt-single-core'\], \$single_feature_handles\)/);
assert.doesNotMatch(singleBlock, /\$enqueue_module\('single-post'\)|\$enqueue_module\('comments'\)/);
for (const requirement of [
'has_code',
'needs_navigation',
'needs_cover',
'needs_related_toc',
'has_hidden_content',
]) {
assert.match(singleBlock, new RegExp(`'${requirement}'\\s*=>`));
}
for (const requirement of [
'needs_post_card',
'needs_comments',
'needs_sidebar',
'needs_breadcrumb',
]) {
assert.match(singleBlock, new RegExp(`singular_assets\\['${requirement}'\\]`));
}
assert.match(runtime, /wp:\(\?:code\|preformatted\|aksrt\\\/enlighter\)/);
assert.match(runtime, /preg_match_all\('\/<h\[1-4\]/);
assert.match(runtime, /data-aksrt-video/);
assert.match(runtime, /post_password_required\(\$post_id\)/);
assert.match(runtime, /comment_settings\['close_comments'\]/);
assert.match(runtime, /comment_settings\['require_login'\]/);
assert.match(runtime, /needs_reward'[\s\S]*?rewards_enabled/);
assert.match(runtime, /needs_yiyan'[\s\S]*?yiyan_header/);
assert.match(runtime, /needs_share'[\s\S]*?share_enabled/);
for (const requirement of [
'has_code',
'has_toc',
'has_video',
'needs_reward',
'needs_yiyan',
'needs_comments',
'needs_comment_tools',
'needs_page_template',
'needs_share',
]) {
assert.match(runtime, new RegExp(`singular_assets\\['${requirement}'\\]`));
}
});
+1 -1
View File
@@ -439,7 +439,7 @@ test('public CSS bundles have parser-minified production variants', () => {
assert.match(builder, /loader: 'css'/);
assert.match(builder, /minify: true/);
for (const basename of ['public', 'homepage']) {
for (const basename of ['public', 'homepage', 'single', 'comments']) {
const readablePath = path.join(root, 'assets', 'css', 'build', `${basename}.css`);
const minifiedPath = path.join(root, 'assets', 'css', 'build', `${basename}.min.css`);
+10
View File
@@ -47,6 +47,16 @@ const cssBundles = {
'assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css',
'assets/css/frontend/homepage-fixed/ajax-tab-error-state.css',
],
'single.css': [
'assets/css/frontend/legacy-utilities.css',
'assets/css/frontend/single-post/shell.css',
'assets/css/frontend/single-post/content.css',
'assets/css/frontend/single-post/author-actions.css',
],
'comments.css': [
'assets/css/frontend/comments/shell.css',
'assets/css/frontend/comments/mobile-item.css',
],
};
const publicScripts = [