自动目录:正文里那份和浮层那份要能分别设置「默认显示 / 默认隐藏」,不要共用一个 #27

Closed
opened 2026-10-27 11:58:02 +00:00 by laoyang · 2 comments
Owner

现象 / 诉求

「主题设置 → 自动目录」里现在只有一个「默认状态」下拉(toc_default,选 默认显示 / 默认隐藏)。
正文里那份目录和浮在页面边上的那份共用这一个值,改一个另一个必然跟着变。

用户原话:

另外还有一个就是自动目录功能,文章中的和悬浮,需要分别设置是默认开启还是默认隐藏,
比如我选择悬浮的默认隐藏,文章中的默认显示,这两个不一定是同步的。

所以:toc_inline(正文)与 toc_float(浮层)各自独立的「默认显示 / 默认隐藏」。

现状核实(已查过源码)

toc_default 目前被两处读取,一处是正文、一处是浮层:

位置 代码 作用
inc/theme-toc.php:296 'open' => $s['default'] === 'show' ? '1' : '0' yang_toc_atts_from_settings() → 正文 <details> 的 open 属性
inc/theme-toc.php:982 $open = ($s['default'] === 'show'); yang_toc_rail_html() → 浮层 is-open 类 + aria-expanded

默认值定义在 inc/theme-toc.php:118:'default' => 'show'。

后台选项在 inc/theme-options.php:557-568,位于「两份目录共用的设置」这个 info 分组下面。

要做的改动

把 default 一拆为二:

  • inline_default:正文那份的默认显示/隐藏,默认继承原值(show)
  • float_default:浮层那份的默认显示/隐藏,默认继承原值(show)
  • default 保留为兼容键:老配置里只有 default 时,两个新键都从它取初值(否则升级后用户设置会被重置成 show)

⚠️ yang_toc_defaults() 与 inc/theme-options.php 的 std 必须同步改。
该文件第 449 行已经用大字注释写了这条规矩:

⚠️ 这里的 std 必须与 inc/theme-toc.php 的 yang_toc_defaults() 一致。

两处不一致会出「页面照 A 渲染、后台框里显示 B」的错位,而且极难发现。

涉及的坑(先写在单里)

  1. pick() 兜底会把空串当「没填」回落默认值。这条在本项目踩过(见 pick() 相关经验):
    如果新键允许空串,inline_default / float_default 就不能走 pick(),否则「不选」会被当成「用默认」。
    本次两键都是 show|hide 二值,理论上不会空,但归一化函数要一并确认 yang_toc_normalize_settings() 的
    $pick 闭包对未知键的处理(见 theme-toc.php:190-222,那里是 array_key_exists + in_array 白名单,
    不在白名单里的值一律回落默认 —— 新键必须同时加进第 252 行的键列表,否则会被丢掉)。
  2. toc_default 在老配置里的迁移,见上面「兼容键」。
  3. 浮动目录的展开态是写进 class 的(is-open),所以没有 JS 也能看到默认状态(theme-toc.php:940
    注释里明确写了这个设计)。拆分后这个特性必须保留 —— 不要为了省事改成 JS 初始化。
  4. .section 显隐:拆成两项后,「正文里的目录」分组下多一项、「浮动目录」分组下多一项,
    分组 info 的 id 也要跟着调整(toc_group_inline / toc_group_float)。
  5. 正文那份的 open="0" 优先级:theme-toc.php:568 附近提到手写 [TOC] 可用 open="0" 单独指定,
    拆分后这个短代码属性仍然只对正文那份生效,浮层不受它影响,别写混。

验收标准

  • 后台出现两个独立下拉:正文那份的「默认状态」、浮层那份的「默认状态」
  • 正文设 默认显示 + 浮层设 默认隐藏 → 正文目录展开、浮层只露侧边标签
  • 正文设 默认隐藏 + 浮层设 默认显示 → 正文目录只露标题栏、浮层面板展开
  • 两个都设 默认显示 / 两个都设 默认隐藏 也都正常(互不干扰)
  • 老配置升级不丢:只存过 default = hide 的站点,升级后两个新键都是 hide
  • 浮层默认态仍然是纯 CSS/服务端 class 就能体现(关掉 JS 也能看到正确的默认状态)
  • 手写 [TOC] 的 open="0" 仍然只影响正文那份
  • 「恢复默认」后两项都回到 show
  • 后台选项说明文字同步更新,不再出现「对两份同时生效」这种已过时的说法

备注

  • 服务器 IP 目前被防火墙封禁(ping 通但 22/80/443 全 DROP),本地改码不受影响;
    线上几何测量(浮层默认态在窄屏/宽屏的实际表现)与部署需等解封,届时在本单追加评论。
  • 上一轮 #1「正文显示与左右浮动应可同时开启」已关闭,那两个「显示开关」本身不动,
    本单只动「默认开合」这一维,两者是正交的。

为什么单独建单

已关闭的 #1 解决的是「显示开关」这一维(正文与浮动能否同时开启),本单动的是正交的「默认开合」这一维;在途工单里没有任何一张涉及 toc_default。两条需求互不相关(一条是后台表单显隐、一条是目录默认态),用户明确要求分开建单。

## 现象 / 诉求 「主题设置 → 自动目录」里现在只有**一个**「默认状态」下拉(`toc_default`,选 默认显示 / 默认隐藏)。 正文里那份目录和浮在页面边上的那份**共用这一个值**,改一个另一个必然跟着变。 用户原话: > 另外还有一个就是自动目录功能,文章中的和悬浮,需要分别设置是默认开启还是默认隐藏, > 比如我选择悬浮的默认隐藏,文章中的默认显示,这两个不一定是同步的。 所以:**`toc_inline`(正文)与 `toc_float`(浮层)各自独立的「默认显示 / 默认隐藏」**。 ## 现状核实(已查过源码) `toc_default` 目前被**两处**读取,一处是正文、一处是浮层: | 位置 | 代码 | 作用 | |---|---|---| | `inc/theme-toc.php:296` | `'open' => $s['default'] === 'show' ? '1' : '0'` | `yang_toc_atts_from_settings()` → 正文 `<details>` 的 open 属性 | | `inc/theme-toc.php:982` | `$open = ($s['default'] === 'show');` | `yang_toc_rail_html()` → 浮层 `is-open` 类 + `aria-expanded` | 默认值定义在 `inc/theme-toc.php:118`:`'default' => 'show'`。 后台选项在 `inc/theme-options.php:557-568`,位于「两份目录共用的设置」这个 `info` 分组下面。 ## 要做的改动 把 `default` 一拆为二: - `inline_default`:正文那份的默认显示/隐藏,默认继承原值(`show`) - `float_default`:浮层那份的默认显示/隐藏,默认继承原值(`show`) - `default` 保留为**兼容键**:老配置里只有 `default` 时,两个新键都从它取初值(否则升级后用户设置会被重置成 `show`) ⚠️ **`yang_toc_defaults()` 与 `inc/theme-options.php` 的 `std` 必须同步改**。 该文件第 449 行已经用大字注释写了这条规矩: > ⚠️ 这里的 std 必须与 inc/theme-toc.php 的 yang_toc_defaults() 一致。 两处不一致会出「页面照 A 渲染、后台框里显示 B」的错位,而且极难发现。 ## 涉及的坑(先写在单里) 1. **`pick()` 兜底会把空串当「没填」回落默认值**。这条在本项目踩过(见 `pick()` 相关经验): 如果新键允许空串,`inline_default` / `float_default` 就不能走 `pick()`,否则「不选」会被当成「用默认」。 本次两键都是 `show|hide` 二值,理论上不会空,但**归一化函数要一并确认** `yang_toc_normalize_settings()` 的 `$pick` 闭包对未知键的处理(见 `theme-toc.php:190-222`,那里是 `array_key_exists` + `in_array` 白名单, 不在白名单里的值一律回落默认 —— 新键必须同时加进第 252 行的键列表,否则会被丢掉)。 2. **`toc_default` 在老配置里的迁移**,见上面「兼容键」。 3. **浮动目录的展开态是写进 class 的**(`is-open`),所以**没有 JS 也能看到默认状态**(`theme-toc.php:940` 注释里明确写了这个设计)。拆分后这个特性必须保留 —— 不要为了省事改成 JS 初始化。 4. **`.section` 显隐**:拆成两项后,「正文里的目录」分组下多一项、「浮动目录」分组下多一项, 分组 `info` 的 id 也要跟着调整(`toc_group_inline` / `toc_group_float`)。 5. **正文那份的 `open="0"` 优先级**:`theme-toc.php:568` 附近提到手写 `[TOC]` 可用 `open="0"` 单独指定, 拆分后这个短代码属性**仍然只对正文那份生效**,浮层不受它影响,别写混。 ## 验收标准 - [ ] 后台出现两个独立下拉:正文那份的「默认状态」、浮层那份的「默认状态」 - [ ] 正文设 `默认显示` + 浮层设 `默认隐藏` → 正文目录展开、浮层只露侧边标签 - [ ] 正文设 `默认隐藏` + 浮层设 `默认显示` → 正文目录只露标题栏、浮层面板展开 - [ ] 两个都设 `默认显示` / 两个都设 `默认隐藏` 也都正常(互不干扰) - [ ] **老配置升级不丢**:只存过 `default = hide` 的站点,升级后两个新键都是 `hide` - [ ] 浮层默认态仍然是**纯 CSS/服务端 class** 就能体现(关掉 JS 也能看到正确的默认状态) - [ ] 手写 `[TOC]` 的 `open="0"` 仍然只影响正文那份 - [ ] 「恢复默认」后两项都回到 `show` - [ ] 后台选项说明文字同步更新,不再出现「对两份同时生效」这种已过时的说法 ## 备注 - 服务器 IP 目前被防火墙封禁(ping 通但 22/80/443 全 DROP),本地改码不受影响; 线上几何测量(浮层默认态在窄屏/宽屏的实际表现)与部署需等解封,届时在本单追加评论。 - 上一轮 #1「正文显示与左右浮动应可同时开启」已关闭,那两个「显示开关」本身不动, 本单**只动「默认开合」这一维**,两者是正交的。 --- ### 为什么单独建单 已关闭的 #1 解决的是「显示开关」这一维(正文与浮动能否同时开启),本单动的是正交的「默认开合」这一维;在途工单里没有任何一张涉及 toc_default。两条需求互不相关(一条是后台表单显隐、一条是目录默认态),用户明确要求分开建单。
Author
Owner

3.2.59 已发布,请升级后验收

发布通道:走 /theme-update/ 正常更新通道。服务器上的 wp-content/themes/kratos_yang/ 没有被碰过,仍是 3.2.58,等你在后台点升级。

  • update.json 现在是 {"version":"3.2.59", download_url: .../kratos_yang-3.2.59.zip, md5: ba6abca49d5609b02bc754660c973b98}
  • 包:kratos_yang-3.2.59.zip,4821394 字节,md5 ba6abca49d5609b02bc754660c973b98
  • 上一版包 kratos_yang-3.2.58.zip 保留着(还停在旧版、后台缓存了旧 update.json 的人点升级不会 404)
  • readme:50 个版本标题(上一版 49 + 本版 1),历史一条没丢

代码提交:d55667a(3 文件 +175/−19),已推送。


改了什么

inc/theme-toc.php

  • toc_default 一拆为二:inline_default(正文那份)、float_default(浮层那份)

  • 迁移段写成四分支,不是一句 $pick():

    • ① 新键存在且合法 → 用它
    • ② 新键存在但非法 → 回落该键自己的默认
    • ③ 新键不存在、老键存在 → 用老键的值(← 老站点走这条)
    • ④ 都不存在 → 各键默认

    为什么不能简单写 $pick('inline_default', ...):$pick 在键不存在时直接取 $d[$key],那样 ③ 会落进 ④,老站点会被静默重置成 show。

  • yang_toc_settings() 的读库键列表里继续保留 'default'。不读它就不知道老配置里存了什么,迁移段拿不到值,老站点升级后默认开合被重置 —— 而且界面上一切正常,没人会发现。

  • 两个消费点各读自己的键,互不引用:正文走 inline_default,浮层走 float_default。

  • 新增 yang_toc_admin_legacy_values(),挂在 option_kratos filter 上(仅 is_admin() 时挂)。这个函数是真实 WP 验证抓出来的,单里原本没写:

    不挂它的话,老站点会出现「页面按 hide 渲染、后台下拉框却显示 show」。原因是后台框架取值顺序是「先取 std,有保存值才覆盖」,而库里只有 toc_default、没有新键 ⇒ 两个新框都落到 std=show。用户升级后第一眼看到的就是「我的设置没了」。

    它只在读取时把老键的值投影到缺失的新键上,库不动,老键也不删(降级回 3.2.58 时旧版还读得到 toc_default)。

inc/theme-options.php

  • 两个独立下拉,分别落在「正文里的目录」「浮动目录」两个分组末尾
  • 共用分组里「对两份同时生效」那句已经过时,改掉了
  • std 与 yang_toc_defaults() 一致(都是 show)

style.css:3.2.58 → 3.2.59。本版没改前台 CSS(kratos.min.css 与线上逐字节相同),也没动 JS(assets/js/toc.js 与线上逐字节相同)—— 默认态仍然纯粹靠服务端 class 直出,关掉 JS 也能看到正确默认态。


验证数据

项 结果
桩判据 _toc359_split_check.php 61 / 0
反证 _toc359_falsify.php 36 / 0(16 组注入,全部有牙齿且红在预期判据上)
真实 WP 判据 _toc359_wp_check.php 30 / 0(PHP 8.5.12 + WP 7.1.3)
回归 _toc330_logic.php 101 / 0
回归 _test_toc.php 53 / 0
打包自检 _mkzip359.py 42 / 0

本轮踩到的两个坑(值得记一笔)

① 判据脚本自己拿错了版本。

第一轮发布失败在 R13~R16 四条,全是「改坏了但失败数没增加」,看上去像「投影函数的判据没牙齿」。差一点就去重写判据了。

实际错因是:服务器上那份 _toc359_split_check.php 是 24542 字节的旧版(52 条),本地是 27647 字节的新版(61 条)。旧版里根本没有 K 组(投影函数那几条),改坏了当然不会红。而「52 条全过」也被当成「61 条全过」念过去了。

所以发布脚本现在会硬判判据的条数(桩 61 / WP 30 / 反证 16 组 36 查),不够就报「跑的是旧版判据,结论无效」。这是「判据选错靶子」的一个新变体 —— 不是验错了对象,是验证者本身过期了。

② readme 关键词是我脑子里的话,不是文件里的话。

第一轮另外 3 条失败是 readme 关键词:我写了「分别设置」「老配置」「is-open」。真实正文里是:

  • 「可以<b>分别</b>设置」—— 中间夹了标签,grep -F 分别设置 永远匹配不到
  • 说的是「老版本只存了一个」「老站点升级后」,没有「老配置」这个词
  • 说的是「直接写在页面 HTML 上的(一个 class)」,没写 is-open

三个词全部在正确文件上假红。改法是每个词都用 head -80 readme359.html | grep -oF 逐条核过命中数再写进脚本,不再凭印象。


请你验收这几条(不关单,等你确认)

  1. 「主题设置 → 自动目录」里出现两个独立下拉:一个在「正文里的目录」分组下,一个在「浮动目录」分组下
  2. 正文设默认显示 + 浮层设默认隐藏 → 打开一篇文章,正文里目录展开、浮层只露侧边标签
  3. 反过来(正文隐藏 + 浮层显示)→ 正文只露标题栏、浮层面板展开
  4. 两个设成同一个值也都正常
  5. 老配置不丢(这条最要紧):你原来如果是「默认隐藏」,升级后进后台看,两个下拉框显示的也该是隐藏,不是显示
  6. 关掉 JS(或拦截 toc.js)后,浮层默认态仍然正确,只是点不动
  7. 「恢复默认」后两项都回到默认显示

第 5 条是本版真正容易出问题的地方,麻烦重点看一眼。确认没问题我再关单。

## 3.2.59 已发布,请升级后验收 **发布通道**:走 `/theme-update/` 正常更新通道。服务器上的 `wp-content/themes/kratos_yang/` **没有被碰过**,仍是 `3.2.58`,等你在后台点升级。 - `update.json` 现在是 `{"version":"3.2.59", download_url: .../kratos_yang-3.2.59.zip, md5: ba6abca49d5609b02bc754660c973b98}` - 包:`kratos_yang-3.2.59.zip`,4821394 字节,md5 `ba6abca49d5609b02bc754660c973b98` - 上一版包 `kratos_yang-3.2.58.zip` **保留着**(还停在旧版、后台缓存了旧 update.json 的人点升级不会 404) - readme:50 个版本标题(上一版 49 + 本版 1),历史一条没丢 代码提交:`d55667a`(3 文件 +175/−19),已推送。 --- ### 改了什么 **`inc/theme-toc.php`** - `toc_default` 一拆为二:`inline_default`(正文那份)、`float_default`(浮层那份) - 迁移段写成四分支,不是一句 `$pick()`: - ① 新键存在且合法 → 用它 - ② 新键存在但非法 → 回落**该键自己的**默认 - ③ 新键不存在、老键存在 → 用老键的值(← 老站点走这条) - ④ 都不存在 → 各键默认 为什么不能简单写 `$pick('inline_default', ...)`:`$pick` 在键不存在时直接取 `$d[$key]`,那样 ③ 会落进 ④,**老站点会被静默重置成 show**。 - `yang_toc_settings()` 的读库键列表里**继续保留 `'default'`**。不读它就不知道老配置里存了什么,迁移段拿不到值,老站点升级后默认开合被重置 —— 而且界面上一切正常,没人会发现。 - 两个消费点各读自己的键,互不引用:正文走 `inline_default`,浮层走 `float_default`。 - **新增 `yang_toc_admin_legacy_values()`,挂在 `option_kratos` filter 上(仅 `is_admin()` 时挂)**。这个函数是真实 WP 验证抓出来的,单里原本没写: 不挂它的话,老站点会出现「**页面按 hide 渲染、后台下拉框却显示 show**」。原因是后台框架取值顺序是「先取 `std`,有保存值才覆盖」,而库里只有 `toc_default`、没有新键 ⇒ 两个新框都落到 `std=show`。用户升级后第一眼看到的就是「我的设置没了」。 它只在**读取时**把老键的值投影到缺失的新键上,**库不动**,老键也**不删**(降级回 3.2.58 时旧版还读得到 `toc_default`)。 **`inc/theme-options.php`** - 两个独立下拉,分别落在「正文里的目录」「浮动目录」两个分组末尾 - 共用分组里「对两份同时生效」那句已经过时,改掉了 - `std` 与 `yang_toc_defaults()` 一致(都是 `show`) **`style.css`**:3.2.58 → 3.2.59。本版**没改前台 CSS**(`kratos.min.css` 与线上逐字节相同),**也没动 JS**(`assets/js/toc.js` 与线上逐字节相同)—— 默认态仍然纯粹靠服务端 class 直出,关掉 JS 也能看到正确默认态。 --- ### 验证数据 | 项 | 结果 | |---|---| | 桩判据 `_toc359_split_check.php` | **61 / 0** | | 反证 `_toc359_falsify.php` | **36 / 0**(16 组注入,全部有牙齿且红在预期判据上) | | 真实 WP 判据 `_toc359_wp_check.php` | **30 / 0**(PHP 8.5.12 + WP 7.1.3) | | 回归 `_toc330_logic.php` | **101 / 0** | | 回归 `_test_toc.php` | **53 / 0** | | 打包自检 `_mkzip359.py` | **42 / 0** | --- ### 本轮踩到的两个坑(值得记一笔) **① 判据脚本自己拿错了版本。** 第一轮发布失败在 R13~R16 四条,全是「改坏了但失败数没增加」,看上去像「投影函数的判据没牙齿」。差一点就去重写判据了。 实际错因是:服务器上那份 `_toc359_split_check.php` 是 24542 字节的**旧版(52 条)**,本地是 27647 字节的新版(61 条)。旧版里根本没有 K 组(投影函数那几条),改坏了当然不会红。而「52 条全过」也被当成「61 条全过」念过去了。 所以发布脚本现在会**硬判判据的条数**(桩 61 / WP 30 / 反证 16 组 36 查),不够就报「跑的是旧版判据,结论无效」。这是「判据选错靶子」的一个新变体 —— 不是验错了对象,是**验证者本身过期了**。 **② readme 关键词是我脑子里的话,不是文件里的话。** 第一轮另外 3 条失败是 readme 关键词:我写了「分别设置」「老配置」「is-open」。真实正文里是: - 「可以`<b>分别</b>设置`」—— 中间夹了标签,`grep -F 分别设置` 永远匹配不到 - 说的是「老**版本**只存了一个」「老**站点**升级后」,没有「老配置」这个词 - 说的是「直接写在页面 HTML 上的(**一个 class**)」,没写 `is-open` 三个词全部在正确文件上假红。改法是**每个词都用 `head -80 readme359.html | grep -oF` 逐条核过命中数**再写进脚本,不再凭印象。 --- ### 请你验收这几条(不关单,等你确认) 1. 「主题设置 → 自动目录」里出现**两个独立下拉**:一个在「正文里的目录」分组下,一个在「浮动目录」分组下 2. 正文设`默认显示` + 浮层设`默认隐藏` → 打开一篇文章,正文里目录展开、浮层只露侧边标签 3. 反过来(正文隐藏 + 浮层显示)→ 正文只露标题栏、浮层面板展开 4. 两个设成同一个值也都正常 5. **老配置不丢**(这条最要紧):你原来如果是「默认隐藏」,升级后进后台看,**两个下拉框显示的也该是隐藏**,不是显示 6. 关掉 JS(或拦截 `toc.js`)后,浮层默认态仍然正确,只是点不动 7. 「恢复默认」后两项都回到`默认显示` 第 5 条是本版真正容易出问题的地方,麻烦重点看一眼。确认没问题我再关单。
Author
Owner

按用户确认收尾,交付见上条发布评论。

交付版本:3.2.59(正文/浮层两份默认状态分别设置 + 老配置平滑迁移)

用户已验收,关闭本单。

按用户确认收尾,交付见上条发布评论。 交付版本:3.2.59(正文/浮层两份默认状态分别设置 + 老配置平滑迁移) 用户已验收,关闭本单。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/wordpress-kratos-yang#27