feat: 標點半形 margin 後備模式+下游回饋修復
margin 後備(供缺 OpenType halt 之字型): - jiya.halfWidth: "halt"(預設)|"margin"。margin 以 width:0.5em+字身依墨色 偏側溢出定位,於 CSS 盒模型重現 halt 之半形 advance(真 0.5em;相鄰標點各 0.5em、合佔 1em,無負 margin 之鄰接疊加/單側重疊)。模式由 data-jz-halfwidth 子樹屬性決定(可逐區塊/逐 lang,含 halt-island 反置)。 - 偏側 inkBias 依字身墨色中心給 left/center/right/full;參考表據方正書宋 GBK 實測,consumer 可經 jiya.bias 逐 lang 逐字覆寫。 - _lang.css 字型堆疊僅作後備(全包 :where 零特異度、只命中帶 lang 屬性之元素、 不直接覆寫 jz-inner)→ 消費端 font-family 恆優先,標點隨之以消費端字型渲染。 - 新增 tools/measure-bias.py(量 glyph ink 中心、產偏側建議表)+ README 「字型適配工作流」。demo/fallback.html:方正書宋 GBK 對照 halt 失效 vs margin。 下游回饋修復: - 1a:adjacentLogicalChar 透明穿越 jz-jinze(同 jz-hws/樣式行內)→ pill 緊鄰 CJK 標點時,左緣間隙與作者空格剝除復原(jinze 先於 spacing 之交互)。 - 1b:CJK↔CJK 贅餘作者空格(含跨 inline 標籤)剝除、不留隙,與 CJK↔Latin 之 邊界正規化一致(DEL 哨符,全形空格 U+3000 不動)。 - 問題二:新增 justifyAtoms 選項;false → jz-char/jz-jinze 改 display:inline, 相容分頁器(Paged.js)對齊引擎(halt 半形與禁則 nowrap 保留)。 測試 43→49 全通過;dist 重建;README/ARCHITECTURE 同步更新契約。
This commit is contained in:
@@ -197,6 +197,52 @@ test("政策:未設 style/policy 時回退內建預設(繁全角不擠、
|
||||
assert.ok(!ps[1].querySelector("jz-char.bd-pause").classList.contains("jz-half"), "繁體內建全角");
|
||||
});
|
||||
|
||||
// ----- 字形偏側(jz-ink-*)+ margin 後備模式(.feedback)-----
|
||||
|
||||
test("偏側:jz-ink-* 恆於 charify 標記(halt 預設模式亦然,root 不設 margin 屬性)", () =>
|
||||
{
|
||||
const { document } = setupDom('<p lang="zh-Hans">好,「走」。</p>');
|
||||
createJuzhen(JIYA_ONLY).render(document.body);
|
||||
// 簡體點號偏左;角括號「」墨色強偏一側 → 開 right、閉 left(圓方括號才 center)。
|
||||
assert.ok(document.querySelector("jz-char.bd-pause").classList.contains("jz-ink-left"), "簡體 ,偏左");
|
||||
assert.ok(document.querySelector("jz-char.bd-open").classList.contains("jz-ink-right"), "角括號「墨偏右 → right");
|
||||
assert.ok(document.querySelector("jz-char.bd-close").classList.contains("jz-ink-left"), "角括號」墨偏左 → left");
|
||||
assert.equal(document.body.getAttribute("data-jz-halfwidth"), null, "halt 預設模式不設 root 屬性");
|
||||
});
|
||||
|
||||
test("偏側:繁體點號居中(jz-ink-center),!?恆居中", () =>
|
||||
{
|
||||
const { document } = setupDom('<p lang="zh-Hant">走,真?</p>');
|
||||
createJuzhen(JIYA_ONLY).render(document.body);
|
||||
assert.ok(document.querySelector("jz-char.bd-pause").classList.contains("jz-ink-center"), "繁體 ,居中");
|
||||
assert.ok(document.querySelector("jz-char.bd-stop").classList.contains("jz-ink-center"), "?居中");
|
||||
});
|
||||
|
||||
test("margin 模式:render 於 root 設 data-jz-halfwidth=margin,revert 清除", () =>
|
||||
{
|
||||
const { document } = setupDom('<p lang="zh-Hans">好,走。</p>');
|
||||
const jz = createJuzhen({ ...JIYA_ONLY, jiya: { halfWidth: "margin" } });
|
||||
jz.render(document.body);
|
||||
assert.equal(document.body.getAttribute("data-jz-halfwidth"), "margin", "margin 模式設 root 屬性");
|
||||
// 偏側 class 與 jz-half 並存,CSS 始能定向收縮。
|
||||
const comma = document.querySelector("jz-char.bd-pause");
|
||||
assert.ok(comma.classList.contains("jz-half") && comma.classList.contains("jz-ink-left"), ",半形+偏左");
|
||||
jz.revert(document.body);
|
||||
assert.equal(document.body.getAttribute("data-jz-halfwidth"), null, "revert 清除 root 屬性");
|
||||
});
|
||||
|
||||
test("margin 模式:消費端 bias 覆寫參考表(如把簡體 ,改判居中)", () =>
|
||||
{
|
||||
const { document } = setupDom('<p lang="zh-Hans">好,走</p>');
|
||||
createJuzhen({
|
||||
...JIYA_ONLY,
|
||||
jiya: { halfWidth: "margin", bias: { "zh-Hans": { ",": "center" } } },
|
||||
}).render(document.body);
|
||||
const comma = document.querySelector("jz-char.bd-pause");
|
||||
assert.ok(comma.classList.contains("jz-ink-center"), "覆寫後 ,判居中");
|
||||
assert.ok(!comma.classList.contains("jz-ink-left"), "不再用參考預設之偏左");
|
||||
});
|
||||
|
||||
// ----- 長英文詞(longWord)-----
|
||||
|
||||
test("longWord:[A-Za-z]{6,} 包進 span[lang],textContent 不變", () =>
|
||||
@@ -291,6 +337,59 @@ test("分塊:data-juzhen-off 黑名單停用列出功能,其餘繼承", () =
|
||||
assert.equal(countTag(p, "jz-char"), 0, "jiya 被黑名單停用");
|
||||
});
|
||||
|
||||
// ----- 下游回饋修復(問題一 1a/1b、問題二)-----
|
||||
|
||||
test("1a:pill 後接 CJK 標點時,pill 左緣仍補 jz-hws(穿越 jz-jinze)", () =>
|
||||
{
|
||||
const { document } = setupDom("<p>代码<code>build</code>,后</p>");
|
||||
createJuzhen({ pillSelector: "code, kbd", lang: { default: "zh-Hans", style: "quanjiao" } })
|
||||
.render(document.body);
|
||||
// jinze 已把 code+,納入 jz-jinze;spacing 仍須能找到 code 左鄰字「码」並補間隙。
|
||||
const hws = document.querySelector("jz-hws");
|
||||
assert.ok(hws && hws.textContent === "码", "pill 左側「码」包入 jz-hws(不因右側標點/jz-jinze 而遺失)");
|
||||
});
|
||||
|
||||
test("1a:pill 後接 CJK 標點且有作者空格 → 空格被剝除、左緣補間隙", () =>
|
||||
{
|
||||
const { document } = setupDom("<p>代码 <code>build</code>,后</p>");
|
||||
createJuzhen({ pillSelector: "code, kbd", lang: { default: "zh-Hans", style: "quanjiao" } })
|
||||
.render(document.body);
|
||||
assert.ok(document.querySelector("jz-hws"), "補了 jz-hws");
|
||||
assert.equal(document.querySelector("p").textContent, "代码build,后", "作者空格被剝除(與無空格輸入一致)");
|
||||
});
|
||||
|
||||
test("1b:CJK↔CJK 贅餘作者空格被剝除(含跨樣式行內標籤)", () =>
|
||||
{
|
||||
const { document } = setupDom('<p><span class="b">事件</span> 元件</p>');
|
||||
createJuzhen({ lang: { default: "zh-Hans" } }).render(document.body);
|
||||
assert.equal(document.querySelector("p").textContent, "事件元件", "跨 <span> 之 CJK↔CJK 空格剝除");
|
||||
});
|
||||
|
||||
test("1b:CJK↔CJK 不插 jz-hws(僅剝空格,無留隙)", () =>
|
||||
{
|
||||
const { document } = setupDom("<p>事件 元件</p>");
|
||||
createJuzhen({ spacing: true, jiya: false, jinze: false, longWord: false }).render(document.body);
|
||||
assert.equal(countTag(document.body, "jz-hws"), 0, "CJK↔CJK 不需間隙,僅刪空格");
|
||||
assert.equal(document.querySelector("p").textContent, "事件元件");
|
||||
});
|
||||
|
||||
test("問題二:justifyAtoms:false → root 設 data-jz-atoms=inline,revert 清除", () =>
|
||||
{
|
||||
const { document } = setupDom("<p lang='zh-Hans'>测试,(甲)。</p>");
|
||||
const jz = createJuzhen({ lang: { default: "zh-Hans" }, justifyAtoms: false });
|
||||
jz.render(document.body);
|
||||
assert.equal(document.body.getAttribute("data-jz-atoms"), "inline", "設 inline 原子屬性");
|
||||
jz.revert(document.body);
|
||||
assert.equal(document.body.getAttribute("data-jz-atoms"), null, "revert 清除");
|
||||
});
|
||||
|
||||
test("問題二:justifyAtoms 預設 true → 不設屬性(維持 inline-block 原子)", () =>
|
||||
{
|
||||
const { document } = setupDom("<p lang='zh-Hans'>测试,</p>");
|
||||
createJuzhen({ lang: { default: "zh-Hans" } }).render(document.body);
|
||||
assert.equal(document.body.getAttribute("data-jz-atoms"), null, "預設不設屬性");
|
||||
});
|
||||
|
||||
// ----- v1 相容層(§3.5)-----
|
||||
|
||||
test("compat:createCjkAutospace().apply() 可跑,產生中西間隙(margin 模型,copy-clean)", () =>
|
||||
|
||||
Reference in New Issue
Block a user