进行了一些小修复

This commit is contained in:
2026-08-26 19:51:31 +08:00
parent 02cbff1ddf
commit fbada8bd6a
20 changed files with 294 additions and 191 deletions
@@ -6,8 +6,6 @@ export const featureSchema = {
defaults: {
feature_pdf_export: false,
feature_print: true,
feature_word_count: true,
feature_reading_time: true,
},
groups: [
{
@@ -16,8 +14,6 @@ export const featureSchema = {
icon: 'fa fas fa-wrench',
fields: [
{ key: 'feature_print', label: '打印文章', type: 'switch', default: true },
{ key: 'feature_word_count', label: '字数统计', type: 'switch', default: true },
{ key: 'feature_reading_time', label: '预计阅读时间', type: 'switch', default: true },
{ key: 'feature_pdf_export', label: 'PDF 导出', type: 'switch', default: false, help: '实验性功能' },
],
},
+19 -18
View File
@@ -336,22 +336,6 @@ body.single main.container {
box-sizing: border-box;
}
/* Reading facts below the author row. */
.article-reading-meta {
display: flex;
flex-wrap: wrap;
gap: 8px 14px;
margin: 12px 0 2px;
color: var(--muted-color, #777);
font-size: 12px;
}
.article-reading-meta span {
display: inline-flex;
align-items: center;
gap: 5px;
}
/* source: assets/css/frontend/single-post/content.css */
/* ========== Single Post ========== */
@@ -1332,10 +1316,24 @@ html.dark .post-drop-meta__item:hover {
color: var(--key-color, #333);
}
.article-header .article-avatar .relative {
.article-header .article-avatar .single-meta-row {
margin-top: 20px;
position: relative;
min-height: 1px;
min-height: 28px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.article-header .article-avatar .single-meta-row > .line-form-line {
bottom: 50%;
}
.article-header .article-avatar .single-meta-row > .single-metabox {
position: relative;
inset: auto;
transform: none;
z-index: 1;
}
.single-metabox {
@@ -1368,6 +1366,9 @@ html.dark .post-drop-meta__item:hover {
.single-metabox .post-drop-meta {
position: relative;
display: inline-block;
--this-size: 1.73em;
--this-color: var(--meta-color);
--this-bg: var(--body-bg-color, #f5f5f5);
}
.single-metabox.cover-meta {
+1 -1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -91,6 +91,13 @@
border-top: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.08));
}
.newposts-editor .aksrt-submit-word-count {
float: right;
margin-right: 24px;
color: var(--muted-color, #777);
line-height: 24px;
}
.newposts-editor .mce-toolbar .mce-btn-group .mce-btn,
.newposts-editor .qt-dfw {
margin: 4px;
@@ -576,10 +576,24 @@ html.dark .post-drop-meta__item:hover {
color: var(--key-color, #333);
}
.article-header .article-avatar .relative {
.article-header .article-avatar .single-meta-row {
margin-top: 20px;
position: relative;
min-height: 1px;
min-height: 28px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.article-header .article-avatar .single-meta-row > .line-form-line {
bottom: 50%;
}
.article-header .article-avatar .single-meta-row > .single-metabox {
position: relative;
inset: auto;
transform: none;
z-index: 1;
}
.single-metabox {
@@ -612,6 +626,9 @@ html.dark .post-drop-meta__item:hover {
.single-metabox .post-drop-meta {
position: relative;
display: inline-block;
--this-size: 1.73em;
--this-color: var(--meta-color);
--this-bg: var(--body-bg-color, #f5f5f5);
}
.single-metabox.cover-meta {
-16
View File
@@ -34,19 +34,3 @@ body.single .sidebar .widget {
body.single main.container {
box-sizing: border-box;
}
/* Reading facts below the author row. */
.article-reading-meta {
display: flex;
flex-wrap: wrap;
gap: 8px 14px;
margin: 12px 0 2px;
color: var(--muted-color, #777);
font-size: 12px;
}
.article-reading-meta span {
display: inline-flex;
align-items: center;
gap: 5px;
}
+69
View File
@@ -1921,6 +1921,74 @@ tbquire.config({
});
}
var postMetaDocumentEventsBound = false;
function setPostMetaMenuState(menuRoot, open) {
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
var menu = menuRoot.querySelector(".post-drop-meta__menu");
if (!toggle || !menu) return;
menuRoot.classList.toggle("is-open", open);
toggle.setAttribute("aria-expanded", open ? "true" : "false");
menu.setAttribute("aria-hidden", open ? "false" : "true");
}
function closePostMetaMenus(except, restoreFocus) {
document.querySelectorAll(".post-drop-meta.is-open").forEach(function (menuRoot) {
if (menuRoot === except) return;
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
setPostMetaMenuState(menuRoot, false);
if (restoreFocus && toggle) toggle.focus();
});
}
function initPostMetaMenus(root) {
var scope = root || document;
var menuRoots = [];
if (scope.nodeType === 1 && scope.matches(".post-drop-meta")) {
menuRoots.push(scope);
}
scope.querySelectorAll(".post-drop-meta").forEach(function (menuRoot) {
menuRoots.push(menuRoot);
});
menuRoots.forEach(function (menuRoot) {
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
var menu = menuRoot.querySelector(".post-drop-meta__menu");
if (!toggle || !menu || toggle.dataset.postMetaMenuBound) return;
toggle.dataset.postMetaMenuBound = "1";
setPostMetaMenuState(menuRoot, false);
toggle.addEventListener("click", function () {
var open = !menuRoot.classList.contains("is-open");
closePostMetaMenus(menuRoot, false);
setPostMetaMenuState(menuRoot, open);
});
menu.addEventListener("click", function (event) {
if (event.target.closest(".post-drop-meta__item")) {
setPostMetaMenuState(menuRoot, false);
}
});
});
if (menuRoots.length && !postMetaDocumentEventsBound) {
postMetaDocumentEventsBound = true;
document.addEventListener("click", function (event) {
if (!event.target.closest(".post-drop-meta")) {
closePostMetaMenus(null, false);
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
closePostMetaMenus(null, true);
}
});
}
}
function getBaseStatCount(statName) {
var statEl = document.querySelector('[data-stat-count="' + statName + '"][data-base-count]');
return statEl ? (parseInt(statEl.dataset.baseCount, 10) || 0) : 0;
@@ -2104,6 +2172,7 @@ tbquire.config({
window.AksrtFrontend.register("aksrt-search-clear", function () { initSearchClear(); });
window.AksrtFrontend.register("aksrt-article-tools", function () { initArticleTools(); });
window.AksrtFrontend.register("aksrt-post-meta-menus", function (root) { initPostMetaMenus(root); });
window.AksrtFrontend.register("aksrt-password-toggles", function (root) { initPasswordToggles(root); });
window.AksrtFrontend.register("aksrt-interaction-bar", function (root) { initInteractionBar(root); });
})();
+69
View File
@@ -78,6 +78,74 @@
});
}
var postMetaDocumentEventsBound = false;
function setPostMetaMenuState(menuRoot, open) {
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
var menu = menuRoot.querySelector(".post-drop-meta__menu");
if (!toggle || !menu) return;
menuRoot.classList.toggle("is-open", open);
toggle.setAttribute("aria-expanded", open ? "true" : "false");
menu.setAttribute("aria-hidden", open ? "false" : "true");
}
function closePostMetaMenus(except, restoreFocus) {
document.querySelectorAll(".post-drop-meta.is-open").forEach(function (menuRoot) {
if (menuRoot === except) return;
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
setPostMetaMenuState(menuRoot, false);
if (restoreFocus && toggle) toggle.focus();
});
}
function initPostMetaMenus(root) {
var scope = root || document;
var menuRoots = [];
if (scope.nodeType === 1 && scope.matches(".post-drop-meta")) {
menuRoots.push(scope);
}
scope.querySelectorAll(".post-drop-meta").forEach(function (menuRoot) {
menuRoots.push(menuRoot);
});
menuRoots.forEach(function (menuRoot) {
var toggle = menuRoot.querySelector(".post-drop-meta__toggle");
var menu = menuRoot.querySelector(".post-drop-meta__menu");
if (!toggle || !menu || toggle.dataset.postMetaMenuBound) return;
toggle.dataset.postMetaMenuBound = "1";
setPostMetaMenuState(menuRoot, false);
toggle.addEventListener("click", function () {
var open = !menuRoot.classList.contains("is-open");
closePostMetaMenus(menuRoot, false);
setPostMetaMenuState(menuRoot, open);
});
menu.addEventListener("click", function (event) {
if (event.target.closest(".post-drop-meta__item")) {
setPostMetaMenuState(menuRoot, false);
}
});
});
if (menuRoots.length && !postMetaDocumentEventsBound) {
postMetaDocumentEventsBound = true;
document.addEventListener("click", function (event) {
if (!event.target.closest(".post-drop-meta")) {
closePostMetaMenus(null, false);
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
closePostMetaMenus(null, true);
}
});
}
}
function getBaseStatCount(statName) {
var statEl = document.querySelector('[data-stat-count="' + statName + '"][data-base-count]');
return statEl ? (parseInt(statEl.dataset.baseCount, 10) || 0) : 0;
@@ -261,6 +329,7 @@
window.AksrtFrontend.register("aksrt-search-clear", function () { initSearchClear(); });
window.AksrtFrontend.register("aksrt-article-tools", function () { initArticleTools(); });
window.AksrtFrontend.register("aksrt-post-meta-menus", function (root) { initPostMetaMenus(root); });
window.AksrtFrontend.register("aksrt-password-toggles", function (root) { initPasswordToggles(root); });
window.AksrtFrontend.register("aksrt-interaction-bar", function (root) { initInteractionBar(root); });
})();
+35
View File
@@ -531,6 +531,39 @@
});
}
function bindCharacterCount(editor) {
var counter = null;
function getCounter() {
var container = editor.getContainer();
var statusbar = container && container.querySelector('.mce-statusbar .mce-container-body');
if (!statusbar) {
return null;
}
counter = counter || statusbar.querySelector('[data-submit-word-count]');
if (!counter) {
counter = document.createElement('span');
counter.className = 'mce-wordcount aksrt-submit-word-count';
counter.setAttribute('data-submit-word-count', '');
counter.setAttribute('aria-live', 'polite');
statusbar.appendChild(counter);
}
return counter;
}
function updateCount() {
var count = String((editor.getBody() && editor.getBody().textContent) || '')
.replace(/\s+/g, '').length;
var element = getCounter();
if (element) {
element.textContent = '字数:' + count;
}
}
editor.on('init SetContent input keyup change Undo Redo', updateCount);
}
function openCodeModal(editor) {
var selected = editor.dom.getParent(editor.selection.getNode(), 'pre.enlighter-pre');
var code = selected ? selected.querySelector('code') : null;
@@ -591,6 +624,8 @@
}
window.tinymce.PluginManager.add('aksrt_editor_tools', function (editor) {
bindCharacterCount(editor);
if (editorCfg.canUploadImage) {
editor.addButton('aksrt_image', {
text: '',
-49
View File
@@ -3,7 +3,6 @@
*
* 提供前台编辑页面的增强功能:
* - 自动保存草稿
* - 字数统计
* - 标签建议
* - 快捷键支持
*
@@ -27,8 +26,6 @@
contentSelector: 'textarea[name="content"], textarea[name="topic_content"]',
tagsSelector: 'input[name="tags"], input[name="topic_tags"]',
autoSaveInterval: 30000, // 30秒
maxTitleLength: 200,
maxContentLength: 100000,
draftKey: '',
}, options || {});
@@ -47,9 +44,6 @@
this.contentTextarea = this.form.querySelector(this.options.contentSelector);
this.tagsInput = this.form.querySelector(this.options.tagsSelector);
// 字数统计
this.initWordCount();
// 自动保存草稿
this.initAutoSave();
@@ -73,49 +67,6 @@
});
};
PageEdit.prototype.initWordCount = function () {
var self = this;
// 创建字数统计显示
this.wordCountEl = document.createElement('div');
this.wordCountEl.className = 'aksrt-page-edit__word-count';
if (this.titleInput) {
var titleCount = document.createElement('span');
titleCount.className = 'aksrt-page-edit__title-count';
this.titleInput.parentNode.appendChild(titleCount);
this.titleInput.addEventListener('input', function () {
var len = self.titleInput.value.length;
titleCount.textContent = len + '/' + self.options.maxTitleLength;
titleCount.classList.toggle('aksrt-page-edit__count--warn', len > self.options.maxTitleLength * 0.9);
titleCount.classList.toggle('aksrt-page-edit__count--error', len > self.options.maxTitleLength);
});
}
if (this.contentTextarea) {
this.contentTextarea.parentNode.appendChild(this.wordCountEl);
this.updateWordCount();
this.contentTextarea.addEventListener('input', function () {
self.updateWordCount();
});
}
};
PageEdit.prototype.updateWordCount = function () {
if (!this.contentTextarea || !this.wordCountEl) return;
var text = this.contentTextarea.value;
var chars = text.length;
var words = text.trim() ? text.trim().split(/\s+/).length : 0;
var chinese = (text.match(/[一-鿿]/g) || []).length;
this.wordCountEl.textContent = '字数: ' + chars + ' | 词数: ' + words + ' | 中文: ' + chinese;
this.wordCountEl.classList.toggle('aksrt-page-edit__count--warn', chars > this.options.maxContentLength * 0.9);
this.wordCountEl.classList.toggle('aksrt-page-edit__count--error', chars > this.options.maxContentLength);
};
PageEdit.prototype.initAutoSave = function () {
var self = this;
+1 -53
View File
@@ -1,60 +1,10 @@
<?php
/**
* 前端模板标签:阅读时长、面包屑、评论回调
* 前端模板标签:文章展示设置、面包屑与统计辅助
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_reading_minutes')) :
/**
* 估算文章阅读分钟数
*
* @param int|null $post_id 文章 ID,默认当前文章
* @return int
*/
function aksrt_reading_minutes($post_id = null) {
$post = get_post($post_id);
if (!$post) {
return 1;
}
$text = wp_strip_all_tags($post->post_content);
$han = 0;
if (preg_match_all('/\p{Han}/u', $text, $m)) {
$han = count($m[0]);
}
$words = str_word_count($text) + (int) ceil($han / 2);
if ($words < 1) {
$words = (int) max(1, strlen($text) / 4);
}
$minutes = (int) ceil($words / 220);
return max(1, $minutes);
}
endif;
if (!function_exists('aksrt_post_word_count')) :
/**
* Approximate visible word count for single-post meta display.
*
* @param int|null $post_id Post ID.
* @return int
*/
function aksrt_post_word_count($post_id = null): int {
$post = get_post($post_id);
if (!($post instanceof WP_Post)) {
return 0;
}
$text = wp_strip_all_tags((string) $post->post_content);
$han = 0;
if (preg_match_all('/\p{Han}/u', $text, $matches)) {
$han = count($matches[0]);
}
$latin_words = str_word_count($text);
$total = $latin_words + $han;
if ($total <= 0) {
$total = (int) ceil(strlen($text) / 2);
}
return max(0, $total);
}
endif;
if (!function_exists('aksrt_resolve_single_post_display_settings')) :
/**
* Resolve single post/resource display settings, including post-meta overrides.
@@ -104,8 +54,6 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
'yiyan_box' => false,
'print_enabled' => true,
'pdf_export_enabled' => false,
'word_count_enabled' => true,
'reading_time_enabled' => true,
];
// Normalize legacy aliases → canonical render keys (idempotent).
if (!array_key_exists('share_enabled', $settings) && array_key_exists('share_s', $settings)) {
+5 -6
View File
@@ -99,11 +99,9 @@ if (!function_exists('aksrt_get_single_meta_box')) :
/**
* legacy equivalent.
*
* @param string $class Extra class on wrapper.
* @param string $direction Unused (kept for API parity).
* @param int|null $post_id Post ID.
*/
function aksrt_get_single_meta_box(string $class = 'abs-right', string $direction = 'down', $post_id = null): string {
function aksrt_get_single_meta_box($post_id = null): string {
if (!is_single() && !is_singular()) {
return '';
}
@@ -128,11 +126,12 @@ if (!function_exists('aksrt_get_single_meta_box')) :
}
$permalink = get_permalink($post_id);
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url($permalink ?: home_url('/'));
$menu_id = 'post-drop-meta-menu-' . $post_id;
$more .= '<div class="clearfix ml6 post-drop-meta">';
$more .= '<button type="button" class="but cir post-drop-meta__toggle" aria-haspopup="true" aria-expanded="false" aria-label="' . esc_attr__('更多', 'aksrt') . '">';
$more .= '<button type="button" class="but cir post-drop-meta__toggle" aria-haspopup="true" aria-controls="' . esc_attr($menu_id) . '" aria-expanded="false" aria-label="' . esc_attr__('更多', 'aksrt') . '">';
$more .= '<i class="fa fas fa-ellipsis-h" aria-hidden="true"></i></button>';
$more .= '<div class="post-drop-meta__menu" aria-hidden="true">';
$more .= '<div id="' . esc_attr($menu_id) . '" class="post-drop-meta__menu" aria-hidden="true">';
if ($edit_link) {
$more .= '<a href="' . esc_url($edit_link) . '" class="post-drop-meta__item"><i class="fa fas fa-edit" aria-hidden="true"></i><span>' . esc_html__('编辑文章', 'aksrt') . '</span></a>';
}
@@ -144,7 +143,7 @@ if (!function_exists('aksrt_get_single_meta_box')) :
}
$more .= '</div></div>';
return '<div class="flex ac single-metabox ' . esc_attr($class) . '"><div class="post-metas">' . $meta . '</div>' . $more . '</div>';
return '<div class="flex ac single-metabox"><div class="post-metas">' . $meta . '</div>' . $more . '</div>';
}
endif;
+4 -12
View File
@@ -42,7 +42,7 @@ if (!function_exists('aksrt_single_render_cover')) :
<div class="post-breadcrumbs"><?php echo $crumbs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
<?php endif; ?>
<?php if ($meta_box !== '') : ?>
<?php echo str_replace('abs-right', 'mb10 ml10 shrink0', $meta_box); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo str_replace('single-metabox', 'single-metabox mb10 ml10 shrink0', $meta_box); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endif; ?>
</div>
<h1 class="article-title">
@@ -96,7 +96,7 @@ if (!function_exists('aksrt_single_render_cover')) :
. ($crumbs !== '' ? $crumbs : '')
. $badge
. '</div>'
. ($meta_box !== '' ? str_replace('abs-right', 'cover-meta abs-right', $meta_box) : '');
. ($meta_box !== '' ? str_replace('single-metabox', 'single-metabox cover-meta abs-right', $meta_box) : '');
$slider_html = '';
if (function_exists('aksrt_render_slider')) {
$slider_html = aksrt_render_slider([
@@ -143,7 +143,7 @@ if (!function_exists('aksrt_single_render_cover')) :
<?php echo $badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php if ($meta_box !== '') : ?>
<?php echo str_replace('abs-right', 'cover-meta abs-right', $meta_box); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo str_replace('single-metabox', 'single-metabox cover-meta abs-right', $meta_box); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endif; ?>
</div>
</div>
@@ -174,15 +174,7 @@ if (!function_exists('aksrt_single_render_box_header')) :
'show_time' => empty($settings['hide_time']),
'meta_html' => empty($ctx['show_cover']) ? (string) ($ctx['meta_box_html'] ?? '') : '',
]);
$reading_meta = is_array($ctx['meta_items_secondary'] ?? null) ? $ctx['meta_items_secondary'] : [];
if ($reading_meta !== []) :
?>
<div class="article-reading-meta" aria-label="<?php esc_attr_e('阅读信息', 'aksrt'); ?>">
<?php foreach ($reading_meta as $item) : ?>
<span><i class="<?php echo esc_attr((string) ($item['icon'] ?? 'fa fas fa-file-alt')); ?>" aria-hidden="true"></i><?php echo esc_html((string) ($item['text'] ?? '')); ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
?>
</div>
<?php
}
+1 -21
View File
@@ -26,31 +26,12 @@ if (!function_exists('aksrt_single_build_context')) :
$comment_count = (int) get_comments_number($post_id);
$like_count = function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($post_id) : 0;
$favorite_count = function_exists('aksrt_get_post_favorites') ? (int) aksrt_get_post_favorites($post_id) : 0;
$word_count = function_exists('aksrt_post_word_count') && !empty($settings['word_count_enabled'])
? aksrt_post_word_count($post_id)
: 0;
$reading_minutes = function_exists('aksrt_reading_minutes') && !empty($settings['reading_time_enabled'])
? aksrt_reading_minutes($post_id)
: 0;
// legacy primary meta = comment/views/likes via meta_box_html.
$meta_items = [];
$meta_box_html = function_exists('aksrt_get_single_meta_box')
? aksrt_get_single_meta_box('abs-right', 'down', $post_id)
? aksrt_get_single_meta_box($post_id)
: '';
$meta_items_secondary = [];
if ($word_count > 0) {
$meta_items_secondary[] = [
'icon' => 'fa fas fa-file-word',
'text' => sprintf(__('约 %s 字', 'aksrt'), number_format_i18n($word_count)),
];
}
if ($reading_minutes > 0) {
$meta_items_secondary[] = [
'icon' => 'fa fas fa-hourglass',
'text' => sprintf(_n('约 %d 分钟', '约 %d 分钟', $reading_minutes, 'aksrt'), $reading_minutes),
];
}
$copyright = trim((string) ($settings['copyright_text'] ?? ''));
if ($copyright === '') {
@@ -121,7 +102,6 @@ if (!function_exists('aksrt_single_build_context')) :
'video_episodes' => is_array($settings['video_episodes'] ?? null) ? array_values($settings['video_episodes']) : [],
'video_poster' => (string) ($settings['video_poster'] ?? ''),
'meta_items' => $meta_items,
'meta_items_secondary' => $meta_items_secondary,
'meta_box_html' => $meta_box_html,
'title_html' => function_exists('aksrt_get_single_title_html') ? aksrt_get_single_title_html($post_id) : esc_html(get_the_title($post_id)),
'allow_view' => $allow_view,
+2 -4
View File
@@ -191,10 +191,8 @@ class SchemaPostList {
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'tools', 'title' => '工具功能', 'fields' => [
['key' => 'feature_print', 'label' => '打印文章', 'type' => 'switch', 'default' => true],
['key' => 'feature_word_count', 'label' => '字数统计', 'type' => 'switch', 'default' => true],
['key' => 'feature_reading_time', 'label' => '预计阅读时间', 'type' => 'switch', 'default' => true],
['key' => 'feature_pdf_export', 'label' => 'PDF 导出', 'type' => 'switch', 'default' => false],
['key' => 'feature_print', 'label' => '打印文章', 'type' => 'switch', 'default' => true],
['key' => 'feature_pdf_export', 'label' => 'PDF 导出', 'type' => 'switch', 'default' => false],
]],
],
],
+1 -1
View File
@@ -156,7 +156,7 @@ trait FacadeBulk {
/**
* Single post/page display settings.
*
* @return array{reading_progress:bool,lightbox:bool,related_enabled:bool,related_count:int,like_enabled:bool,favorite_enabled:bool,share_enabled:bool,copyright_enabled:bool,print_enabled:bool,pdf_export_enabled:bool,word_count_enabled:bool,reading_time_enabled:bool}
* @return array<string,mixed>
*/
public static function get_post_page_settings(): array {
// Canonical assembly lives in the post-display helper (related style/source split, aliases).
-2
View File
@@ -274,8 +274,6 @@ class PostDisplay {
'default_views_max' => max(1, min(9999, (int) ($settings['post_default_views_max'] ?? 50))),
'default_likes_min' => max(0, min(9999, (int) ($settings['post_default_likes_min'] ?? 5))),
'default_likes_max' => max(1, min(9999, (int) ($settings['post_default_likes_max'] ?? 15))),
'word_count_enabled' => !isset($settings['post_word_count_enabled']) || !empty($settings['post_word_count_enabled']),
'reading_time_enabled' => !isset($settings['post_reading_time_enabled']) || !empty($settings['post_reading_time_enabled']),
'print_enabled' => !isset($settings['feature_print']) || !empty($settings['feature_print']),
'pdf_export_enabled' => !empty($settings['feature_pdf_export']),
];
+2 -2
View File
@@ -137,12 +137,12 @@ $is_self = is_user_logged_in() && get_current_user_id() === $author_id;
</div>
<?php if ($show_actions) : ?>
<div class="relative">
<div class="single-meta-row">
<i class="line-form-line" aria-hidden="true"></i>
<?php if ($meta_html !== '') : ?>
<?php echo $meta_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php elseif (!empty($meta_items)) : ?>
<div class="flex ac single-metabox abs-right">
<div class="flex ac single-metabox">
<div class="post-metas">
<?php foreach ($meta_items as $meta_item) : ?>
<?php
@@ -88,3 +88,17 @@ test('public theme does not inject a global focus-visible ring', () => {
assert.doesNotMatch(publicCss, globalFocusRule);
assert.doesNotMatch(publicMinCss, globalFocusRule);
});
test('front submit TinyMCE status bar shows one live character counter', () => {
const editor = read('assets/js/front-submit-editor.js');
const submitCss = read('assets/css/frontend/pages/submit.css');
const legacyPageEdit = read('assets/js/page-edit.js');
assert.match(editor, /querySelector\('\.mce-statusbar \.mce-container-body'\)/);
assert.match(editor, /data-submit-word-count/);
assert.match(editor, /textContent\s*=\s*'字数:'\s*\+\s*count/);
assert.match(editor, /editor\.on\('init SetContent input keyup change Undo Redo'/);
assert.match(editor, /replace\(\/\\s\+\/g, ''\)\.length/);
assert.match(submitCss, /\.newposts-editor \.aksrt-submit-word-count\s*{[^}]*float:\s*right;/);
assert.doesNotMatch(legacyPageEdit, /initWordCount|updateWordCount|aksrt-page-edit__word-count|字数:/);
});
@@ -494,6 +494,51 @@ test('single articles enqueue only content and settings driven assets', () => {
}
});
test('single post more menu has one accessible runtime and an in-flow author anchor', () => {
const article = read('assets/js/core/article.js');
const components = read('inc/helpers/aksrt-single-components.php');
const single = read('inc/helpers/aksrt-single.php');
const authorBar = read('templates/parts/single-author-bar.php');
const styles = read('assets/css/frontend/single-post/author-actions.css');
assert.match(article, /function initPostMetaMenus\(root\)/);
assert.match(article, /classList\.toggle\("is-open", open\)/);
assert.match(article, /setAttribute\("aria-expanded", open \? "true" : "false"\)/);
assert.match(article, /setAttribute\("aria-hidden", open \? "false" : "true"\)/);
assert.match(article, /event\.key === "Escape"/);
assert.match(article, /window\.AksrtFrontend\.register\("aksrt-post-meta-menus"/);
assert.doesNotMatch(components + article, /data-toggle=["']dropdown|\.dropdown\(/);
assert.match(components, /\$menu_id = 'post-drop-meta-menu-' \. \$post_id/);
assert.match(components, /aria-controls="' \. esc_attr\(\$menu_id\)/);
assert.match(components, /aria-haspopup="true"/);
assert.match(single, /aksrt_get_single_meta_box\(\$post_id\)/);
assert.doesNotMatch(components, /\$direction/);
assert.match(authorBar, /class="single-meta-row"/);
assert.doesNotMatch(authorBar, /single-metabox abs-right/);
assert.match(styles, /\.single-meta-row > \.single-metabox\s*\{[^}]*position:\s*relative;[^}]*transform:\s*none;/s);
assert.match(styles, /\.post-drop-meta__menu\s*\{[^}]*position:\s*absolute;[^}]*right:\s*0;/s);
});
test('single post has no word-count or estimated-reading-time chain', () => {
const chain = join([
'inc/helpers/aksrt-single.php',
'inc/helpers/aksrt-single-render.php',
'inc/helpers/aksrt-frontend-tags.php',
'src/Settings/PostDisplay.php',
'src/Settings/FacadeBulk.php',
'src/Admin/Schema/SchemaPostList.php',
'assets/admin/src/schema/sections/post-list/feature.js',
'assets/css/frontend/single-post/shell.css',
]);
assert.doesNotMatch(chain, /aksrt_(?:post_word_count|reading_minutes)/);
assert.doesNotMatch(chain, /(?:feature_|post_)?word_count(?:_enabled)?/);
assert.doesNotMatch(chain, /(?:feature_|post_)?reading_time(?:_enabled)?/);
assert.doesNotMatch(chain, /meta_items_secondary|article-reading-meta/);
assert.doesNotMatch(chain, /字数统计|预计阅读时间|约 %s 字|约 %d 分钟/);
});
test('resource meta CSS uses one canonical direct stylesheet', () => {
const enqueue = read('src/Core/ScriptsPart1b.php');
const canonical = path.join(root, 'assets/css/frontend/resource-meta/part.css');