feat(channelbridge): u 加回 IM 出站的行内白名单(改为六项)
主人 2026-10-07 裁定「下划线确实可以保留」。 - 行内白名单:b / strong / i / em / code / u(六项) - s 仍在外(逐字原样保留,含大写 <S>)—— 有一个守门变异专门锁这条 - 行为改动只有一行(case 列表加 "u"),其余是注释与测试同步
This commit is contained in:
1 parent
a19d12b228
commit
74c9f2d8df
2 files changed
+16
-9
No files matched your search
@@ -15,9 +15,10 @@ import (
|
||||
// 与星号块 ⇒ `<b>18:35</b>` 连标签一起字面发给微信/QQ,用户看到裸标签。
|
||||
//
|
||||
// 🔴 处置口径(必须与契约 v0.89 及 Web 端渲染器逐条一致,否则同一段文本两端显示不同):
|
||||
// 1. 行内白名单 = **五项** `b` / `strong` / `i` / `em` / `code`;**成对且平衡**的
|
||||
// 1. 行内白名单 = **六项** `b` / `strong` / `i` / `em` / `code` / `u`;**成对且平衡**的
|
||||
// 白名单标签 ⇒ **剥标签、留内部文本**(微信/QQ 不支持 HTML,没有别的选择);
|
||||
// 2. **白名单外**的标签(`<script>` / `<div>` / `<u>` / `<s>` …)⇒ **逐字原样保留**
|
||||
// (`u` 由主人 2026-10-07 裁定加回 —— 下划线要保留渲染;`s` 仍不在白名单内。)
|
||||
// 2. **白名单外**的标签(`<script>` / `<div>` / `<s>` …)⇒ **逐字原样保留**
|
||||
// (它们是文本,一个字符不丢);
|
||||
// 3. **结构不平衡**(未闭合 / 落单闭标签 / 交错)⇒ **整段保持原样**(契约把这一条的
|
||||
// 粒度列为实现细节,本端与 Web 端取同一粒度,保证两端对同一段文本给出同一结果);
|
||||
@@ -45,10 +46,10 @@ func isBreakTagName(name string) bool {
|
||||
return strings.EqualFold(name, inlineBreakTag)
|
||||
}
|
||||
|
||||
// isPairedInlineTag 报告标签名是否属于需配对处理的行内白名单(契约 v0.89:五项)。
|
||||
// isPairedInlineTag 报告标签名是否属于需配对处理的行内白名单(契约 v0.89:六项)。
|
||||
func isPairedInlineTag(name string) bool {
|
||||
switch name {
|
||||
case "b", "strong", "i", "em", "code":
|
||||
case "b", "strong", "i", "em", "code", "u":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// 本文件覆盖 IM 出站的行内标签白名单(契约 §6 v0.89:`b` / `strong` / `i` / `em` /
|
||||
// `code` **五项**)与 `<br>` 的**气泡/消息分隔符**语义(与 `<p>` 同级)。
|
||||
// `code` / `u` **六项**)与 `<br>` 的**气泡/消息分隔符**语义(与 `<p>` 同级)。
|
||||
// 口径与 Web 端渲染器(frontend/web/src/lib/inlineMarkup.ts)逐条对齐。
|
||||
|
||||
// TestInlineTags_RealSampleParagraph 复现主人 2026-10-07 报障的真样例:
|
||||
@@ -35,7 +35,7 @@ func TestInlineTags_RealSampleParagraph(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestInlineTags_PairedWhitelistTagsStripped 报告五项白名单的成对标签只去标签、
|
||||
// TestInlineTags_PairedWhitelistTagsStripped 报告六项白名单的成对标签只去标签、
|
||||
// 留内部文本,且大小写不敏感。
|
||||
func TestInlineTags_PairedWhitelistTagsStripped(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -45,6 +45,9 @@ func TestInlineTags_PairedWhitelistTagsStripped(t *testing.T) {
|
||||
{"<i>斜</i>", "斜"},
|
||||
{"<em>强调</em>", "强调"},
|
||||
{"<code>go test</code>", "go test"},
|
||||
{"<u>下划线</u>", "下划线"},
|
||||
{"<U>大写下划线</U>", "大写下划线"},
|
||||
{"<u class=x>属性也丢</u>", "属性也丢"},
|
||||
{"<B>大写</B>", "大写"},
|
||||
{"<STRONG>大写</STRONG>", "大写"},
|
||||
{"<b><i>嵌套</i></b>", "嵌套"},
|
||||
@@ -138,7 +141,7 @@ func TestBreakTags_NoLiteralLeak(t *testing.T) {
|
||||
|
||||
// TestInlineTags_NonWhitelistKeptVerbatim 白名单外标签是文本,逐字不丢 ——
|
||||
// 这与 `<p>` / `<action>`(角色扮演/段落标记,要剥)刻意不同。
|
||||
// `u` / `s` 自 v0.89 修订起**不在**白名单内,因此也按文本逐字保留。
|
||||
// `s` **不在**白名单内(主人只批了下划线 `u`),因此也按文本逐字保留。
|
||||
func TestInlineTags_NonWhitelistKeptVerbatim(t *testing.T) {
|
||||
t.Parallel()
|
||||
cases := []string{
|
||||
@@ -147,15 +150,18 @@ func TestInlineTags_NonWhitelistKeptVerbatim(t *testing.T) {
|
||||
"<a href=\"http://x\">链接</a>",
|
||||
"<img src=x onerror=y>",
|
||||
"<iframe src=x></iframe>",
|
||||
"<u>下划线</u>",
|
||||
"<s>删除线</s>",
|
||||
"<U>大写也不认</U>",
|
||||
"<S>大写删除线</S>",
|
||||
}
|
||||
for _, in := range cases {
|
||||
if got := stripNarration(in); got != in {
|
||||
t.Errorf("stripNarration(%q) = %q, want verbatim", in, got)
|
||||
}
|
||||
}
|
||||
// `u` 已由主人 2026-10-07 裁定加回白名单 ⇒ 正向断言:剥标签、留文本。
|
||||
if got := stripNarration("<u>下划线</u>"); got != "下划线" {
|
||||
t.Errorf(`stripNarration("<u>下划线</u>") = %q, want %q`, got, "下划线")
|
||||
}
|
||||
// 白名单与外标签混排:只动白名单那对,其余逐字保留。
|
||||
in := "她说了 <b>这样</b> 和 <script>alert(1)</script> 两回事"
|
||||
want := "她说了 这样 和 <script>alert(1)</script> 两回事"
|
||||
|
||||
Reference in new issue
Block a user