Skip to content

Fix: CSS/JS Minification Bugs, PJAX Gutenberg Style Loss, and Comment UI Errors#1360

Draft
DazaiYuki wants to merge 6 commits intomirai-mamori:mainfrom
DazaiYuki:main
Draft

Fix: CSS/JS Minification Bugs, PJAX Gutenberg Style Loss, and Comment UI Errors#1360
DazaiYuki wants to merge 6 commits intomirai-mamori:mainfrom
DazaiYuki:main

Conversation

@DazaiYuki
Copy link
Contributor

概述

WP6.8、6.9的部分特性产生了新的问题,修复 WP-Optimize 插件开启 CSS/JS 压缩时导致F12报错和样式异常的问题,同时解决 PJAX 导航后 Gutenberg 区块样式丢失的问题。修复已登录评论区的样式错误

问题描述

  1. WP-Optimize 兼容性问题: 开启压缩后 Loading chunk 900 failed 错误导致主题报错
  2. PJAX + Gutenberg 区块样式问题: PJAX 导航后图片居中失效、Gallery 布局错乱,需 F5 刷新恢复
    3.已登录时评论区错位:
    修复前:
3153cb47f6b157ede02635cf484666c4 修复后: 9a7df0025cd89e4bc5f763eb94772287

修改内容

1. Webpack Code Splitting 兼容性 (functions.php)

  • 添加 wp-optimize-minify-default-exclusions 过滤器
  • 添加 wpo_minify_run_on_js 过滤器
  • 排除 app.jspage.jsapp-page.js 的压缩处理
  • 原因: 这些脚本使用 Webpack 动态加载,压缩后路径变更会导致 chunk 文件 404

2. PJAX + Gutenberg Block Styles 兼容性 (functions.php)

  • 添加 should_load_separate_core_block_assets 过滤器,返回 false
  • 原因: WordPress 5.8+ 按需加载区块样式,但 PJAX 只替换内容区域,不替换 <head> 样式标签
  • 效果: 所有区块样式在初始加载时全部加载,PJAX 导航后样式不再丢失

3. Polyfills defer 属性修复 (functions.php)

  • 添加 strpos($tag, 'defer') === false 检查
  • 避免重复添加 defer 属性

4. 主题设置说明优化 (opt/options/theme-options.php)

  • 更新 PJAX 设置的 label,说明会自动预加载 Gutenberg 区块样式
  • 为分页模式添加 desc 说明 AJAX 加载和传统分页的区别

5. 多语言翻译更新 (opt/languages/)

  • 更新 zh_CN.pozh_TW.poja.po 中的对应翻译
  • 重新编译 .mo 文件

测试验证

  • WP-Optimize 开启 CSS/JS 压缩后主题正常运行
  • PJAX 导航后 Gutenberg 区块(Image、Gallery 等)样式正常
  • 主题设置页面翻译正常显示

备注

  • 禁用 "Separate Core Block Assets" 会轻微增加初始 CSS 体积(约几 KB)
  • 如需使用 WP-Optimize 压缩 JS,请确保排除列表包含 app.js 和 page.js

DazaiYuki and others added 4 commits June 9, 2025 16:06
Fixed the data type mismatch issue in `get_post_views()` by converting the view count to an integer. This ensures compatibility with `number_format()`, preventing errors.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses compatibility issues with WordPress 6.8/6.9 features by fixing CSS/JS minification conflicts with WP-Optimize plugin, resolving PJAX-induced Gutenberg block style loss, and correcting logged-in user comment UI layout problems.

Key Changes

  • Added WP-Optimize plugin exclusion filters to prevent minification of Webpack code-split scripts (app.js, page.js, app-page.js)
  • Disabled WordPress separate core block assets loading to ensure PJAX compatibility with Gutenberg blocks
  • Refactored comment form HTML structure to properly separate logged-in and non-logged-in user layouts

Reviewed changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
functions.php Added WP-Optimize compatibility filters, disabled separate block assets loading, improved post views tracking with cookie-based deduplication, and added AJAX endpoint for batch view queries
style.css Enhanced animations with GPU acceleration, added skeleton loading effects, fixed comment UI spacing for logged-in users, and improved content-visibility optimizations
comments.php Restructured comment form to conditionally render different layouts for logged-in vs non-logged-in users, moved captcha logic to only show for guests
opt/options/theme-options.php Updated PJAX and pagination mode descriptions to clarify automatic Gutenberg block style preloading
opt/languages/*.po Updated translations across Chinese, Japanese, and POT files to reflect new option descriptions
css/responsive.css Added mobile-specific fixes for navigation touch events, comment layout adjustments, and GPU acceleration for animations
css/dark.css Added dark mode variant of skeleton loading effect
css/animation.css Added skeleton-loading keyframe animation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

comments.php Outdated
Comment on lines 152 to 154
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using var keyword for variable declarations is outdated JavaScript. The captcha-related variables on lines 152-154 use var which has function scope and can lead to hoisting issues. Modern JavaScript should use let or const for block-scoped variables to avoid potential bugs.

Suggested change
var captchaHideTimeout = null;
var captchaField = document.getElementById("captcha");
var captchaImg = document.getElementById("captchaimg");
let captchaHideTimeout = null;
const captchaField = document.getElementById("captcha");
const captchaImg = document.getElementById("captchaimg");

Copilot uses AI. Check for mistakes.
style.css Outdated
Comment on lines 213 to 215
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The animation timing changes on lines 213-215 add both animation-delay and animation-fill-mode: both, but there's no corresponding change to ensure the element remains hidden during the delay period. Without an explicit opacity: 0 or visibility: hidden in the base .post-list-thumb state, the element may be visible for 0.3s before the animation starts, causing a flash of unstyled content.

Copilot uses AI. Check for mistakes.
style.css Outdated
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CSS property content-visibility: hidden on line 202 is non-standard and may not work as intended. The valid values for content-visibility are visible, auto, and hidden was removed from the spec. This line appears to be trying to hide content but should use visibility: hidden or display: none instead for reliable cross-browser behavior.

Suggested change
content-visibility: hidden;
visibility: hidden;

Copilot uses AI. Check for mistakes.
functions.php Outdated
Comment on lines 569 to 571
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The defer attribute addition check has a logic issue. The condition strpos($tag, 'defer') === false will return false when 'defer' is found at position 0, which could lead to duplicate defer attributes being added. Use !== false or >= 0 for the positive case instead.

Copilot uses AI. Check for mistakes.
Comment on lines +849 to +864
// Cookie 防刷:每篇文章使用独立的 cookie,24小时内只能 +1
$cookie_name = 'iro_viewed_' . $post_id;

// 如果已有该文章的 cookie,说明24小时内已访问过,不再增加
if (isset($_COOKIE[$cookie_name]))
return;

// 增加浏览量
$views = (int) get_post_meta($post_id, 'views', true);
if (!update_post_meta($post_id, 'views', ($views + 1))) {
add_post_meta($post_id, 'views', 1, true);
}

// 设置 cookie,24小时后过期
// 注意:此时可能已经有输出,所以用 $_COOKIE 模拟(当前请求生效)+ setcookie(后续请求生效)
$_COOKIE[$cookie_name] = '1';
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cookie-based view prevention logic has a security concern. The code sets $_COOKIE[$cookie_name] = '1' on line 864, which simulates a cookie for the current request but doesn't actually prevent double-counting if setcookie() fails (due to headers already sent). Additionally, there's no CSRF protection - malicious scripts could make requests to increment view counts. Consider using a nonce or referer check.

Suggested change
// Cookie 防刷:每篇文章使用独立的 cookie,24小时内只能 +1
$cookie_name = 'iro_viewed_' . $post_id;
// 如果已有该文章的 cookie,说明24小时内已访问过,不再增加
if (isset($_COOKIE[$cookie_name]))
return;
// 增加浏览量
$views = (int) get_post_meta($post_id, 'views', true);
if (!update_post_meta($post_id, 'views', ($views + 1))) {
add_post_meta($post_id, 'views', 1, true);
}
// 设置 cookie,24小时后过期
// 注意:此时可能已经有输出,所以用 $_COOKIE 模拟(当前请求生效)+ setcookie(后续请求生效)
$_COOKIE[$cookie_name] = '1';
// 仅统计 GET 请求,避免 POST 等非正常访问方式刷量
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
return;
}
// 简单的来源检查:如果有 Referer,则要求与当前主机名相同,减少跨站刷量
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
if (!empty($referer)) {
$referer_host = parse_url($referer, PHP_URL_HOST);
$current_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
if (!empty($referer_host) && !empty($current_host) && strcasecmp($referer_host, $current_host) !== 0) {
return;
}
}
// Cookie 防刷:每篇文章使用独立的 cookie,24小时内只能 +1
$cookie_name = 'iro_viewed_' . $post_id;
// 如果已有该文章的 cookie,说明24小时内已访问过,不再增加
if (isset($_COOKIE[$cookie_name]))
return;
// 增加浏览量
$views = (int) get_post_meta($post_id, 'views', true);
if (!update_post_meta($post_id, 'views', ($views + 1))) {
add_post_meta($post_id, 'views', 1, true);
}
// 设置 cookie,24小时后过期

Copilot uses AI. Check for mistakes.
Comment on lines 895 to 904
function iro_ajax_get_post_views() {
// 获取文章 ID 列表
$post_ids = isset($_GET['ids']) ? $_GET['ids'] : '';
if (empty($post_ids)) {
wp_send_json_error('No post IDs provided');
}

// 解析 ID 列表(逗号分隔)
$ids = array_map('intval', explode(',', $post_ids));
$ids = array_filter($ids); // 移除无效 ID
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AJAX endpoint iro_ajax_get_post_views lacks input sanitization. While intval() is used on line 903, the initial $_GET['ids'] value should be sanitized before the explode operation to prevent potential injection issues. Use sanitize_text_field() on the input string before processing.

Copilot uses AI. Check for mistakes.
@Shiroiame-Kusu
Copy link
Collaborator

rebase到3.1分支宝宝,我们最近在合预览版pr

@Shiroiame-Kusu Shiroiame-Kusu self-assigned this Jan 3, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 17 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +855 to +862
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
if (!empty($referer)) {
$referer_host = parse_url($referer, PHP_URL_HOST);
$current_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
if (!empty($referer_host) && !empty($current_host) && strcasecmp($referer_host, $current_host) !== 0) {
return;
}
}
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referer host comparison logic has a potential issue. When the referer is from the same host, the function returns early without counting the view. This appears to be inverted logic - you likely want to allow same-host requests and block different-host requests. The condition should be changed to allow counting when hosts match or when there's no referer (direct visits).

Copilot uses AI. Check for mistakes.
Comment on lines +910 to +935
function iro_ajax_get_post_views() {
// 获取文章 ID 列表,使用 sanitize_text_field 清理输入
$post_ids = isset($_GET['ids']) ? sanitize_text_field($_GET['ids']) : '';
if (empty($post_ids)) {
wp_send_json_error('No post IDs provided');
}

// 解析 ID 列表(逗号分隔)
$ids = array_map('intval', explode(',', $post_ids));
$ids = array_filter($ids); // 移除无效 ID

// 限制最多查询 50 篇文章,防止滥用
$ids = array_slice($ids, 0, 50);

$result = array();
foreach ($ids as $id) {
$views = get_post_views($id);
$result[$id] = $views;
}

// 设置短缓存头(1分钟),减轻服务器压力
header('Cache-Control: public, max-age=60');
wp_send_json_success($result);
}
add_action('wp_ajax_iro_get_views', 'iro_ajax_get_post_views');
add_action('wp_ajax_nopriv_iro_get_views', 'iro_ajax_get_post_views');
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AJAX endpoint 'iro_ajax_get_post_views' lacks nonce verification, making it vulnerable to CSRF attacks. While it's a read-only operation, adding nonce validation would follow WordPress security best practices. Consider adding check_ajax_referer() at the beginning of the function.

Copilot uses AI. Check for mistakes.
Comment on lines +938 to +978
function iro_ajax_increment_views() {
// 仅接受 POST 请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
wp_send_json_error('Invalid request method');
}

$post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
if (!$post_id || !get_post($post_id)) {
wp_send_json_error('Invalid post ID');
}

// 排除管理员和编辑
if (current_user_can('edit_posts')) {
$views = get_post_views($post_id);
wp_send_json_success(array('views' => $views, 'incremented' => false));
}

// Cookie 防刷
$cookie_name = 'iro_viewed_' . $post_id;
if (isset($_COOKIE[$cookie_name])) {
$views = get_post_views($post_id);
wp_send_json_success(array('views' => $views, 'incremented' => false));
}

// 增加浏览量
$views = (int) get_post_meta($post_id, 'views', true);
$new_views = $views + 1;
if (!update_post_meta($post_id, 'views', $new_views)) {
add_post_meta($post_id, 'views', 1, true);
$new_views = 1;
}

// 设置 cookie
setcookie($cookie_name, '1', time() + 86400, '/');

// 格式化输出
$formatted_views = restyle_text($new_views);
wp_send_json_success(array('views' => $formatted_views, 'incremented' => true));
}
add_action('wp_ajax_iro_increment_views', 'iro_ajax_increment_views');
add_action('wp_ajax_nopriv_iro_increment_views', 'iro_ajax_increment_views');
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AJAX endpoint 'iro_ajax_increment_views' lacks nonce verification for CSRF protection. Since this endpoint modifies data (increments view count), it should validate a nonce token. Add check_ajax_referer() with an appropriate action name to prevent unauthorized requests from incrementing view counts.

Copilot uses AI. Check for mistakes.
Comment on lines +217 to +261
<script>
(function() {
'use strict';

function incrementAndUpdateViews() {
if (typeof _iro === 'undefined' || !_iro.ajax_url) return;

// 从 DOM 获取 post ID(支持 PJAX)
var viewsElement = document.querySelector('.post-views-count[data-post-id]');
if (!viewsElement) return;

var postId = viewsElement.getAttribute('data-post-id');
if (!postId || postId === '0') return;

var xhr = new XMLHttpRequest();
xhr.open('POST', _iro.ajax_url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var response = JSON.parse(xhr.responseText);
if (response.success && response.data) {
viewsElement.textContent = response.data.views + ' Views';
// 简单的高亮动画
viewsElement.classList.remove('views-updated');
void viewsElement.offsetWidth;
viewsElement.classList.add('views-updated');
}
} catch (e) {}
}
};
xhr.send('action=iro_increment_views&post_id=' + postId);
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', incrementAndUpdateViews);
} else {
incrementAndUpdateViews();
}

document.addEventListener('pjax:complete', function() {
setTimeout(incrementAndUpdateViews, 100);
});
})();
</script>
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inline JavaScript for view counting should be wrapped in a DOMContentLoaded check or moved to an external file for better Content Security Policy (CSP) compliance. Additionally, the AJAX request doesn't include any nonce for CSRF protection, which should match the security token expected by the 'iro_ajax_increment_views' endpoint.

Copilot uses AI. Check for mistakes.
Comment on lines +152 to +180
(function() {
var captchaHideTimeout = null;
var captchaField = document.getElementById("captcha");
var captchaImg = document.getElementById("captchaimg");
window.showCaptcha = function() {
captchaField.setAttribute("placeholder", "");
if (captchaHideTimeout) { clearTimeout(captchaHideTimeout); captchaHideTimeout = null; }
captchaImg.style.width = "120px";
captchaImg.style.marginRight = "10px";
};
window.hideCaptcha = function() {
captchaHideTimeout = setTimeout(function() {
captchaImg.style.width = "0";
captchaImg.style.marginRight = "0";
captchaField.setAttribute("placeholder", "'. $captcha_placeholder .'");
}, 5000);
};
window.refreshCaptcha = function() {
fetch(_iro.captcha_endpoint)
.then(function(resp) { return resp.json(); })
.then(function(json) {
captchaImg.src = json["data"];
document.querySelector("input[name=\'timestamp\']").value = json["time"];
document.querySelector("input[name=\'id\']").value = json["id"];
})
.catch(function(error) { console.error("获取验证码失败:", error); });
};
})();
</script>';
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The captcha JavaScript functions (showCaptcha, hideCaptcha, refreshCaptcha) are assigned to the global window object inside an IIFE. While this works, it creates global pollution. Consider using event delegation or data attributes instead, which would be more maintainable and avoid the need for global functions that are called via inline event handlers (onclick, onfocus, onblur).

Copilot uses AI. Check for mistakes.
@Shiroiame-Kusu Shiroiame-Kusu marked this pull request as draft January 15, 2026 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments