自动目录:正文显示与左右浮动应可同时开启,且各自独立选择对齐方向 #1

Closed
opened 2026-10-25 05:18:52 +00:00 by laoyang · 4 comments
Owner

背景

文章目录(TOC)目前「显示位置」是一个三选一的下拉:正文中间 / 页面左侧 / 页面右侧,三者互斥。选了左侧或右侧,正文里一份目录都不放。

实际需求是:在正文中显示 与 左右浮动显示 是两个互相独立的能力,可以同时开启。两者不是「页面的哪一栏」,而是两类不同的呈现方式。

需求

1. 显示方式改为两个独立开关(可同时勾选)

  • 在正文中显示 —— 勾选后在正文流里插入一份目录
  • 浮动显示 —— 勾选后在页面边缘输出可滑出的浮动目录面板

两者互不互斥:允许只开其一,也允许全开。全开时同一篇文章里正文一份 + 浮动一份,两份目录指向同一批锚点。

2. 勾选「在正文中显示」后,再展开两个子选项

  • 正文中的对齐:靠左 / 靠右

    已与需求方确认:指目录块在正文容器内部的左对齐或右对齐(即显示在文章页面的左侧还是右侧),受正文栏宽度约束,不是浮动到页面边缘。

  • 插入位置:文章开头 / 第一个标题(H1 或 H2)之前 / 文章结尾

3. 勾选「浮动显示」后,再展开子选项

  • 浮动方向:左侧 / 右侧

4. 保持不变的既有能力

  • 添加方式:手动([TOC])/ 自动
  • 默认状态:默认显示 / 默认隐藏
  • 目录标题、收录层级(H1~H4)、是否显示序号

关键约束

  1. 手写 [TOC] 永远优先:正文里只要有手写标记,就按标记位置渲染,不再自动插第二份。老文章升级后不能突然多出目录。
  2. 两个开关全关时,正文不做任何改动:连标题 id 都不补,避免改变页面上已有的锚点与选择器行为。
  3. 浮动面板只在正文确实被处理过时才出现:正文没走 the_content(缓存插件 / OEmbed / get_the_content())时标题没有 id,浮动面板条目会全部点不动,且外观完全正常、极难排查 —— 这种情况宁可不显示。
  4. 同一份扫描结果:正文目录与浮动目录必须共用同一次标题扫描结果,否则重名标题会算出不同 id,点进去跳不动。
  5. 正文内的目录块不参与浮动定位:收起态不得以 opacity: 0 之类方式占据原位吃掉正文点击。

影响范围(初判)

  • inc/theme-options.php:toc_place 单下拉拆成「开关 + 子选项」结构
  • inc/theme-toc.php:yang_toc_plan() 决策表、yang_toc_inject() 插入逻辑、浮动渲染前置闸门
  • assets/css/toc.css / assets/js/toc.js:正文内对齐与浮动面板需能共存
  • 后台联动脚本:字段显隐依赖勾选状态

验收标准

  • 四种组合(只正文 / 只浮动 / 全开 / 全关)行为各自正确、互不干扰
  • 全开时,正文目录与浮动目录指向的锚点 id 完全一致
  • 手写 [TOC] 的页面,无论后台怎么配,都不出现第二份目录
  • 全关时,正文 HTML 与未启用目录时逐字节相同
  • 正文对齐靠左 / 靠右在真实渲染下能量到左右位移
## 背景 文章目录(TOC)目前「显示位置」是一个三选一的下拉:**正文中间 / 页面左侧 / 页面右侧**,三者互斥。选了左侧或右侧,正文里一份目录都不放。 实际需求是:**在正文中显示** 与 **左右浮动显示** 是两个互相独立的能力,可以同时开启。两者不是「页面的哪一栏」,而是两类不同的呈现方式。 ## 需求 ### 1. 显示方式改为两个独立开关(可同时勾选) - [ ] **在正文中显示** —— 勾选后在正文流里插入一份目录 - [ ] **浮动显示** —— 勾选后在页面边缘输出可滑出的浮动目录面板 两者互不互斥:允许只开其一,也允许全开。全开时同一篇文章里正文一份 + 浮动一份,两份目录指向同一批锚点。 ### 2. 勾选「在正文中显示」后,再展开两个子选项 - **正文中的对齐**:靠左 / 靠右 > 已与需求方确认:指目录块在**正文容器内部**的左对齐或右对齐(即显示在文章页面的左侧还是右侧),受正文栏宽度约束,不是浮动到页面边缘。 - **插入位置**:文章开头 / 第一个标题(H1 或 H2)之前 / 文章结尾 ### 3. 勾选「浮动显示」后,再展开子选项 - **浮动方向**:左侧 / 右侧 ### 4. 保持不变的既有能力 - 添加方式:手动(`[TOC]`)/ 自动 - 默认状态:默认显示 / 默认隐藏 - 目录标题、收录层级(H1~H4)、是否显示序号 ## 关键约束 1. **手写 `[TOC]` 永远优先**:正文里只要有手写标记,就按标记位置渲染,不再自动插第二份。老文章升级后不能突然多出目录。 2. **两个开关全关时,正文不做任何改动**:连标题 id 都不补,避免改变页面上已有的锚点与选择器行为。 3. **浮动面板只在正文确实被处理过时才出现**:正文没走 `the_content`(缓存插件 / OEmbed / `get_the_content()`)时标题没有 id,浮动面板条目会全部点不动,且外观完全正常、极难排查 —— 这种情况宁可不显示。 4. **同一份扫描结果**:正文目录与浮动目录必须共用同一次标题扫描结果,否则重名标题会算出不同 id,点进去跳不动。 5. **正文内的目录块不参与浮动定位**:收起态不得以 `opacity: 0` 之类方式占据原位吃掉正文点击。 ## 影响范围(初判) - `inc/theme-options.php`:`toc_place` 单下拉拆成「开关 + 子选项」结构 - `inc/theme-toc.php`:`yang_toc_plan()` 决策表、`yang_toc_inject()` 插入逻辑、浮动渲染前置闸门 - `assets/css/toc.css` / `assets/js/toc.js`:正文内对齐与浮动面板需能共存 - 后台联动脚本:字段显隐依赖勾选状态 ## 验收标准 - 四种组合(只正文 / 只浮动 / 全开 / 全关)行为各自正确、互不干扰 - 全开时,正文目录与浮动目录指向的锚点 id 完全一致 - 手写 `[TOC]` 的页面,无论后台怎么配,都不出现第二份目录 - 全关时,正文 HTML 与未启用目录时逐字节相同 - 正文对齐靠左 / 靠右在真实渲染下能量到左右位移
Author
Owner

需求澄清记录

首版需求描述与实现现状存在理解偏差,经与需求方确认,澄清如下。

一、最初的偏差

需求方原话 最初的错误理解 实际含义
「左侧/右侧显示」 目录浮动到页面边缘 目录块在正文容器内的左对齐 / 右对齐

原先被实现为「三选一」的 正文中间 / 页面左侧 / 页面右侧,把「放在哪里」和「怎么对齐」混成了同一个选项。实际这是两个正交的维度。

二、确认后的结构

  1. 两个显示开关,互相独立、可同时勾选

    • 在正文中显示
    • 浮动显示
  2. 「在正文中显示」的子选项

    • 对齐:靠左 / 靠右(正文容器内部对齐,已确认)
    • 插入位置:文章开头 / 第一个标题(H1 或 H2)之前 / 文章结尾
  3. 「浮动显示」的子选项

    • 方向:左侧 / 右侧
  4. 两者全开时是正常的合法状态,不是冲突:正文一份 + 浮动一份,共用同一批锚点。

三、关于老配置迁移

已确认:无需处理。不考虑从旧版 toc_place 三选一配置迁移,直接按新结构实现即可。

四、流程约定(本项目通用)

  1. 每个需求先在 Gitea 建工单,记下编号
  2. 完成后的提交信息带上工单编号,便于追溯「哪个提交完成了哪个需求」
  3. 需求方确认无误后再关闭工单

注:本评论由讨论内容整理而成,已去除其中的认证凭据等敏感信息。

## 需求澄清记录 首版需求描述与实现现状存在理解偏差,经与需求方确认,澄清如下。 ### 一、最初的偏差 | 需求方原话 | 最初的错误理解 | 实际含义 | |---|---|---| | 「左侧/右侧显示」 | 目录浮动到页面边缘 | 目录块**在正文容器内**的左对齐 / 右对齐 | 原先被实现为「三选一」的 `正文中间 / 页面左侧 / 页面右侧`,把「放在哪里」和「怎么对齐」混成了同一个选项。实际这是两个正交的维度。 ### 二、确认后的结构 1. **两个显示开关,互相独立、可同时勾选** - 在正文中显示 - 浮动显示 2. **「在正文中显示」的子选项** - 对齐:靠左 / 靠右(正文容器内部对齐,已确认) - 插入位置:文章开头 / 第一个标题(H1 或 H2)之前 / 文章结尾 3. **「浮动显示」的子选项** - 方向:左侧 / 右侧 4. **两者全开时是正常的合法状态**,不是冲突:正文一份 + 浮动一份,共用同一批锚点。 ### 三、关于老配置迁移 已确认:**无需处理**。不考虑从旧版 `toc_place` 三选一配置迁移,直接按新结构实现即可。 ### 四、流程约定(本项目通用) 1. 每个需求先在 Gitea 建工单,记下编号 2. 完成后的提交信息带上工单编号,便于追溯「哪个提交完成了哪个需求」 3. 需求方确认无误后再关闭工单 --- > 注:本评论由讨论内容整理而成,已去除其中的认证凭据等敏感信息。
Author
Owner

完成情况

已实现并发布 3.2.31,提交 4a2d62b(提交信息带 #1)。

一、按本单澄清的两点落地

  1. 「在正文中显示」与「浮动显示」做成两个独立勾选,互斥关系取消;两个都勾就同时出现两份。
  2. 正文内的「靠左 / 靠右」= 目录块在正文容器内部左右对齐,不是浮到页边。

二、后台控件(共 10 个,同一标签页)

控件 作用 默认
在正文中显示 开关 勾上
正文中的对齐 靠左 / 靠右 靠左
自动插入位置 开头 / 第一个标题之前 / 结尾 第一个标题之前
浮动显示 开关 不勾
浮动方向 页面左侧 / 页面右侧 页面左侧
添加方式 / 默认状态 / 标题 / 层级 / 序号 沿用 3.2.30 —

子选项随开关显隐:「正文中的对齐」「自动插入位置」跟「在正文中显示」;「浮动方向」跟「浮动显示」。

三、两处需要记录的实现要点

  1. 对齐必须有宽度上限。块级盒子默认撑满正文栏,此时 margin:auto 没有剩余空间可分配,只写 margin 的「靠左/靠右」是空操作。已加 max-width: min(100%, 28em),窄屏自动退化整栏宽。
  2. 手写 [TOC] 语义收窄。以前它会让整份自动处理全停(连带 rail=false);现在只手管正文那一份,浮动仍由开关独立决定。这样「某篇精确控制正文位置」与「全站边上都有目录」可并存。

四、顺手修掉的一处默认值错配

checkbox 用 !empty() 判断会把「键不存在」和「键明确为空」混成一件事 → 新装站点后台框显示勾上、页面却不出目录。已改用 array_key_exists() 区分的三态判断。

五、老配置

按讨论结论不做迁移,3.2.30 的旧位置设置直接作废。默认 inline=1 / float=0,升级后页面与升级前一致。

六、验证结果

层 正向 反向
逻辑(设置组合) 101/0 15/15
旧回归 53/0 —
静态契约(选项↔代码↔默认值) 58/0 11/11
后台几何+交互(四象限联动) 70/0 11/11
浮动侧栏几何 73/0 8/8
正文对齐几何 23/0 5/5(含阴性对照)
包内容契约 59/0 9/9

正文对齐那条量的是真实像素位移:同一份正文、同样的宽度,靠右比靠左的目录块左边缘右移 348px,宽度不变(不是被压窄)。只断言 data-align 字符串存在是不够的 —— 属性对而画面不动正是这个需求最典型的假绿。

七、发布

  • 包 kratos_yang.zip 公网 md5 与本地一致;解包核对版本 3.2.31、旧字段 0 残留。
  • readme 已更新,历史 21 个版本条目全部保留。
  • update.json 最后一步切换,两个链接均可下载。
  • 已清 transient。按新流程未解包覆盖服务器主题目录,请在后台「外观 → 主题」里自行升级。
## 完成情况 已实现并发布 3.2.31,提交 `4a2d62b`(提交信息带 #1)。 ### 一、按本单澄清的两点落地 1. 「在正文中显示」与「浮动显示」做成**两个独立勾选**,互斥关系取消;两个都勾就同时出现两份。 2. 正文内的「靠左 / 靠右」= 目录块在正文容器内部左右对齐,不是浮到页边。 ### 二、后台控件(共 10 个,同一标签页) | 控件 | 作用 | 默认 | |---|---|---| | 在正文中显示 | 开关 | 勾上 | | 正文中的对齐 | 靠左 / 靠右 | 靠左 | | 自动插入位置 | 开头 / 第一个标题之前 / 结尾 | 第一个标题之前 | | 浮动显示 | 开关 | 不勾 | | 浮动方向 | 页面左侧 / 页面右侧 | 页面左侧 | | 添加方式 / 默认状态 / 标题 / 层级 / 序号 | 沿用 3.2.30 | — | 子选项随开关显隐:「正文中的对齐」「自动插入位置」跟「在正文中显示」;「浮动方向」跟「浮动显示」。 ### 三、两处需要记录的实现要点 1. **对齐必须有宽度上限**。块级盒子默认撑满正文栏,此时 margin:auto 没有剩余空间可分配,只写 margin 的「靠左/靠右」是空操作。已加 `max-width: min(100%, 28em)`,窄屏自动退化整栏宽。 2. **手写 [TOC] 语义收窄**。以前它会让整份自动处理全停(连带 rail=false);现在只手管正文那一份,浮动仍由开关独立决定。这样「某篇精确控制正文位置」与「全站边上都有目录」可并存。 ### 四、顺手修掉的一处默认值错配 checkbox 用 `!empty()` 判断会把「键不存在」和「键明确为空」混成一件事 → 新装站点后台框显示勾上、页面却不出目录。已改用 `array_key_exists()` 区分的三态判断。 ### 五、老配置 按讨论结论**不做迁移**,3.2.30 的旧位置设置直接作废。默认 inline=1 / float=0,升级后页面与升级前一致。 ### 六、验证结果 | 层 | 正向 | 反向 | |---|---|---| | 逻辑(设置组合) | 101/0 | 15/15 | | 旧回归 | 53/0 | — | | 静态契约(选项↔代码↔默认值) | 58/0 | 11/11 | | 后台几何+交互(四象限联动) | 70/0 | 11/11 | | 浮动侧栏几何 | 73/0 | 8/8 | | **正文对齐几何** | 23/0 | 5/5(含阴性对照) | | 包内容契约 | 59/0 | 9/9 | 正文对齐那条**量的是真实像素位移**:同一份正文、同样的宽度,靠右比靠左的目录块左边缘右移 348px,宽度不变(不是被压窄)。只断言 `data-align` 字符串存在是不够的 —— 属性对而画面不动正是这个需求最典型的假绿。 ### 七、发布 - 包 `kratos_yang.zip` 公网 md5 与本地一致;解包核对版本 3.2.31、旧字段 0 残留。 - readme 已更新,历史 21 个版本条目全部保留。 - update.json 最后一步切换,两个链接均可下载。 - 已清 transient。按新流程**未解包覆盖**服务器主题目录,请在后台「外观 → 主题」里自行升级。
Author
Owner

补充修正(3.2.32):浮动目录不存在「手动 / 自动」这一维度

这轮讨论澄清了一个语义问题,结论整理如下。

1. 你的原话要点

  • 浮动窗口(显示在左右的那两个目录)没有「自动 / 不自动」的概念。
  • 只有正文里才可能有手动 —— 因为只有正文里你才有地方写 [TOC] 那个标记。
  • 浮动的这两份,你没有地方写这两个标记,所以它没有那个选项。
  • 浮动窗口要么显示、要么不显示;如果显示,就让它显示在左边还是右边 —— 就这一个选项,没有其他的了。
  • 「默认显示还是默认隐藏」这个选项仍然保留,还是有用的。

2. 核查结果:代码本来就是对的

实测把「添加方式」在手动 / 自动之间切换,浮动目录的有无与左右方向均不受影响:

添加方式 正文里写没写 [TOC] 浮动是否出现 浮动方向 正文内插入点
手动 没写 出现 左 无
自动 没写 出现 左 第一个标题之前
手动 写了 出现 右 手写标记处
自动 写了 出现 右 手写标记处

即 rail(是否浮动)只由「浮动显示」开关决定,与 mode 正交。这一版没有改动任何判断逻辑。

3. 真正的问题:后台的排列方式让人误解

原来十项排成一长列,顺序是:
在正文中显示 → 正文中的对齐 → 自动插入位置 → 浮动显示 → 浮动方向 → 添加方式 → 默认状态 → …

「添加方式」「自动插入位置」排在浮动选项之后,视觉上像是两种目录共用的设置 —— 于是会让人以为浮动目录也分手动、自动。

4. 改法:按归属切成三段(不新增标签页、不新增设置项)

在同一个「自动目录」标签页内,用框架的 info 类型加三行小标题:

  1. 正文里的目录 —— 在正文中显示 / 正文中的对齐 / 添加方式 / 自动插入位置
  2. 浮动目录 —— 浮动显示 / 浮动方向
  3. 两份目录共用的设置 —— 默认状态 / 目录标题 / 收录标题级别 / 显示序号

用 info 而不是 heading,是因为 heading 会另起一个标签页(框架里 case "heading" 会新建 #options-group-N),而 info 只渲染成一行 <h4> + 说明,既不进标签页菜单也不生成表单字段 —— 正是需要的组内小标题。

5. 文案同步收窄

  • 「添加方式」:补一句「本项只管正文里的那一份;浮动目录不受它影响(浮动目录没有地方写 [TOC],勾了就一直在)」。
  • 「浮动显示」:补一句「它没有手动/自动之分:勾了就一直在,不勾就不出现」。
  • 「自动插入位置」:标明手动方式下插入点由你自己写的 [TOC] 决定;清掉上一版残留的「目录位置 = 正文中间」这种已经不存在的说法(那个三选一在 3.2.31 已作废)。

6. 「默认状态」确认对两种目录都有效(保留,未改)

正文那一份与浮动那一份读的是同一个设置,所以两种目录都会按这里选的状态决定「一进来是展开还是先收起」。你的要求是保留,实现上也确实是这样,无需改动。

7. 顺带修掉的真 bug

上一版选项定义里 「自动插入位置」被写了两遍(后一个会覆盖前一个),后台会渲染出两个同名下拉框。已删掉多余的一份,并加了检查项防止再犯。

8. 验收情况

  • 前台零变化:这一版只动后台分组与文案,未改任何渲染逻辑、选项 id、存库键或默认值。
  • 后台几何已实测:三段小标题都真实渲染、有可见高度与标题文字,且十个控件在纵向上都排在自己那一段的标题之后(归属靠位置判定,不靠记忆);「添加方式」「自动插入位置」确实排在「浮动目录」标题之前。
  • 反向验证覆盖:把三段小标题藏掉 / 写成 heading / 删掉一段 / 把「添加方式」搬回浮动选项之后 —— 每种都必须让检查变红,全部按预期红在对应判据上。

9. 交付

  • 版本 3.2.32,提交 71f8a73(信息带 #1),已推送 main。
  • 发布方式:只更新 theme-update/ 下的 zip + readme + update.json,未解包覆盖服务器主题目录,你在后台自己点升级即可。
## 补充修正(3.2.32):浮动目录不存在「手动 / 自动」这一维度 这轮讨论澄清了一个语义问题,结论整理如下。 ### 1. 你的原话要点 - 浮动窗口(显示在左右的那两个目录)**没有「自动 / 不自动」的概念**。 - 只有**正文里**才可能有手动 —— 因为只有正文里你才有地方写 `[TOC]` 那个标记。 - 浮动的这两份,**你没有地方写这两个标记**,所以它没有那个选项。 - 浮动窗口要么**显示**、要么**不显示**;如果显示,就让它显示在**左边还是右边** —— 就这一个选项,没有其他的了。 - **「默认显示还是默认隐藏」这个选项仍然保留,还是有用的。** ### 2. 核查结果:代码本来就是对的 实测把「添加方式」在手动 / 自动之间切换,浮动目录的**有无**与**左右方向**均不受影响: | 添加方式 | 正文里写没写 [TOC] | 浮动是否出现 | 浮动方向 | 正文内插入点 | |---|---|---|---|---| | 手动 | 没写 | 出现 | 左 | 无 | | 自动 | 没写 | 出现 | 左 | 第一个标题之前 | | 手动 | 写了 | 出现 | 右 | 手写标记处 | | 自动 | 写了 | 出现 | 右 | 手写标记处 | 即 `rail`(是否浮动)**只由「浮动显示」开关决定**,与 `mode` 正交。**这一版没有改动任何判断逻辑。** ### 3. 真正的问题:后台的排列方式让人误解 原来十项排成一长列,顺序是: `在正文中显示` → `正文中的对齐` → `自动插入位置` → `浮动显示` → `浮动方向` → **`添加方式`** → `默认状态` → … 「添加方式」「自动插入位置」排在浮动选项**之后**,视觉上像是两种目录共用的设置 —— 于是会让人以为浮动目录也分手动、自动。 ### 4. 改法:按归属切成三段(不新增标签页、不新增设置项) 在同一个「自动目录」标签页内,用框架的 `info` 类型加三行小标题: 1. **正文里的目录** —— 在正文中显示 / 正文中的对齐 / 添加方式 / 自动插入位置 2. **浮动目录** —— 浮动显示 / 浮动方向 3. **两份目录共用的设置** —— 默认状态 / 目录标题 / 收录标题级别 / 显示序号 用 `info` 而不是 `heading`,是因为 `heading` 会另起一个标签页(框架里 `case "heading"` 会新建 `#options-group-N`),而 `info` 只渲染成一行 `<h4>` + 说明,既不进标签页菜单也不生成表单字段 —— 正是需要的组内小标题。 ### 5. 文案同步收窄 - **「添加方式」**:补一句「本项**只管正文里的那一份**;浮动目录不受它影响(浮动目录没有地方写 `[TOC]`,勾了就一直在)」。 - **「浮动显示」**:补一句「**它没有手动/自动之分**:勾了就一直在,不勾就不出现」。 - **「自动插入位置」**:标明手动方式下插入点由你自己写的 `[TOC]` 决定;清掉上一版残留的「目录位置 = 正文中间」这种已经不存在的说法(那个三选一在 3.2.31 已作废)。 ### 6. 「默认状态」确认对两种目录都有效(保留,未改) 正文那一份与浮动那一份读的是**同一个设置**,所以两种目录都会按这里选的状态决定「一进来是展开还是先收起」。你的要求是保留,实现上也确实是这样,无需改动。 ### 7. 顺带修掉的真 bug 上一版选项定义里 **「自动插入位置」被写了两遍**(后一个会覆盖前一个),后台会渲染出两个同名下拉框。已删掉多余的一份,并加了检查项防止再犯。 ### 8. 验收情况 - 前台**零变化**:这一版只动后台分组与文案,未改任何渲染逻辑、选项 id、存库键或默认值。 - 后台几何已实测:三段小标题都真实渲染、有可见高度与标题文字,且十个控件**在纵向上都排在自己那一段的标题之后**(归属靠位置判定,不靠记忆);「添加方式」「自动插入位置」确实排在「浮动目录」标题之前。 - 反向验证覆盖:把三段小标题藏掉 / 写成 heading / 删掉一段 / 把「添加方式」搬回浮动选项之后 —— 每种都必须让检查变红,全部按预期红在对应判据上。 ### 9. 交付 - 版本 3.2.32,提交 `71f8a73`(信息带 `#1`),已推送 main。 - 发布方式:只更新 `theme-update/` 下的 zip + readme + update.json,**未解包覆盖**服务器主题目录,你在后台自己点升级即可。
Author
Owner

用户确认需求完成,关闭此单。3.2.31(正文/浮动拆成两个独立开关)+ 3.2.32(后台按归属切成三段)均已发布。

用户确认需求完成,关闭此单。3.2.31(正文/浮动拆成两个独立开关)+ 3.2.32(后台按归属切成三段)均已发布。
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#1