refactor: 專案整理階段一——確認缺陷修復(jinze 冪等/pill 自身 avoid)+死代碼清理

下游審計(4 路並行測繪 + 逐條源碼複驗)之階段一:落地已複驗確認之缺陷與低風險
清理;架構統一(透明判定單一真相源)與文檔重整留待階段二/三。

修復(複驗確認):
・jinze 二次 render(未 revert)產生巢狀 jz-jinze、違反 I6 冪等——守衛改判 parent
  自身即本 pass 產物(isJz(parent, PASS)),已綁定內容不再重包(實測 jz-jinze 3→6 已修)。
・processPills 漏檢 avoidsSelf——自身命中 avoid(如 <code data-jz-skip>)之 pill 仍被補
  間隙(isAvoided 只查祖先、不含自身,同「下游問題六」型)。processPills + root 自處理
  分支補 avoidsSelf 檢查。
・三分類互斥:CODE/KBD 自 DEFAULT_SKIP_TAGS 移除——二者已由預設 pillSelector
  "code, kbd" 以 pill 機制涵蓋(內部不可見+兩端補隙+斷 run/相鄰),再列 skipTags 致
  同元素既 pill 又 avoid、pill 兩端間隙被 avoid 抹掉(違反互斥,且令上一項修復誤傷普通
  code)。移除後普通 code 為純 pill、正常補隙;唯自身 data-jz-skip 者不補(即上項修復)。

清理:
・刪零引用死代碼 createMarker/ANY_CJK/BD_ALL/BD_CLASS_NAMES/CreateOptions.attrs;
  isJz 由 jinze 冪等守衛啟用、脫離死代碼。
・死旗標 biaodian/emphasis/ruby 補 @reserved 註記(比照 hanging;點明與
  charClass.biaodian 撞名異義,避免混淆)。
・JzKind 補註 data-jz-kind 第三值 "splitoff"(split.ts 直接設、不經 createJz);
  longWord/orphan 冗餘 ===false 特判簡化(feature() 已對 false 回 false)。

複驗後重新定性(不照單全收):
・jinze 跨透明元素邊界避頭尾漏綁(你好<strong>。世界</strong> 之句末點號漏綁)——**真
  缺陷**,但正解須改 jinze 之父級處理模型(穿越透明包裹上攀評估跨層綁定),與階段二
  「透明判定單一真相源」一併處理更穩;forbiddenBreak 下探草稿已還原、缺口以註解標記。
・lineedge edgeRect 攀穿 isolate——**非缺陷**:edgeRect 為物理版面測量(getClientRects),
  isolate 斷的是邏輯 run/相鄰,其內部字元之物理行首/行尾判定須跨 <mark> 找真實相鄰
  內容(否則「文字<mark>「引」</mark>」之 「 誤判行首而錯收左半)。初評誤判、已還原並補註。

新增 3 回歸測試(jinze 冪等、預設 code 為 pill 非 skipTags、自身 avoid 之 pill 不補隙);
119 測試全綠、tsc + esbuild 構建乾淨。
This commit is contained in:
2026-07-07 20:28:11 +08:00
parent 6c57461b61
commit 30a11b5d6e
13 changed files with 114 additions and 81 deletions
+6 -2
View File
@@ -252,7 +252,10 @@ function processPills(root: Element, finder: Finder, boundarySelector: string, p
{
root.querySelectorAll(boundarySelector).forEach((pill) =>
{
if (finder.isAvoided(pill) || finder.insidePill(pill) || !finder.inScope(pill))
// 自身即 avoid(如 pill 帶 data-jz-skip)亦不補間隙——isAvoided 只查祖先鏈、
// 不含自身,須另判 avoidsSelf(下游問題六同型:漏此半則 avoid 對自身形同虛設)。
if (finder.avoidsSelf(pill) || finder.isAvoided(pill)
|| finder.insidePill(pill) || !finder.inScope(pill))
{
return;
}
@@ -332,7 +335,8 @@ export const spacingPass: StandalonePass = {
// 遇巢狀 block 仍會 flush,故與上面逐 block 不重複;行內 root 通常無 block 子)。
if (!options.finder.blockTags.has(ctx.root.nodeName)
&& finder.featureEnabledFor(ctx.root, PASS)
&& finder.inScope(ctx.root) && !finder.isAvoided(ctx.root))
&& finder.inScope(ctx.root)
&& !finder.avoidsSelf(ctx.root) && !finder.isAvoided(ctx.root))
{
processBlock(ctx.root, finder, R);
}