feat: 全角句點 . 納入句末挤压 + 連續標點挤压規則(雙側獨立+透明穿越)

本會話標點挤压一致性兩項(改內置默認;皆以 Noto CJK + 真實 Chromium 量測驗證)。

一、全角句點 .(U+FF0E)納入句末標點
- BD_STOP 由 。!? 擴為 。.!?——納入全角句點 .(異於表意句號 。U+3002)。實測
  Noto CJK SC/TC 之 halt(GPOS SinglePos)皆覆蓋 .、挤压收半形 advance 0.5em,與 。
  一致。inkBias 同步補 .(簡 left/繁 center),margin 後備亦可挤。
- 政策行為與 。!? 同:全角式與開明式句末保持全角 1em,banjiao(或鄰接被收)挤半。
- 設計原則:halt 即字型之「挤压意願」——字型不提供某標點 halt(字形占滿、不宜挤,如某些
  字型之全角 ?、〈〉)則信任字型、保持全角不強挤;margin 後備僅用於整體無 halt 之字型。

二、連續標點挤压規則:雙側獨立 + 透明穿越(修正既有不一致)
- 規則(用戶確定):相鄰兩標點,**對每一標點**獨立判斷——若其「有空白之側」緊鄰另一標點,
  即挤掉該側空白(收半形)。原 jiyaAdjacencyPass 為「二選一只收一側」,致:
  · ,「(pause 右空白 + open 左空白)原只收 ,→ 全角式 1.5em;應雙側皆收 → 1em。
  改 else-if 為雙獨立 if。修後:,「 全角式與開明式皆 1em;。」 全角式 1.5em/開明式 1em
  (」左為墨不收);·— 兩式皆 2em(不宜挤之例外)。
- 透明穿越:原以「同 parent 直接兄弟」掃描,漏掉跨 strong/em 等行內邊界之連續標點(致
  跨邊界標點對未挤、達 2em)。改為從 root 之透明遍歷(穿越樣式行內;block 邊界與 avoid
  子樹斷相鄰;jz-char 為原子不下探),跨 inline 邊界之連續標點亦正確配對。

- src/core/unicode.ts:BD_STOP +.;inkBias 表 +.。
- src/typeset/jiya.ts:jiyaAdjacencyPass 重寫(雙側收 + root 透明遍歷)。
- test:. 納入+連續挤压(雙側/句末單側/跨 inline/多標點鏈)回歸,70 測試通過。
- README/ARCHITECTURE:. 與連續挤压規則、halt 挤压意願原則;**涉長度處標明全角式/
  開明式**(。」 全角 1.5em/開明 1em 等)。dist 重建(僅 JS,juzhen.css 不變)。
This commit is contained in:
2026-06-09 15:19:35 +08:00
parent b821cd1134
commit fdf071c5bb
7 changed files with 231 additions and 102 deletions
+6 -4
View File
@@ -60,8 +60,10 @@ export const ANS_BEFORE_CJK = ALPHA + WEST_SHARED;
// 注意:分類依「字形角色」,而開明式/全角式之別依「句法角色」。slice 1 之
// 擠壓集(句內點號)由 BD_PAUSE 表達——此即 v1 Pass D 所擠之 ,、;:。
/** 句末點號:。!?(開明式與全角式皆保持全形,不擠壓)。 */
export const BD_STOP = "。!?";
/** 句末點號:。!?(開明式與全角式皆保持全形,不擠壓banjiao 擠半)。
* 含全角句點 .(U+FF0E,異於表意句號 。U+3002)——實測 Noto CJK SCTC 皆有 halt、
* 挤壓收 0.5em,故與 。!? 同列為句末點號(下游回饋)。 */
export const BD_STOP = "。.!?";
/** 句內點號:,、;:(開明式擠成半形;全角式保持全形)。 */
export const BD_PAUSE = ",、;:";
@@ -245,11 +247,11 @@ const BIAS_BRACKETS: Record<string, Bias> = (() =>
// 在右 → 全判 left(經方正書宋 GBK 實測:,、。;:!? 墨色 inkL≈0.1–0.18、
// inkR≈0.580.68,一致偏左)。繁體(Noto/教育部字形)點號置中 → center。
const BIAS_HANS: Record<string, Bias> = {
"": "left", "、": "left", "。": "left",
"": "left", "、": "left", "。": "left", "": "left",
"": "left", "": "left", "": "left", "": "left",
};
const BIAS_HANT: Record<string, Bias> = {
"": "center", "、": "center", "。": "center",
"": "center", "、": "center", "。": "center", "": "center",
"": "center", "": "center", "": "center", "": "center",
};