更新换行算法和APP-PUSH
This commit is contained in:
111
spec_kit/Text Wrap/modules/core-contract/plan.md
Normal file
111
spec_kit/Text Wrap/modules/core-contract/plan.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# core-contract(技术计划)
|
||||
|
||||
## 1. 计划目标
|
||||
|
||||
基于 `spec.md` 与 `设计说明文档/文档换行算法.md v1.2.1`,落地跨端一致的“基础口径与契约”,为后续断点生成、搜索与评分提供稳定输入与确定性工具,确保:
|
||||
|
||||
- EN/TC 的 **token 索引体系** 与断点 `pos` 语义固定
|
||||
- 文本 **可重组**:任意 `[start..end)` 区间可稳定还原为行文本
|
||||
- EN 关键词命中规则严格为 **全词等值匹配**(避免 substring 误伤)
|
||||
- 空白归一化策略可配置但默认一致(推荐 NORMALIZE)
|
||||
- 提供可复用的 **确定性比较工具**(用于 breaks 字典序/tieKey 比较)
|
||||
|
||||
## 2. 默认技术决策(本计划采用)
|
||||
|
||||
- **空白策略**:默认 `whitespacePolicy=NORMALIZE`
|
||||
- 行为:折叠连续空白为 1 个空格、去首尾空白
|
||||
- 并在 meta(后续模块)中打点 `hadMultiWhitespace`(本模块先预留布尔返回位)
|
||||
- **EN tokenize**:仅生成 WORD token(不生成 SPACE token),以空白分隔;标点按“极简派”保留在词内
|
||||
- **TC tokenize**:本模块只定义接口,具体分割由 `grapheme-segmentation` 提供
|
||||
- **EN 关键词命中**:`lowercase → strip 两端常见标点 → 等值比较`,禁止 contains/substring
|
||||
- **确定性比较**:breaks 字典序比较按“逐项比较 + 公共前缀相同则更短者更小”
|
||||
|
||||
## 3. 目录与产物
|
||||
|
||||
本子模块目录:
|
||||
|
||||
- `spec_kit/Text Wrap/modules/core-contract/spec.md`
|
||||
- `spec_kit/Text Wrap/modules/core-contract/plan.md`(本文)
|
||||
|
||||
建议未来代码落位(实现阶段再定,不在本计划强制):
|
||||
|
||||
- `client/src/features/textWrap/core/`(或 `client/src/utils/textWrap/`)
|
||||
|
||||
## 4. 设计与实现要点(按落地顺序)
|
||||
|
||||
### 4.1 文本预处理:normalizeWhitespace
|
||||
|
||||
实现 `normalizeWhitespace(text) -> { normalizedText, hadMultiWhitespace }`:
|
||||
|
||||
- 规则:
|
||||
- 把任意连续空白(空格/制表/换行等)折叠为单个空格
|
||||
- 去除首尾空白
|
||||
- 注意:
|
||||
- 该规范会改变输入文本;必须作为“算法契约”的一部分固定下来
|
||||
- 若后续产品需要保留原始空白,则走 `PRESERVE` 分支并输出 `rawSeparators`(见 4.3)
|
||||
|
||||
### 4.2 EN tokenize:word tokens(极简派)
|
||||
|
||||
实现 `tokenizeEN(normalizedText) -> tokens[]`:
|
||||
|
||||
- 以空格分隔生成 token
|
||||
- token 只包含 WORD,标点视为词内字符(例如 `tired.`、`Wait...`、`hello—world`、`don't` 都是单 token)
|
||||
- 输出 token 的 `text/start/end`(start/end 为原始或 normalized 的字符区间,需固定口径;建议以 normalizedText 为基准)
|
||||
|
||||
### 4.3 文本重组:joinTokens
|
||||
|
||||
实现 `joinTokens(tokens, start, end, separators?) -> string`:
|
||||
|
||||
- EN 默认:使用单空格 `" "` join `[start..end)` 的 token.text
|
||||
- 若 `whitespacePolicy=PRESERVE`:
|
||||
- 需要 `rawSeparators[i]` 表示 tokens[i] 与 tokens[i+1] 间的原始分隔符
|
||||
- 重组时按 separators 拼接(本计划仅定义接口与行为)
|
||||
|
||||
### 4.4 EN 关键词命中:normalizeENKeyword + matchENKeyword
|
||||
|
||||
实现:
|
||||
|
||||
- `normalizeENKeyword(tokenText) -> string`
|
||||
- `lowercase`
|
||||
- `strip` 两端常见标点(集合需配置化并全端一致,默认参考文档:`, . ! ? : ; " ' … — – ( ) [ ] { }`)
|
||||
- `matchENKeyword(tokenText, keyword) -> boolean`
|
||||
- `normalizeENKeyword(tokenText) === normalizeENKeyword(keyword)`
|
||||
- 禁止 `includes/contains` 类 substring 命中
|
||||
|
||||
### 4.5 断点/区间的索引契约
|
||||
|
||||
固化约定(后续模块必须复用,不得自行发挥):
|
||||
|
||||
- token 索引:`tokens[0..N-1]`
|
||||
- 断点 `pos`:位于 token 边界,切分为 `[0..pos)` 与 `[pos..N)`
|
||||
- 行区间:`[start..end)` 表示 `tokens[start] ... tokens[end-1]`
|
||||
|
||||
## 5. 回归用例与验证方式
|
||||
|
||||
### 5.1 必测示例(EN)
|
||||
|
||||
- `"I am so tired"` → tokens=`[I, am, so, tired]`
|
||||
- `pos=2` → `"I am"` / `"so tired"`
|
||||
- 标点极简派:
|
||||
- `"tired."` 为单 token
|
||||
- 关键词命中:
|
||||
- keyword=`"but"`:`"but,"` 命中;`"rebuttal"` 不命中
|
||||
|
||||
### 5.2 确定性检查
|
||||
|
||||
- 同一输入在同一配置下多次调用:
|
||||
- `normalizedText`、`tokens[]`、`joinTokens()`、`matchENKeyword()` 输出完全一致
|
||||
|
||||
## 6. 风险与规避
|
||||
|
||||
- **start/end 索引口径漂移**:若不同端选择以原始 text 或 normalizedText 计数,可能导致 span 对不齐
|
||||
- 规避:本模块明确 start/end 以 normalizedText 为准(或在实现阶段统一选择一种并写入 README/注释)
|
||||
- **标点集合不一致**:strip 集合若跨端不同会导致命中差异
|
||||
- 规避:将 `punctuationStripSetEN` 写入配置并版本化,禁止散落常量
|
||||
|
||||
## 7. 完成定义(DoD)
|
||||
|
||||
- `core-contract/spec.md` 中定义的输入/输出与验收条目均有可运行的最小实现或可验证的约束说明
|
||||
- EN tokenize / 空白归一化 / 关键词命中 / breaks 字典序比较口径写清楚且可复现
|
||||
- 关键示例用例可在本地/CI 以单元测试或脚本方式验证(实现阶段落地)
|
||||
|
||||
59
spec_kit/Text Wrap/modules/core-contract/spec.md
Normal file
59
spec_kit/Text Wrap/modules/core-contract/spec.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# core-contract(子模块规范)
|
||||
|
||||
## 子模块名称
|
||||
|
||||
core-contract(核心口径与契约)
|
||||
|
||||
## 目标描述
|
||||
|
||||
定义并固化跨端一致的“基础口径”,为后续断点生成、搜索与评分提供统一契约,避免实现偏差:
|
||||
|
||||
- **索引体系**:EN/TC 的 token 与断点 `pos` 语义
|
||||
- **文本重组**:从 token 区间稳定重组回行文本
|
||||
- **规范化**:空白归一化策略(默认折叠空白、去首尾)
|
||||
- **EN 关键词命中规则**:全词等值匹配(`lowercase → strip 两端常见标点 → 等值比较`),禁止 substring/contains
|
||||
- **配置与版本**:`configVersion` 的语义与回溯字段;全端一致的默认值入口
|
||||
- **确定性比较**:layout tie-break 的字典序比较口径(作为后续模块复用工具)
|
||||
|
||||
本模块不负责“换行搜索”,只负责**定义数据结构与基础函数**。
|
||||
|
||||
## 输入/输出定义
|
||||
|
||||
### 输入
|
||||
|
||||
- `text: string`
|
||||
- `lang: 'TC' | 'EN'`
|
||||
- `options?: { preserveRawSeparators?: boolean }`
|
||||
- `config: { punctuationStripSetEN: string[]; whitespacePolicy: 'NORMALIZE' | 'PRESERVE' }`
|
||||
|
||||
### 输出
|
||||
|
||||
- `normalizedText: string`
|
||||
- `tokens: Array<{ text: string; start: number; end: number }>`
|
||||
- EN:token 仅为 WORD(不产生 SPACE token;标点视为词内字符)
|
||||
- TC:token 为 grapheme cluster(具体分割由 `grapheme-segmentation` 模块实现/提供)
|
||||
- `rawSeparators?: string[]`
|
||||
- 可选:当选择保留原始空白时,输出 token 间分隔符映射
|
||||
- 基础工具函数(逻辑输出):
|
||||
- `joinTokens(start, end) -> string`
|
||||
- `normalizeENKeyword(tokenText) -> string`
|
||||
- `matchENKeyword(tokenText, keyword) -> boolean`
|
||||
|
||||
## 验收标准(可验证)
|
||||
|
||||
- **索引语义一致**:
|
||||
- EN:`"I am so tired"` tokens=`[I, am, so, tired]`,断点 `pos=2` 必然切为 `"I am"` / `"so tired"`
|
||||
- TC:断点 `pos` 表示在第 `pos` 个 grapheme 之前断开
|
||||
- **EN 标点极简派一致**:
|
||||
- `"tired."` 作为一个 token;断点只允许在词与词之间
|
||||
- **EN 关键词命中无误伤**:
|
||||
- keyword=`"but"`:`"but,"` 命中;`"rebuttal"` 不命中
|
||||
- **空白归一化确定性**:
|
||||
- 输入含多空格/首尾空白时,输出 `normalizedText` 可预测且稳定
|
||||
- **工具函数确定性**:相同输入在多次调用与多端实现中输出一致
|
||||
|
||||
## 依赖与关联
|
||||
|
||||
- **被依赖**:`breakpoint-candidates`、`scoring-tiebreak`、`search-engine-*`、`overflow-fallback`、`integration`
|
||||
- **依赖**:TC token 分割依赖 `grapheme-segmentation`
|
||||
|
||||
150
spec_kit/Text Wrap/modules/core-contract/tasks.md
Normal file
150
spec_kit/Text Wrap/modules/core-contract/tasks.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# core-contract(任务清单)
|
||||
|
||||
> 对应计划:`spec_kit/Text Wrap/modules/core-contract/plan.md`
|
||||
>
|
||||
> 状态含义:`[ ]` 未完成,`[x]` 已完成。
|
||||
> 执行完本清单后,需要在 `spec_kit/overview.md` 的 `Text Wrap` 条目下补充“已完成编码/任务执行完毕”的标记(见最后一节)。
|
||||
|
||||
---
|
||||
|
||||
## 0. 任务标记规则
|
||||
|
||||
- 用勾选框标记执行状态:
|
||||
- `[ ]` 未完成
|
||||
- `[x]` 已完成
|
||||
- 每个任务必须可独立验收(有明确产出与检查方式)。
|
||||
- 涉及“口径”的任务,必须在代码注释中写清楚(简体中文),避免后续模块实现漂移。
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档对齐(先把口径写死,避免实现漂移)
|
||||
|
||||
- [x] 1.1 复核 `core-contract/spec.md` 与 `core-contract/plan.md` 的一致性
|
||||
- **检查点**:
|
||||
- `whitespacePolicy`(NORMALIZE/PRESERVE)语义一致
|
||||
- EN token 规则为“极简派”(不拆标点、不生成 SPACE token)
|
||||
- EN 关键词命中为“全词等值匹配”(禁止 substring)
|
||||
- breaks 字典序比较规则清晰且无歧义
|
||||
- **验收**:两份文档无冲突描述;关键字段命名一致。
|
||||
|
||||
- [x] 1.2 明确 `start/end` 的索引口径(以 normalizedText 为基准)并写入代码注释与 README(如有)
|
||||
- **原因**:跨端 span/调试定位会依赖该口径
|
||||
- **验收**:任意 token 的 `start/end` 都可映射到同一份文本基准(normalizedText)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 目录与代码骨架(客户端侧优先落地)
|
||||
|
||||
> 说明:当前仓库已有 `client/src/features/*` 结构,Text Wrap 建议也放到 `features/` 下,便于后续 Home/Widget 复用。
|
||||
|
||||
- [x] 2.1 新建目录 `client/src/features/textWrap/core/`
|
||||
- **产出**(建议文件):
|
||||
- `types.ts`:Token/Config/Options 类型
|
||||
- `normalizeWhitespace.ts`
|
||||
- `tokenizeEN.ts`
|
||||
- `joinTokens.ts`
|
||||
- `enKeyword.ts`(normalizeENKeyword/matchENKeyword)
|
||||
- `compare.ts`(breaks 字典序比较)
|
||||
- `index.ts`(统一导出)
|
||||
- **验收**:目录存在且可被 TS 正常 import(不报路径错误)。
|
||||
|
||||
- [x] 2.2 定义 `Token` 与基础配置类型(只含 core-contract 需要的字段)
|
||||
- **要求**:
|
||||
- `Token` 至少包含 `text/start/end`
|
||||
- `CoreConfig` 至少包含 `whitespacePolicy` 与 `punctuationStripSetEN`
|
||||
- **验收**:类型定义满足后续函数签名需要,且命名清晰。
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心函数实现(纯函数 + 确定性)
|
||||
|
||||
- [x] 3.1 实现 `normalizeWhitespace(text)`(默认 NORMALIZE)
|
||||
- **规则**:
|
||||
- 连续空白折叠为单个空格
|
||||
- 去除首尾空白
|
||||
- 返回 `hadMultiWhitespace`(用于后续 meta 打点)
|
||||
- **验收**:
|
||||
- 输入 `" a b \n c "` 输出 `"a b c"`
|
||||
- `hadMultiWhitespace` 在出现折叠/trim 时为 true
|
||||
|
||||
- [x] 3.2 实现 `tokenizeEN(normalizedText)`(极简派)
|
||||
- **规则**:
|
||||
- 以空格切分为 WORD tokens
|
||||
- 标点作为 token.text 的一部分(不拆)
|
||||
- 不生成 SPACE token
|
||||
- **验收**:
|
||||
- `"I am so tired"` → `[I, am, so, tired]`
|
||||
- `"tired."` 为单 token
|
||||
|
||||
- [x] 3.3 实现 `joinTokens(tokens, start, end, separators?)`
|
||||
- **规则**:
|
||||
- 默认用单空格 join `[start..end)` 的 token.text
|
||||
- `start/end` 为半开区间,越界/空区间需有明确行为(建议:空区间返回空字符串,交由上层硬约束处理)
|
||||
- **验收**:
|
||||
- tokens=`[I, am, so, tired]`,`join(0,2)` 为 `"I am"`
|
||||
|
||||
- [x] 3.4 实现 EN 关键词命中:`normalizeENKeyword` + `matchENKeyword`
|
||||
- **规则**:
|
||||
- `lowercase`
|
||||
- strip 两端常见标点(使用配置 `punctuationStripSetEN`,全端一致)
|
||||
- 等值比较(禁止 substring)
|
||||
- **验收**:
|
||||
- keyword=`but`:`but,` 命中;`rebuttal` 不命中
|
||||
|
||||
- [x] 3.5 实现 breaks 字典序比较 `compareBreaksLexicographically(a, b)`
|
||||
- **规则**:
|
||||
- 从 index=0 起逐项比较,首个不同元素更小者更小
|
||||
- 公共前缀相同则更短数组更小
|
||||
- **验收**:
|
||||
- `[2] < [3]`
|
||||
- `[2] < [2, 5]`
|
||||
- `[2, 3] > [2]`
|
||||
|
||||
---
|
||||
|
||||
## 4. 单元测试(Vitest,纯函数为主)
|
||||
|
||||
- [x] 4.1 新建测试目录 `client/src/features/textWrap/core/__tests__/`
|
||||
- **验收**:测试文件可被现有 test runner 发现。
|
||||
|
||||
- [x] 4.2 为 `normalizeWhitespace` 增加用例
|
||||
- **覆盖**:多空格、换行、首尾空白、空字符串、全空白字符串
|
||||
- **验收**:测试断言输出字符串与 `hadMultiWhitespace` 符合预期。
|
||||
|
||||
- [x] 4.3 为 `tokenizeEN` + `joinTokens` 增加用例
|
||||
- **覆盖**:普通句子、带标点的 token、单词间多个空格(先 normalize 再 tokenize)
|
||||
- **验收**:tokens 序列与 join 后文本完全一致且确定。
|
||||
|
||||
- [x] 4.4 为 `matchENKeyword` 增加用例
|
||||
- **覆盖**:大小写、两端标点、误伤样例(rebuttal vs but)
|
||||
- **验收**:命中与不命中行为符合 spec。
|
||||
|
||||
- [x] 4.5 为 breaks 字典序比较增加用例
|
||||
- **验收**:比较规则在多组数组上输出稳定顺序。
|
||||
|
||||
---
|
||||
|
||||
## 5. 最终自检清单(合入前)
|
||||
|
||||
- [x] 5.1 `tsc --noEmit` 通过(或项目既有 TS 检查命令通过)
|
||||
- **验收**:无类型错误。
|
||||
|
||||
- [x] 5.2 `vitest` 通过(或项目既有测试命令通过)
|
||||
- **验收**:新增用例全部通过,不影响现有测试。
|
||||
|
||||
- [x] 5.3 代码注释口径检查(简体中文)
|
||||
- **检查点**:
|
||||
- EN 极简派与“断点只在词间”
|
||||
- 全词等值匹配(禁止 substring)
|
||||
- `start/end` 基于 normalizedText 的口径说明
|
||||
- **验收**:后续模块开发者只看代码也不会产生歧义。
|
||||
|
||||
---
|
||||
|
||||
## 6. 文档回写(任务清单执行完毕后必须做)
|
||||
|
||||
- [x] 6.1 在 `spec_kit/overview.md` 的 `Text Wrap` 条目下补充执行状态
|
||||
- **建议写法**:
|
||||
- 增加一行:`- **已完成编码(阶段性)**:core-contract(核心口径与契约)`
|
||||
- **验收**:overview 能反映该子模块已完成,便于全局追踪。
|
||||
|
||||
Reference in New Issue
Block a user