Repository navigation
fix(search): 高亮改为在原文上定位命中,修掉错高亮与实体边界 - #111
Merged
Merged
Conversation
旧实现是「先 esc() 再在已转义串上定位」(safe / safeNeedle),命中区间 因此是「转义后的形态」:& → & 的实体边界被切开(高亮范围与用户所见的 字符不对应);更严重的是大小写折叠会改变长度(İ → i̇,1 → 2),折叠串 索引与原文整体错位 —— 原文「İstanbul」搜「T」会高亮到字母「a」。 改为在**未转义原文**上定位命中,切片后**逐段** esc() 再包 <mark>;比较走 码点数组([...raw] + 逐码点 toLowerCase,长度变化时保留原码点 ⇒ 宁可漏 高亮也不错高亮),规避 String.slice 的 UTF-16 计数(𝔘 占 2)带来的错位。 XSS 不变式更清楚:<mark> 是本函数唯一插入的标签,每一段都过 esc()。 守卫(按红线 11「字符串存在断言是死测」,实质保证走行为探针): - tools/wb_search_probe.mjs 新增场景 highlight_hit_alignment:13 组 text/needle × 三条不变式(去 <mark> 后反转义 === 原文 ⇒ 永不切开实体; 每个 <mark> 内反转义 === needle ⇒ 不许错高亮;输出无可执行 <script>) + 两条等值断言(İstanbul 搜 t === İs<mark>t</mark>anbul; AT&T 搜 T&T === A<mark>T&T</mark>)。 - 另加两条反回退切片检查:旧标志 safe/safeNeedle MUST NOT 再现; MUST 含码点级展开(长度对齐的前提)。 - tests/test_search_ui.py 的旧 esc(text 字面守卫随实现形态改写为形态反回归 守卫,并把 highlight_hit_alignment 加进关键场景名清单(防删场景仍全绿)。 守卫自证:把 search.js 单独 stash 回退旧实现后,探针按预期抛错并 EXITCODE=1;恢复后全绿。临时复现脚本枚举 598 组用例,异常 0。 门禁:wb_search_probe 10/10、28 个 tools 探针全绿、半 A 1053 passed / 半 B 264 passed + 1 skipped(全量 1317 + 1 skipped,与 v5.16.0 同数:本轮 重写一条测试、未新增测试函数)、ruff 0、mypy 93 + 70 files 零错误。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
缺陷
static/js/search.js::_highlight旧实现是「先esc()再在已转义串上定位」(safe/safeNeedle)。命中区间因此是"转义后的形态",两个后果:&→&,高亮范围与用户所见的字符不对应。İ.toLowerCase() 长度 1→2),折叠串索引与原文整体错位。实测(切真实实现丢 node 跑 224 组text × needle):修法
在未转义原文上定位命中,切片后逐段
esc()再包<mark>;比较走码点数组([...raw]+ 逐码点toLowerCase,长度变化时保留原码点 ⇒ 宁可漏高亮也不错高亮),规避String.slice的 UTF-16 计数(𝔘占 2)造成的错位。XSS 不变式反而更清楚:
<mark>是本函数唯一插入的标签,每一段都过esc()。守卫(实质保证走行为探针,红线 11)
tools/wb_search_probe.mjs新增场景highlight_hit_alignment:13 组text/needle× 三条不变式(去<mark>后反转义 === 原文;每个<mark>内反转义 === needle;输出无可执行<script>)+ 两条等值断言。另加两条反回退切片检查(旧标志safe/safeNeedleMUST NOT 再现;MUST 含码点级展开)。tests/test_search_ui.py的旧esc(text字面守卫改写为形态反回归守卫,并把新场景加进关键场景名清单。守卫自证:把
search.js单独 stash 回退旧实现后探针按预期抛错、EXITCODE=1;恢复后全绿。临时复现脚本枚举 598 组用例,异常 0。门禁
wb_search_probe.mjs10/10;28 个tools/*.mjs探针全绿ruff check .0;mypy --follow-imports=skip tests93 files /mypy --strict delector tools70 files 零错误core.hooksPath=.githooks),本次提交未跳过备注
只动
static/、tools/、tests/与WORKMEMORY/,未发版(发布面五件套未动)。PROJECT_OVERVIEW开放待办里已划掉这条递延项。