Files
Cyrene-For-Android/app
AskaEth 4b19278733 feat(W68): 行内标签按契约 v0.89 对齐 —— 大小写不敏感、属性一律丢弃、结构不平衡整段降级、补 u/s 与 </br>
后端 2026-10-07 傍晚把行内标签升成契约 v0.89(推库 `2dae469`),本端四处按它对齐。

1. 标签名大小写不敏感(`<B>` / `<STRONG>` / `<Br>` 都认)
   消费侧与流式**扣留**侧一起改,两边同源:`parseInlineTag` 与
   `couldBeInlineTagNamePrefix` / `isTagNameLetter` 收在 `InlineMarkup.kt` 一份,
   `isPotentialTagPrefix` 引用它。原来扣留侧只扫 `a..z`,若只改消费侧,`<B` / `<b class`
   这种残缺形态就会在中间态被当正文吐上屏、等 `>` 到了再吃掉——屏幕上显示过的字当场改口。
   段落/旁白标签(`<p>` / `<action>` / `<narration>`)仍只认小写,既有契约逐字未改。

2. 补 `u` / `s`:`InlineStyle` 加 Underline / Strikethrough;`MessageBubble.inlineBody`
   落到 `TextDecoration.Underline` / `LineThrough`(两者叠加时给两条线,不二选一)。

3. 属性一律不解析:白名单标签只取标签名,`<b class="x" onclick="y">` 就是粗体,属性整段丢掉。
   形状判据:名字后必须是 `>`、空白或 `/`,所以 `<boolean>` / `<br2>` 仍是普通文本。
   `inlineTagEnd` 那扇定宽窗换成「扫到 `>` 或下一个 `<` 为止」(属性没有长度上界),仍是线性。

4. 结构不平衡 ⇒ **该气泡正文整段降级为原文**(未闭合 / 落单闭标签 / 交错;`<br>` 也一起放弃)。
   取代 W67 的局部降级。粒度 = 该气泡的 `body`(不是整条消息、也不是单个 `<p>` 块),
   理由写进 `parseInlineMarkup` 的 KDoc,由 `theFallbackCoversOnlyTheBubbleThatIsBroken` 钉住。
   白名单外的尖括号(`<script>` 等)不参与结构判定,按契约第 1 条原样显示、字符一个不丢。

另:`</br>` 与 `<br>` / `<br/>` 等价(HTML5);`<code>` 内的内容仍不解析、也不算结构,
与契约第 3 条方向一致但不是同一条规则(原因写在 KDoc 里)。
渲染仍是 `AnnotatedString` + `SpanStyle`,不引入任何 HTML 注入路径、不新增依赖。
`parts`(编辑/搜索读的逐字原文)、`runs` 为空时 UI 走原路、`tokenize` / `stripLooseTags` /
`ContentAfterQuery` / `P_BLOCK_RE` / `ROLE_RE` / 星号语义 全部未动。

验收:`assembleDebug` 通过;`testDebugUnitTest` 全量 126 suites / 1553 tests / 0 failures / 0 errors。
`InlineMarkupTest` 新增 11 条(大小写、属性、四种不平衡形状整段降级、气泡粒度、白名单外字符、
`u`/`s`、`</br>`、流式大小写+属性不吐标签),与 v0.89 冲突的老断言按新口径改写并在 KDoc 里
写明「口径在 W68 按契约 v0.89 变更、为什么」,不冲突的一条都没放松。
2026-10-07 17:25:26 +08:00
..