fix: 標點擠壓句界例外——句末點號接開類保留右空白(。「 全角/開明皆 1.5em)
機制 A 行內連續擠壓原對 (L,R) 兩側獨立收:L 有右空白即收,不看 R 是誰,致句末 點號接開類(。「/?「)兩側皆收、合占 1em,丟失句界視覺。修為:L 為句末點號 (bd-stop)且 R 為開類(bd-open)時保留 L 右空白、僅收開類左側 → 全角式與開明式 皆 1.5em,對稱於 。」。例外僅限句末點號+開類;句內點號 ,「 與雙括號 」「/》《 仍兩側皆收 1em。 半角式不回歸:句末點號於 banjiao 由 baseline(機制 C)已收半形,守衛僅跳過 adjacency 之重複追加、不移除 baseline 之 jz-half;實測 32 可壓縮標點全半形、句界 組合句末點號仍半形(0 回歸)。唯非可壓縮 ·・‧/…— 各式皆全寬,屬設計。 唯一改動點 jiyaAdjacencyPass.squeeze() 加 stopBeforeOpen 守衛;lineedge/baseline /jinze/spacing 不波及。新增 3 契約測試(116 全綠);README/ARCHITECTURE §6.3 同步句界例外。
This commit is contained in:
@@ -241,6 +241,48 @@ test("jiya 機制 A:。」→ 僅 。半形(」左為墨、無空白可挤
|
||||
assert.ok(!close.classList.contains("jz-half"), "」左為墨、無空白 → 不收(全角式 1.5em)");
|
||||
});
|
||||
|
||||
test("jiya 機制 A 句界:。「→ 句末點號保留右空白(。全形、「半形;全角/開明皆 1.5em)", () =>
|
||||
{
|
||||
for (const lang of [ "zh-Hant", "zh-Hans" ]) // 全角式/開明式皆 1.5em
|
||||
{
|
||||
const { document } = setupDom(`<p lang="${lang}">甲。「乙</p>`);
|
||||
createJuzhen({ spacing: false, longWord: false, jinze: false }).render(document.body);
|
||||
const stop = document.querySelector("jz-char.bd-stop"); // 。
|
||||
const open = document.querySelector("jz-char.bd-open"); // 「
|
||||
assert.ok(!stop.classList.contains("jz-half"), `${lang}:。句末點號接開類為句界 → 保留右空白(全形)`);
|
||||
assert.ok(open.classList.contains("jz-half"), `${lang}:「開類左空白仍收(半形)→ 合占 1.5em`);
|
||||
}
|
||||
});
|
||||
|
||||
test("jiya 機制 A 句界:例外僅限句末點號+開類——,「 與 」「 仍兩側皆收 1em", () =>
|
||||
{
|
||||
// 句內點號(pause)與閉類後接開類不屬句界,照舊兩側收。
|
||||
const c = setupDom('<p lang="zh-Hant">甲,「乙</p>');
|
||||
createJuzhen({ spacing: false, longWord: false, jinze: false }).render(c.document.body);
|
||||
assert.ok(c.document.querySelector("jz-char.bd-pause").classList.contains("jz-half"), ",仍收(句內點號非句界)");
|
||||
assert.ok(c.document.querySelector("jz-char.bd-open").classList.contains("jz-half"), ",「之「仍收");
|
||||
|
||||
const b = setupDom('<p lang="zh-Hant">甲」「乙</p>');
|
||||
createJuzhen({ spacing: false, longWord: false, jinze: false }).render(b.document.body);
|
||||
assert.ok(b.document.querySelector("jz-char.bd-close").classList.contains("jz-half"), "」仍收(雙括號非句界)");
|
||||
assert.ok(b.document.querySelector("jz-char.bd-open").classList.contains("jz-half"), "」「之「仍收");
|
||||
});
|
||||
|
||||
test("jiya 機制 A 句界:半角式不回歸——。「 句末點號仍半形(守衛僅跳過 adjacency 追加,baseline 已半)", () =>
|
||||
{
|
||||
// 半角式所有可壓縮標點皆半形(baseline 機制 C)。句界守衛只跳過 adjacency 之重複
|
||||
// 追加,絕不移除 baseline 之 jz-half,故半角式句末點號不得退回全寬。
|
||||
const { document } = setupDom("<p>甲。「乙</p>");
|
||||
createJuzhen({
|
||||
lang: { default: "zh-Hans", style: "banjiao" },
|
||||
spacing: false, longWord: false, jinze: false,
|
||||
}).render(document.body);
|
||||
const stop = document.querySelector("jz-char.bd-stop"); // 。
|
||||
const open = document.querySelector("jz-char.bd-open"); // 「
|
||||
assert.ok(stop.classList.contains("jz-half"), "半角式 。仍半形(baseline 已收,守衛不回退)");
|
||||
assert.ok(open.classList.contains("jz-half"), "半角式 「仍半形 → 合占 1em");
|
||||
});
|
||||
|
||||
test("jiya 機制 A:跨透明 inline 邊界之連續標點亦正確擠(,「 分置 strong/em,雙側皆收)", () =>
|
||||
{
|
||||
// 下游回饋:原「同 parent 直接兄弟」掃描漏掉跨 strong/em 邊界之連續標點。
|
||||
|
||||
Reference in New Issue
Block a user