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:
@@ -520,6 +520,21 @@ test("jinze:revert 還原(無 jz-jinze/jz-char,文字回原樣)", () =
|
||||
assert.equal(document.querySelector("p").textContent, "他說好。」嗎");
|
||||
});
|
||||
|
||||
test("jinze 冪等:二次 render(未 revert)不巢狀增殖 jz-jinze(守衛 parent 自身即產物)", () =>
|
||||
{
|
||||
// 缺守衛時,二次 render 之 jz-char 其父正是上輪之 jz-jinze,會被再包一層(3→6 巢狀)。
|
||||
const { document } = setupDom('<p lang="zh-Hant">漢字。「引文」結束</p>');
|
||||
const jz = createJuzhen({ spacing: false, longWord: false });
|
||||
jz.render(document.body);
|
||||
const after1 = countTag(document.body, "jz-jinze");
|
||||
jz.render(document.body); // 二次 render,未 revert
|
||||
assert.equal(countTag(document.body, "jz-jinze"), after1, "jz-jinze 數不增(不重複包裹)");
|
||||
assert.equal(countTag(document.body, "jz-jinze jz-jinze"), 0, "無巢狀 jz-jinze");
|
||||
jz.revert(document.body);
|
||||
assert.equal(countTag(document.body, "jz-jinze"), 0, "revert 完全還原");
|
||||
assert.equal(document.querySelector("p").textContent, "漢字。「引文」結束");
|
||||
});
|
||||
|
||||
// ----- 作用域與分塊(§3.6)-----
|
||||
|
||||
test("scope.include:未命中子樹不處理", () =>
|
||||
@@ -1037,6 +1052,27 @@ test("問題六:skipAttribute 自身命中——同 avoid,不切分不下潛
|
||||
assert.equal(countTag(document.body, '[data-jz-kind="splitoff"]'), 0);
|
||||
});
|
||||
|
||||
test("三分類互斥:預設 code 為 pill(非 skipTags)——兩端補間隙、內部不可見", () =>
|
||||
{
|
||||
// code/kbd 由預設 pillSelector 涵蓋、**不再列入 skipTags**(避免同元素既 pill 又
|
||||
// avoid、pill 兩端間隙被 avoid 抹掉之互斥違反)。故預設下 code 為純 pill。
|
||||
const { document } = setupDom("<p>看<code>x</code>這</p>");
|
||||
createJuzhen({ jiya: false, longWord: false, jinze: false }).render(document.body);
|
||||
const p = document.querySelector("p");
|
||||
assert.equal(countTag(p, "jz-hws"), 2, "code(pill)兩端補間隙(看|code、code|這)");
|
||||
assert.equal(countTag(p, "code jz-hws"), 0, "code 內部無間隙(pill 內部不可見)");
|
||||
});
|
||||
|
||||
test("三分類互斥:pill 自身 avoid(data-jz-skip)→ 兩端不補間隙(processPills 查 avoidsSelf)", () =>
|
||||
{
|
||||
// isAvoided 只查祖先鏈、不含自身;自身命中 avoid 之 pill 須另判 avoidsSelf,否則
|
||||
// avoid 對自身形同虛設(下游問題六同型)。
|
||||
const { document } = setupDom("<p>看<code data-jz-skip>x</code>這</p>");
|
||||
createJuzhen({ jiya: false, longWord: false, jinze: false }).render(document.body);
|
||||
assert.equal(countTag(document.querySelector("p"), "jz-hws"), 0,
|
||||
"自身 avoid 之 pill 兩端不補間隙");
|
||||
});
|
||||
|
||||
test("問題六:相鄰兩 pill——descend 不刺穿,jz-hws 絕不插入公式內部", () =>
|
||||
{
|
||||
const { document } = setupDom("<p>公式" + KATEX + KATEX + "文字</p>");
|
||||
|
||||
Reference in New Issue
Block a user