diff --git a/assets/css/archives.css b/assets/css/archives.css new file mode 100644 index 0000000..0dbe027 --- /dev/null +++ b/assets/css/archives.css @@ -0,0 +1,385 @@ +/*! + * 归档式文章列表([Archives])样式 + * Yongquan Yang + * + * ── 设计原则 ──────────────────────────────────────────────── + * 1. **它是导航,不是内容**:所以字号小一点、颜色退后一步, + * 让文章标题成为这一屏唯一的主角。 + * 2. **色值一律带兜底**:`var(--ar-primary, #00a2ff)`。 + * 主题**没有**定义全站 CSS 变量(主色是各处硬编码的), + * 照抄 var(--kratos-primary) 会静默失效、整块永远是默认灰。 + * 所以本文件自己定义一组 `--ar-*` 局部变量,挂在 `.yang-archives` + * 作用域内,不污染全站;同时每个使用点都带兜底值。 + * 3. **与评论区的变量命名区分**:评论用 `--yq-*`,这里用 `--ar-*`。 + * 两套互不依赖,将来任一方改色都不会波及另一方。 + * 4. **不引入图标字体以外的东西**:三项计数用的 `i-hot`/`i-comments`/`i-good` + * 是主题图标集里已有的三个(page-content.php 同款)。 + */ + +.yang-archives { + /* 主色 / 文字三级 / 线 —— 与 comments.css 同一套取值,视觉统一 */ + --ar-primary: #00a2ff; + --ar-primary-soft: #eaf6ff; + --ar-text: #33383f; + --ar-text-2: #5b6470; + --ar-text-3: #6b7280; + --ar-line: #eaedf2; + --ar-line-soft: #f1f4f8; + --ar-radius: 4px; + + margin: 24px 0 8px; + font-size: 14px; + line-height: 1.6; + color: var(--ar-text, #33383f); +} + +/*-------------------------------------------------------------- +1. 头部:年份 + 总数 + 上排导航 +--------------------------------------------------------------*/ + +.yang-archives .ar-head { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px 12px; + padding-bottom: 12px; + border-bottom: 1px solid var(--ar-line, #eaedf2); +} + +.yang-archives .ar-year { + margin: 0; + font-size: 22px; + font-weight: 700; + line-height: 1.2; + color: var(--ar-text, #33383f); + /* 等宽数字:切年时 2026 → 2025 两位都变,不等宽会左右跳一下 */ + font-variant-numeric: tabular-nums; +} + +.yang-archives .ar-total { + font-size: 12.5px; + color: var(--ar-text-3, #6b7280); +} + +/*-------------------------------------------------------------- +2. 四角导航 +--------------------------------------------------------------*/ + +/* 上排靠右、下排靠右 —— 两侧按钮分居两端 */ +.yang-archives .ar-nav { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-left: auto; + min-width: 240px; +} + +.yang-archives .ar-nav-top { + /* 头部是 flex,导航自己靠右;窄屏会换行到标题下方 */ + margin-left: auto; +} + +.yang-archives .ar-foot { + margin-top: 16px; + padding-top: 14px; + border-top: 1px solid var(--ar-line, #eaedf2); +} + +.yang-archives .ar-foot .ar-nav { + margin-left: 0; + min-width: 0; +} + +.yang-archives .ar-nav-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + border: 1px solid var(--ar-line, #eaedf2); + border-radius: var(--ar-radius, 4px); + background-color: #fff; + color: var(--ar-text-2, #5b6470); + font-size: 13px; + line-height: 1.4; + text-decoration: none; + white-space: nowrap; + transition: border-color 0.16s ease, color 0.16s ease, background-color 0.16s ease; +} + +.yang-archives a.ar-nav-btn:hover { + border-color: var(--ar-primary, #00a2ff); + background-color: var(--ar-primary-soft, #eaf6ff); + color: var(--ar-primary, #00a2ff); + text-decoration: none; +} + +.yang-archives a.ar-nav-btn:focus-visible { + outline: 2px solid var(--ar-primary, #00a2ff); + outline-offset: 2px; +} + +.yang-archives .ar-nav-arrow { + font-size: 11px; + line-height: 1; + opacity: 0.8; +} + +.yang-archives .ar-nav-year { + font-size: 12px; + color: var(--ar-text-3, #6b7280); + font-variant-numeric: tabular-nums; +} + +.yang-archives a.ar-nav-btn:hover .ar-nav-year { + color: inherit; +} + +/* 禁用态:到最早/最新一年。用 opacity + 去掉交互, + * 不用 display:none —— 按钮消失会让"上排只剩一个按钮"看着像坏了。 */ +.yang-archives .ar-nav-btn.is-disabled { + opacity: 0.42; + cursor: not-allowed; + background-color: transparent; +} + +/*-------------------------------------------------------------- +3. 月份分组 +--------------------------------------------------------------*/ + +.yang-archives .ar-month + .ar-month { + margin-top: 18px; +} + +.yang-archives .ar-month-title { + display: flex; + align-items: center; + gap: 8px; + margin: 14px 0 6px; + font-size: 14px; + font-weight: 600; + color: var(--ar-text-2, #5b6470); +} + +/* 月份标题左侧一小段主色竖线,作为分组视觉锚点 */ +.yang-archives .ar-month-title::before { + content: ""; + flex: 0 0 auto; + width: 3px; + height: 14px; + border-radius: 2px; + background-color: var(--ar-primary, #00a2ff); +} + +.yang-archives .ar-month-count { + padding: 0 6px; + border-radius: 999px; + background-color: var(--ar-line-soft, #f1f4f8); + color: var(--ar-text-3, #6b7280); + font-size: 11.5px; + font-weight: 400; + font-variant-numeric: tabular-nums; +} + +/*-------------------------------------------------------------- +4. 条目 +--------------------------------------------------------------*/ + +.yang-archives .ar-list { + margin: 0; + padding: 0; + list-style: none; +} + +.yang-archives .ar-item { + display: flex; + align-items: baseline; + gap: 10px; + padding: 6px 8px; + border-radius: var(--ar-radius, 4px); + /* 分隔用极浅的线,不抢视觉 */ + border-bottom: 1px solid var(--ar-line-soft, #f1f4f8); +} + +.yang-archives .ar-item:last-child { + border-bottom: 0; +} + +.yang-archives .ar-item:hover { + background-color: var(--ar-primary-soft, #eaf6ff); +} + +.yang-archives .ar-date { + flex: 0 0 auto; + min-width: 44px; + color: var(--ar-text-3, #6b7280); + font-size: 12.5px; + font-variant-numeric: tabular-nums; +} + +.yang-archives .ar-title { + flex: 1 1 auto; + min-width: 0; + color: var(--ar-text, #33383f); + text-decoration: none; + /* 长标题单行截断:归档是"扫一眼找文章",换行会把行距撑乱 */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.yang-archives .ar-title:hover { + color: var(--ar-primary, #00a2ff); + text-decoration: underline; + text-underline-offset: 2px; +} + +.yang-archives .ar-item:hover .ar-title { + color: var(--ar-primary, #00a2ff); +} + +/*-------------------------------------------------------------- +5. 三项计数 +--------------------------------------------------------------*/ + +.yang-archives .ar-stats { + flex: 0 0 auto; + display: inline-flex; + align-items: center; + gap: 10px; + margin-left: auto; + padding-left: 10px; +} + +.yang-archives .ar-stat { + display: inline-flex; + align-items: center; + gap: 3px; + color: var(--ar-text-3, #6b7280); + font-size: 12px; + font-variant-numeric: tabular-nums; + white-space: nowrap; +} + +.yang-archives .ar-stat .kicon { + font-size: 12px; + line-height: 1; +} + +/* 零值弱化:0 浏览 / 0 评论 / 0 赞占了相当多,一律同等强调会让 + * 计数列看起来全是"0 0 0",反而看不出哪篇有热度。 + * 属性由 PHP 在渲染时按真实值打(见 yang_archives_render_item())。 */ +.yang-archives .ar-stat[data-zero="1"] { + opacity: 0.45; +} + +/*-------------------------------------------------------------- +6. 空态 +--------------------------------------------------------------*/ + +.yang-archives .ar-empty { + margin: 20px 0 4px; + padding: 18px 16px; + border: 1px dashed #dfe5ec; + border-radius: var(--ar-radius, 4px); + color: var(--ar-text-3, #6b7280); + font-size: 13.5px; + text-align: center; +} + +/*-------------------------------------------------------------- +7. 切年时的过渡 +--------------------------------------------------------------*/ + +/* 只做淡入,不做高度动画: + * 高度动画需要先量 scrollHeight 再改 height,在长列表(一年 12 个月) + * 上会强制同步布局,切年时有肉眼可见的卡顿。 + * 淡入用 CSS animation 而不是 JS 定时器,是为了让它自己结束、 + * 不留 pending 的 timeout(否则快速连点切年,几个 timeout 会交错)。 */ +.yang-archives .ar-body.is-switching { + animation: ar-fade 0.18s ease; +} + +@keyframes ar-fade { + from { + opacity: 0; + transform: translateY(-2px); + } + + to { + opacity: 1; + transform: none; + } +} + +/* 尊重系统的"减少动效"设置 */ +@media (prefers-reduced-motion: reduce) { + .yang-archives .ar-body.is-switching { + animation: none; + } +} + +/*-------------------------------------------------------------- +8. 窄屏 +--------------------------------------------------------------*/ + +@media (max-width: 767.98px) { + .yang-archives { + font-size: 13.5px; + } + + .yang-archives .ar-head { + /* 窄屏下导航换到标题下方并且铺满,两个按钮各占一半 */ + align-items: baseline; + } + + .yang-archives .ar-nav { + width: 100%; + min-width: 0; + margin-left: 0; + } + + .yang-archives .ar-nav-btn { + flex: 1 1 0; + justify-content: center; + padding: 7px 8px; + } + + /* 窄屏隐藏计数图标,只留数字 —— 图标加数字在 320px 宽度下 + * 会把标题挤到只剩两三个字 */ + .yang-archives .ar-stat .kicon { + display: none; + } + + .yang-archives .ar-stats { + gap: 8px; + padding-left: 6px; + } + + .yang-archives .ar-date { + min-width: 40px; + font-size: 12px; + } +} + +@media (max-width: 400px) { + .yang-archives .ar-title { + /* 极窄屏允许两行,否则标题只剩几个字完全看不出是哪篇 */ + white-space: normal; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .yang-archives .ar-item { + /* 计数换到标题下一行,避免和标题抢宽度 */ + flex-wrap: wrap; + } + + .yang-archives .ar-stats { + width: 100%; + margin-left: 0; + padding-left: 50px; + } +} \ No newline at end of file diff --git a/assets/css/comments.css b/assets/css/comments.css index 9e0d0cc..a466978 100644 --- a/assets/css/comments.css +++ b/assets/css/comments.css @@ -180,7 +180,9 @@ outline-offset: 2px; } -.comments-closed, +/* .comments-closed 的样式已在 3.2.46 删除:评论关闭时整个评论区 + * 一个字节都不输出(见 comments.php 开头的 return),这个类名 + * 再也不会出现在页面上。留着它会让后来人以为"还有个关闭态要美化"。 */ .comments-empty { margin: 20px 0 4px; padding: 18px 16px; diff --git a/assets/js/archives.js b/assets/js/archives.js new file mode 100644 index 0000000..b7712ee --- /dev/null +++ b/assets/js/archives.js @@ -0,0 +1,538 @@ +/*! + * 归档式文章列表([Archives])—— 年份切换 + * Yongquan Yang + * + * ── 它只做一件事 ──────────────────────────────────────────── + * 把 ``(下面还有一道保险); + * ③ 浏览器不执行它,CSP 里 `unsafe-inline` 也管不到。 + * + * 🔴 JSON_HEX_TAG 等四个 flag 是**必须**的:文章标题里出现 + * `` 时,若不把这四个字符转成 \\u003C 之类, + * 浏览器的 HTML 解析器会在标题中间就把脚本块截断 —— + * 页面后面全部错乱,而且看起来像"某个标题把页面搞坏了"。 */ + $json = wp_json_encode( + array( + 'years' => $data['years'], + 'order' => $data['order'], + 'latest' => $data['latest'], + 'total' => $data['total'], + 'current' => $year, + 'showMonth' => $opt['month'], + 'showNav' => $opt['nav'], + 'baseUrl' => get_permalink(), + 'i18n' => array( + 'month' => __('%s 月', 'kratos'), + 'prev' => __('上一年', 'kratos'), + 'next' => __('下一年', 'kratos'), + 'views' => __('浏览数', 'kratos'), + 'comments' => __('评论数', 'kratos'), + 'love' => __('点赞数', 'kratos'), + 'untitled' => __('(无标题)', 'kratos'), + 'empty' => __('这一年还没有文章。', 'kratos'), + 'totalFmt' => __('共 %s 篇', 'kratos'), + ), + ), + JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT + ); + + $uid = 'yang-archives-' . wp_unique_id(); + + $out = '
'; + + // 顶部:年份标题 + 四角导航上排 + $out .= '
'; + /* 🔴 年份标题同样**不能**过 number_format_i18n(会变「2,025」)。 + * 而且要输出纯数字,与 JS 切年后的 `String(year)` 完全一致 —— + * 两边不一致就是「首屏 2,025、点一下 2025」。 */ + $out .= '

' + . esc_html((string) $year) . '

'; + + $out .= '' + . sprintf( + /* translators: %s: 文章数 */ + esc_html__('共 %s 篇', 'kratos'), + esc_html(number_format_i18n($data['years'][$year]['count'])) + ) + . ''; + + if ($opt['nav']) { + $out .= yang_archives_render_nav($year, $data['order'], 'top'); + } + + $out .= '
'; + + // 列表主体 + $out .= '
'; + $out .= yang_archives_render_year($data['years'][$year], $year, $opt['month']); + $out .= '
'; + + // 底部导航(四角的下排) + if ($opt['nav']) { + $out .= '
'; + $out .= yang_archives_render_nav($year, $data['order'], 'bottom'); + $out .= '
'; + } + + $out .= ''; + + $out .= '
'; + + return $out; +} + +/* WP 的 shortcode 标签是**大小写不敏感**的(它内部统一 strtolower), + * 所以注册小写 `archives` 就能同时匹配 [Archives] / [ARCHIVES] / [archives]。 + * 这里按 WP 惯例注册小写。 */ +add_shortcode('archives', 'yang_archives_shortcode'); \ No newline at end of file diff --git a/inc/theme-comments.php b/inc/theme-comments.php index ba40309..0d680f7 100644 --- a/inc/theme-comments.php +++ b/inc/theme-comments.php @@ -744,6 +744,22 @@ function yang_comment_scripts() return; } + /* 3.2.46:评论关闭时 comments.php 会整块 return(一个字节都不输出), + * 那么这套 10KB 的评论样式与脚本就**永远用不到**。 + * + * 判据必须与 comments.php 的那个 return 同口径,否则会出现两种错: + * · 这里判"开"、那边判"关" → 加载了资源却没有 DOM 可绑, + * comments.js 里找 #commentform 的逻辑全部静默落空(无害但白费); + * · 这里判"关"、那边判"开" → 评论框能显示但没样式,一眼就散架。 + * 两边都用 `comments_open()`(后者不带参数,取当前文章)。 + * + * ⚠️ 必须放在 is_singular() 之后:在非单页上 comments_open() 没有 + * 明确的主语,WP 会退回 $post 全局,可能取到列表里最后一篇文章的 + * 状态 —— 那样判断结果没有意义。 */ + if (!comments_open(get_queried_object_id())) { + return; + } + /* wpDiscuz 在场时**不加载**主题这套脚本与样式。 * * 原因:插件会接管评论表单(换成它自己的 #wpdcom),并绑定自己的 diff --git a/style.css b/style.css index 516d40d..613e992 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,7 @@ /* Theme Name: Kratos_Yang Text Domain: kratos_Yang -Version: 3.2.45 +Version: 3.2.46 Requires PHP: 7.0 Description: 这是一个Kratos主题的分支版本,用来增加一些定制化功能。 Tags: 博客, 双栏, 响应式, 自定义背景, 自定义颜色, 自定义图标, 自定义菜单, 特色图像, 收录优化, 邮件中心, 主题选项, 小工具, 文章置顶, 无障碍友好