跨端: 5 处 Unicode 符号当图标换成 AmIcon(并把判据扩到"排版符号"这一类)
起因:做邮件详情时顺手把 `Text('‹')` 换成 `AmIcon('chevronLeft')`,
想着"本仓不是有这条判据吗,怎么没抓到" —— 去看了判据,发现它**只扫 emoji 那一段**。
判据(`harmony-arkts.test.mjs:168`)扫的是 U+2600–27BF / U+2B00–2BFF / U+FE0F,
而漏网的 5 处全在这三段**之外**:
MainPage.ets Text('‹') 返回键(会话视图)
MainPage.ets Text('›') 会话别名前的小箭头
SettingsPage.ets Text('›') 「管理」的进入下一级指示
ComposePage.ets Text(' ▾') 账号下拉指示
MailDetailPage.ets Text('‹') 返回键
★ 它们与 emoji 那类**问题不同、但同样是"看着像图标其实不是"**:
· 字形宽窄由**字体**决定,与旁边 20vp 的 `AmIcon` 对不齐;
· 而且**WebUI 用的根本不是字符** —— `icons.tsx:135` 是
`ChevronRightIcon`(SVG)、`AccountSwitcher.tsx:84` 是它**转 90°**。
所以这同时是"两端不一致",不只是"字形不好看"。
修法:5 处一律换 `AmIcon`,并按 WebUI 的**同一形状**给:
· 两个返回键 → `chevronLeft` 20vp、可点区 `HEADER_BACK_HIT`(与 `AppHeader` 同值)
· 会话别名 / 「管理」→ `chevronRight`
· 账号下拉 → `chevronRight` + `rotate(open ? 90 : 0)`(照 `AccountSwitcher` 那句)
★ 判据扩了一类(`GLYPH_ISH`:U+2039/203A/00AB/00BB/25A0–25CF/25B2/25BC/25C0/25B6),
并保持原有那条边界不被破坏:**U+2190–21FF 基本箭头仍不扫** ——
`→`/`←` 在正文里是标点,扫进来会误伤大量正常文案(原注释里已经踩过这个坑)。
这次的符号是"单个字符整体",所以 `Text('a → b')` 这类多字符本来也不匹配。
★ 扩完之后判据**当场又抓到一处我自己没注意的**(`SettingsPage.ets` 的 `›`)——
这正是"把判据从'枚举实例'扩到'枚举类'立刻多抓一个"的现场证据,
也说明原来那三条区间是照"已经出现过的实例"框的,不是照"这类东西的共同形状"框的。
This commit is contained in:
@ -193,6 +193,28 @@ test('★ 图标不许用 Unicode 符号充当(`Text(\'✉\')` 会被系统渲
|
||||
* `!EMOJI_ISH.test('→')` 不成立 —— 断言写错就是断言写错,不能靠放宽它来「修」。)
|
||||
*/
|
||||
const EMOJI_ISH = /^[\u2600-\u27BF\u2B00-\u2BFF\uFE0F]$/;
|
||||
/*
|
||||
* ★★ 2026-09-20 补第二类:**排版符号当图标**(上面那一段只覆盖 emoji 那一类)。
|
||||
*
|
||||
* 实测漏网 4 处:`Text('‹')`(两处返回键)、`Text('›')`(会话别名前的小箭头)、
|
||||
* `Text(' ▾')`(账号下拉指示)—— 全都在上面那三个区间**之外**,所以一条都没抓到。
|
||||
*
|
||||
* 它们的问题与 emoji 不同、但同样是"看着像图标其实不是":
|
||||
* · `‹`/`›` 的字形宽窄**由字体决定**,与旁边 20 的 `AmIcon` 对不齐;
|
||||
* 而且它们**不是** WebUI 用的东西 —— WebUI 那里是
|
||||
* `ChevronLeftIcon` / `ChevronRightIcon`(SVG,见 `icons.tsx:135`),
|
||||
* 所以这属于"两端不一致",不只是"字形不好看"。
|
||||
* · `▾`(U+25BE)同理,WebUI `AccountSwitcher.tsx:84` 用的是
|
||||
* 同一个 `ChevronRightIcon` **转 90°**(不是一个专门的"下箭头")。
|
||||
*
|
||||
* 覆盖 U+2039/203A(single/double guillemets)、U+25B2–U+25CF(几何图形:
|
||||
* ▴▾◂▪● 这一类常被拿来当箭头/圆点)、U+2190–U+21FF 里的**单字符箭头**
|
||||
* 仍**不**扫(`→`/`←` 在正文里是标点,上面那段注释已经说明为什么不能扫)。
|
||||
* ★ 注意 `→` 在 `Text('a → b')` 这种**多条字符**里本来就不匹配
|
||||
* (正则要求 1–3 个字符**整体**是个符号),所以这里加 `←→` 也不会误伤;
|
||||
* 但为了不与上面那段注释自相矛盾,这一段仍然只管"几何/引号类"。
|
||||
*/
|
||||
const GLYPH_ISH = /^[\u2039\u203A\u00AB\u00BB\u25A0-\u25CF\u25B2\u25BC\u25C0\u25B6]$/;
|
||||
const hits = [];
|
||||
const walkDir = (dir) => {
|
||||
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
||||
@ -202,7 +224,8 @@ test('★ 图标不许用 Unicode 符号充当(`Text(\'✉\')` 会被系统渲
|
||||
const src = code(full);
|
||||
for (const m of src.matchAll(/Text\(\s*'([^']{1,3})'\s*\)/g)) {
|
||||
const ch = m[1];
|
||||
if (EMOJI_ISH.test(ch)) {
|
||||
const trimmed = ch.trim();
|
||||
if (EMOJI_ISH.test(ch) || GLYPH_ISH.test(trimmed)) {
|
||||
hits.push(`${e.name}: Text('${ch}')(U+${ch.codePointAt(0).toString(16).toUpperCase()})`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user