更新换行算法和APP-PUSH

This commit is contained in:
吕新雨
2026-02-10 11:39:33 +08:00
parent f03d36b5e9
commit ee2d9f44ea
105 changed files with 9967 additions and 233 deletions

View File

@@ -0,0 +1,164 @@
# breakpoint-candidates任务清单
> 对应计划:`spec_kit/Text Wrap/modules/breakpoint-candidates/plan.md`
>
> 状态含义:`[ ]` 未完成,`[x]` 已完成。
> 执行完本清单后,需要在 `spec_kit/overview.md` 的 `Text Wrap` 条目下补充“已完成编码/任务执行完毕”的标记(见最后一节)。
---
## 0. 任务标记规则
- 用勾选框标记执行状态:
- `[ ]` 未完成
- `[x]` 已完成
- 每个任务必须可独立验收(有明确产出与检查方式)。
- 所有代码注释必须为简体中文,并把“去重/裁剪/排序/过滤”的**确定性口径**写死,避免后续模块漂移。
---
## 1. 前置对齐(口径必须写死)
- [x] 1.1 明确 `pos` 的边界范围:仅输出 `pos ∈ [1, N-1]`
- **原因**`pos=0/N` 属于搜索器的起止边界,不应作为候选断点
- **验收**:单测覆盖 `N=0/1/2` 等边界输入,不会输出非法 pos。
- [x] 1.2 明确 `forbiddenBreakRanges` 的区间口径(写死一种)
- **本任务采用**:闭区间 `start <= pos && pos <= end`
- **验收**单测能验证闭区间边界命中start/end 两端都被剔除)。
---
## 2. 目录与代码骨架(客户端侧实现)
- [x] 2.1 新建目录 `client/src/features/textWrap/breakpoints/`
- **产出**(建议文件):
- `types.ts`Breakpoint/Config/Constraints
- `generateBreakpoints.ts`(主入口,纯函数)
- `tcCandidates.ts`TCPUNCT/SPACE/BALANCE 生成)
- `enCandidates.ts`ENSPACE 断点生成)
- `filterAndDedup.ts`(过滤/去重/排序/裁剪)
- `__tests__/generateBreakpoints.test.ts`
- `index.ts`(统一导出)
- **验收**目录存在TS 可正常 import不报路径错误
- [x] 2.2 定义最小类型集合(只覆盖本模块)
- **必须包含**
- `Breakpoint = { pos: number; kind: 'PUNCT'|'SPACE'|'BALANCE'|'OTHER'; priority: number }`
- `BreakpointMeta = { pruned: boolean; originalCount: number; finalCount: number }`
- `Constraints = { forbiddenBreakRanges?: Array<{ start: number; end: number }>; protectedPhrases?: string[] }`
- `Config = { tcMaxCandidateBreaks: number; tcPunctuations: string[]; balanceRange: number }`
- **验收**:后续实现文件引用类型清晰,且不会引入无关依赖。
---
## 3. 断点生成(按语言)
- [x] 3.1 EN 候选断点生成kind=SPACEpriority 固定)
- **规则**
-`i in 1..N-1` 生成 `pos=i, kind='SPACE'`
- `priority=10`(写死)
- **验收**
- tokens=[I, am, so, tired] → pos=[1,2,3]
- [x] 3.2 TC标点后断点kind=PUNCT
- **规则**
-`tokens[i].text ∈ tcPunctuations`,生成 `pos=i+1, kind='PUNCT', priority=30`
- **验收**
- tokens=['我','好','累','','😮‍💨'] → 包含 `pos=4(kind=PUNCT)`
- [x] 3.3 TC空格后断点kind=SPACE
- **规则**
-`tokens[i].text === ' '`,生成 `pos=i+1, kind='SPACE', priority=20`
- **验收**:构造含空格 tokens断点生成稳定且不越界。
- [x] 3.4 TCBALANCE 断点生成kind=BALANCE
- **规则**
- `targetLines = min(maxLines, N)`
-`lineIndex in 1..targetLines-1`
- `idealPos = round((N * lineIndex) / targetLines)`
-`[idealPos-balanceRange, idealPos+balanceRange]` 内生成 pos裁剪到 `[1,N-1]`
- `priority=5`
- **验收**
- 无标点长文本:可生成接近理想位置的候选断点(数量受控、确定性)。
---
## 4. 过滤、去重、裁剪与最终排序(必须确定性)
- [x] 4.1 forbiddenBreakRanges 过滤(闭区间)
- **规则**:命中任一 range 则剔除该 `pos`
- **验收**range 边界 start/end 都会剔除。
- [x] 4.2 去重:同 pos 只保留一个 breakpoint
- **规则**
- priority 更高者优先
- priority 相同按 kind 固定序:`PUNCT > SPACE > BALANCE > OTHER`
- **验收**:构造同 pos 多来源候选,结果唯一且确定性。
- [x] 4.3 TC 裁剪:超过 `tcMaxCandidateBreaks` 时截断(确定性排序后截断)
- **排序 key写死**
- priority 降序
- distToIdeal 升序(到最近 idealPos 的距离;无 idealPos 时为大值)
- pos 升序
- **验收**
- 当候选数 > 上限时finalCount==tcMaxCandidateBreaks
- 截断结果稳定(同输入同输出)
- [x] 4.4 最终输出排序:按 `pos` 升序
- **验收**:无论内部裁剪排序如何,最终输出始终 `pos` 升序。
- [x] 4.5 meta 输出
- **规则**
- `originalCount`:过滤/去重/裁剪前的候选数量
- `finalCount`:最终输出数量
- `pruned = finalCount < originalCount`
- **验收**:单测断言 meta 与候选数量一致。
---
## 5. 单元测试Vitest
- [x] 5.1 新建 `generateBreakpoints.test.ts`,覆盖 EN 基础用例
- **验收**pos=[1,2,3] 且升序。
- [x] 5.2 覆盖 TCPUNCT/SPACE/BALANCE 生成
- **验收**:关键样例存在,且 BALANCE 不越界。
- [x] 5.3 覆盖 forbiddenBreakRanges闭区间
- **验收**start/end 命中都剔除。
- [x] 5.4 覆盖去重与 kind 优先级
- **验收**:同 pos 多候选时输出唯一且正确 kind。
- [x] 5.5 覆盖 TC 裁剪上限与确定性
- **验收**
- 数量上限严格生效
- 同输入多次调用输出完全一致(包括 meta
---
## 6. 最终自检清单(合入前)
- [x] 6.1 `npm test` 通过(包含本模块新增用例)
- **验收**:不影响现有测试文件。
- [x] 6.2 `npx tsc --noEmit` 通过(或项目既有 TS 检查命令通过)
- **验收**:无类型错误。
- [x] 6.3 注释与口径自检(简体中文)
- **检查点**
- `pos` 边界范围 `[1,N-1]`
- forbiddenBreakRanges 闭区间口径
- 去重优先级与裁剪排序 key 的固定顺序
- **验收**:后续模块开发者只看代码也不会产生歧义。
---
## 7. 文档回写(任务清单执行完毕后必须做)
- [x] 7.1 在 `spec_kit/overview.md``Text Wrap` 条目下补充执行状态
- **建议写法**
- 增加一行:`- **已完成编码(阶段性)**breakpoint-candidates候选断点生成与裁剪`
- **验收**overview 能反映该子模块已完成,便于全局追踪。