Files
mindfulness/spec_kit/Text Wrap/modules/overflow-fallback/plan.md
2026-02-10 11:39:33 +08:00

110 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# overflow-fallback技术计划
## 1. 计划目标
实现统一的“溢出与兜底”策略模块,用于在以下情况给出确定性且可解释的返回:
- 搜索器无法在 `<=maxLines` 覆盖到结束边界 `N`
- `lineMode=FIXED` 需要刚好 `maxLines` 但无解
- 测量不可用或失败导致无法执行宽度派约束(尤其 Widget
支持三种模式:
- `ELLIPSIS`:最后一行加省略号并保证不超宽(必要时回退移除 token 再加)
- `CLIP`:截断到 `maxLines`(不加省略号)
- `SYSTEM_DEFAULT`:算法层不插入换行,交给系统排版(仅在 meta 标记)
## 2. 对外输入/输出(与 spec 对齐)
### 2.1 输入
- `tokens: Token[]`
- `partialLayout?: { breaks: number[]; lines: Array<{ start; end; text? }> }`
- 若提供:表示搜索器的 best-effort可能未覆盖到 N
- `overflowMode: 'ELLIPSIS' | 'CLIP' | 'SYSTEM_DEFAULT'`
- `availableWidth: number`
- `maxLines: number`
- `lang: 'TC' | 'EN'`
- `context: 'APP' | 'WIDGET'`
- `ellipsisToken: string`(推荐 `"…"`,配置化)
- `measure?: { contextProfile; fontSpec; measureWidthImpl; widgetEnableMeasure? }`(用于“加省略号后再测量”)
- `reason: 'NO_CANDIDATE' | 'WIDTH_UNKNOWN' | 'TOO_LONG' | 'WIDOW' | 'PARTICLE' | string`
### 2.2 输出
统一返回:
- `result: { lines: string[]; wrappedText: string; meta: { fallback_type; overflow_type; reason } }`
其中:
- `fallback_type`: `NONE | RELAX_RULES | SYSTEM_DEFAULT`
- `overflow_type`: `NONE | ELLIPSIS | CLIP`
## 3. 核心行为细则(对应文档 12.x
### 3.1 overflow 判定
在本模块内不重新跑搜索,仅基于输入判断:
-`partialLayout` 覆盖到 `N`(即最后一行 `end==N`),则 overflow_type=NONE
- 否则为 overflow按 overflowMode 执行
### 3.2 SYSTEM_DEFAULT12.4A
- 返回 `lines=[原文单行]``wrappedText=原文`
- `meta.fallback_type='SYSTEM_DEFAULT'`
- `meta.overflow_type='NONE'`(因为不再输出算法换行;由 UI 决定是否完全交给系统)
- `meta.reason=输入 reason`
### 3.3 CLIP
-`partialLayout` 有 lines取前 `maxLines` 行,重组 `wrappedText=lines.join('\n')`
- 若无:返回单行原文
- `meta.overflow_type='CLIP'``fallback_type='NONE'``reason=输入 reason`
### 3.4 ELLIPSIS12.3/12.5
仅处理最后一行:
1. 选取 baseLines
- 优先使用 `partialLayout.lines`(若为空则把全文当单行)
- 截断到 `maxLines`(只在最后一行做 ellipsis
2. 清理规则(固定,确定性):
- 不输出 `" …"`:最后一行末尾空白先 trim
- 不输出 `",…"/"。…"`:若最后一行末尾是常见 TC 标点(`,。!?;:、`),则移除该标点再加 ellipsis
3. 宽度检查12.3
- 若提供测量能力且启用:
- 重新测量 `lastLine+ellipsisToken`
- 若超宽:按语言回退单位移除 token 再加省略号并重测
- EN按整词token
- TC按 graphemetoken
- 若测量不可用不做重测直接输出meta.reason 仍保留)
> 说明:首版不做“避免截断 emotionPhrase 的整段前移/整段省略”,该策略可在后续结合 scoring 决策升级,但必须保持确定性。
## 4. 代码落位(客户端)
- `client/src/features/textWrap/overflow/`
- `types.ts`
- `ellipsis.ts`
- `fallback.ts`入口applyOverflowFallback
- `index.ts`
- `__tests__/overflowFallback.test.ts`
## 5. 测试计划Vitest
- SYSTEM_DEFAULTlines 单行meta.fallback_type=SYSTEM_DEFAULT
- CLIP超过 maxLines 时截断行数
- ELLIPSIS
- 末尾空白去除,不输出 `" …"`
- 末尾 TC 标点去除,不输出 `",…"`
- 测量超宽时按 token 回退直到不超宽(用 mock measureWidthImpl
## 6. 完成定义DoD
- 三种 overflowMode 行为稳定且可解释
- ELLIPSIS 的清理与回退测量实现完毕(可测)
- 输出 meta 字段满足文档 12/14 的治理需求