AskaEth
9dee236778
feat(W69): 按契约 v0.89 的 <br> 更正与白名单收窄 —— <br> 改做气泡分隔符(与 <p> 同级)、撤掉 u/s
后端 `回执三十` / `回执三十一` 把 v0.89 两处更正了,本端照改。
一、`<br>` 不再是行内标签,而是与 `<p>` 同级的**气泡/消息分隔符**
(`回执三十一` 原话:「对消息内的 `<br>` 始终处理为多条消息隔断」)
1. 行内层(`InlineMarkup.kt`)整体移出:词表少一项、`InlineTag.Break` 与「`<br>` → `\n`」
那套解析/裁剪逻辑全删;白名单只剩五项 `b`/`strong`/`i`/`em`/`code`。
2. 改在气泡切分层:新增 `appendRegion`(`ChatContentParser.kt`),把每个文本区按 `BR_TAG_RE`
切开、段与段之间补 `Tok.Break`(既有 `<p>` 同款机制)。`<p>甲<br>乙</p>` / `甲<br>乙`
都是两条气泡;`<p>甲<br><br>乙</p>` 的中间空气泡照旧丢弃;`<br>` 两侧是空白不产多余气泡;
`<br>` / `<br/>` / `</br>`(含 `<br />` / `</br/>` / `<br class=x>` / 大写)等价。
3. 层序采用「**先按 `<p>`/`<br>` 切分,再对每一段各自做行内解析**」:`<b>甲<br>乙</b>` 两段各自
不平衡 ⇒ 两段都回落原文。理由写进 `appendRegion` 的 KDoc(「同级」本身就规定了层序;
一个气泡 = 一条消息,跨分隔符的标签在结构上不可能成立,后端剥标签同样是按单条消息判平衡;
实现上行内层逐气泡跑一次,一个字节都不用改)。
4. 流式侧跟上:`<br` / `<BR` / `</br` / `<br/` / `<br class=x` 这些残缺形态由
`couldBeLineBreakNamePrefix` 扣留(与 `BR_TAG_RE` 同口径);完整的 `<br>` 不入栈、直接放行。
不扣的话中间态会先把字面 `<br` 吐上屏、收口时再变成两条气泡——屏幕上的字会改口。
二、白名单**收窄到五项**(`回执三十`):`u` / `s` 从 `InlineStyle`、解析、渲染、测试里全撤
(`Underline` / `Strikethrough` 与 `MessageBubble` 的 `TextDecoration` 一并删净,不留死代码)。
现在 `<u>甲</u>` 走「白名单外 ⇒ 原样显示」,与 Web 端一致——多支持反而是制造跨端不一致。
其余口径一律不动:大小写不敏感、属性整段丢弃、不平衡整段降级为原文(粒度 = 该气泡正文)、
`<code>` 内不解析、白名单外字符一个不丢、`parts` 逐字原文、`runs` 为空时 UI 走原路。
`tokenize` 的 `<p>` 块切分 / `stripLooseTags` / `ContentAfterQuery` / `P_BLOCK_RE` / `ROLE_RE` /
星号语义 / `MessageEditText`(`<br>` 不进容差,只含 `<br>` 的消息仍是编辑框恒等路径)行为未改。
渲染仍是 `AnnotatedString` + `SpanStyle`,无新依赖、无 HTML 注入。
验收:`assembleDebug` 通过;`testDebugUnitTest` 全量 126 suites / 1564 tests / 0 failures / 0 errors。
`ChatContentParserTest` 新增 14 条(`<br>` 四情形逐个断言气泡数与文本、三种写法等价、大小写、
像标签但不是的 `<br2>`/`<boolean>`、跨分隔符标签两段各自回落、`parts` 不含结构、旁白跨分隔符依附、
流式完整/残缺两态、`<code>`/`<action>` 内也分隔、行内解析不看 `<br>`、复杂度预算);
`InlineMarkupTest` 删掉 6 条与 v0.89 冲突的(`<br>` 换行 4 条 + `u`/`s` 渲染 + `<b>甲<br>乙</b>` 单气泡
一条),新增 3 条(`u`/`s` 撤掉后走字面、`<br>` 在本层只是普通字符、`<br>` 在解析层真分成两条气泡)。