feat: 字符分類規則集抽象(charClass,可配置;向下兼容)

把散落於各 pass 之硬編碼字符分類(中文 CJK/西文 ANS/全寬標點 BD_* 子類)統一抽象為
規則集 Ruleset:內置默認即現狀值,消費端經 options.charClass 擴充,以覆寫 spacing/
jiya/jinze 對特定字符之分類判定。

動機:英文全角句號 .(U+FF0E,異於中文句號 。U+3002)實證為**完全未分類**——不被
charify、不挤壓、與 CJK 間不補隙。與其每次硬編碼補字符(如先前 € 之西文集),不如給
消費端可配置之分類鉤子。

API(追加語義):
  charClass?: {
    cjk?: string;        // 追加為中文
    western?: string;    // 追加為西文(半寬標點亦歸此)
    biaodian?: { stop?, pause?, open?, close?, middle?, liga? };  // 追加為全寬標點,按子類
  }

實作:
- core/unicode.ts:新增 Ruleset/CharClassOverride/BdSubclass 型別、DEFAULT_RULESET、
  resolveRuleset(追加合併);classifyBiaodian(ch, biaodian) 改吃規則集(預設參數向下兼容)。
- types.ts:JuzhenOptions.charClass;ResolvedOptions.ruleset;index 再匯出公開型別。
- index.ts:resolveRuleset(opts.charClass) → ResolvedOptions.ruleset。
- typeset/spacing.ts:所有 CJK/ANS 依賴正則移入 makeRules(ruleset),per-instance 編譯
  (非每 block);ALNUM/ALPHA/運算符等結構性 ASCII 仍為固定常數。
- typeset/jiya.ts:classifyBiaodian(ch, ruleset.biaodian)。
- typeset/jinze.ts:詞元邊界之 anyCjk 由 ruleset.cjk 建。

向下兼容:不傳 charClass 則 ruleset === DEFAULT_RULESET、行為與重構前完全一致。
v1 為追加語義,不支援重分類/移除內置字符(範圍式集合難挖洞、需求罕見,列後續)。

驗證:實 Chromium end-to-end——charClass.biaodian.stop="." → . charify 為 bd-stop
(开明式句末維持全角,比照 。);western="★"/cjk="〇" → 與對側正確補/不補中西間隙。
測試 66 通過(含 9 條 charClass 新測——默認未分類/各子類 charify/實例隔離不可變
(resolveRuleset 不污染 DEFAULT)/追加不破壞內置/多子類組合;57 既有不變)。

- README「自定義字符分類」節+ARCHITECTURE §4.2 規則集抽象。dist 重建。
This commit is contained in:
2026-06-04 16:22:14 +08:00
parent 5b9c6b5fa1
commit b821cd1134
14 changed files with 701 additions and 326 deletions
+7 -2
View File
@@ -1,7 +1,7 @@
import type { Finder } from "./core/finder.js";
import type { LangClass, LocaleConfig, PunctStyle } from "./core/locale.js";
import type { Bias, BiasTable } from "./core/unicode.js";
export type { LangClass, PunctStyle, Bias, BiasTable };
import type { Bias, BiasTable, BdSubclass, CharClassOverride, Ruleset } from "./core/unicode.js";
export type { LangClass, PunctStyle, Bias, BiasTable, BdSubclass, CharClassOverride, Ruleset };
/** 長英文詞包裝設定。 */
export interface LongWordOptions {
minLength?: number;
@@ -34,6 +34,9 @@ export interface JuzhenOptions {
/** 逐 lang 覆寫(最高優先)。 */
policy?: Partial<Record<LangClass, PunctStyle>>;
};
/** 自定義字符分類(擴充內置規則集)。把未分類字符或新符號歸入中文/西文/
* 全寬標點各子類,以覆寫 spacing/jiya 等規則之分類判定(追加語義)。 */
charClass?: CharClassOverride;
/** 間隙標記沿用之 class(v1 相容;預設無額外 class)。 */
autospaceClass?: string;
/** justify 原子化:jz-charjz-jinze 是否以 inline-block 作對齊單一原子
@@ -67,6 +70,8 @@ export interface JuzhenOptions {
/** 正規化後之內部選項。 */
export interface ResolvedOptions {
locale: LocaleConfig;
/** 最終字符分類規則集(內置默認 + charClass 覆寫)。 */
ruleset: Ruleset;
autospaceClass: string;
justifyAtoms: boolean;
scope: {