初始:cjk-autospace 工廠函式 + TS 宣告 + README

雙 pass 架構:
- Pass A — 對每個 BLOCK 走 DFS 收集邏輯文本(樣式標籤透明、PILL
  與子 BLOCK 中斷 run),套 panguSpace,把 MARK 反映射回
  textNode / offset 並插入 .cjk-autospace marker span
- Pass B — 對每個 PILL(pillSelector)透過樣式鏈遞迴找邏輯鄰字,
  按 0 / 1 / 多 + 特殊規則處理空白

工廠 createCjkAutospace(options) 接受 pillSelector / styleInlines /
blockTags / skipTags / autospaceClass / skipAttribute / isSkipped 等
配置。UMD-ish export 同時支援 ESM、CommonJS、browser global 與
inline script 形式。

規則表 port 自 Pangu.js v7.2.1(MIT),加上跨樣式邊界透明與行內塊
邊界兩 pass 為原創設計。
This commit is contained in:
2026-05-22 22:18:45 +08:00
commit c3defc4054
4 changed files with 593 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
/**
* cjk-autospace — CJK ↔ Latin 邊界自動間距 shimPangu.js v7.2.1 風格)。
*
* 用法:
* ```ts
* import { createCjkAutospace } from "./cjk-autospace.js";
*
* const autospace = createCjkAutospace({
* pillSelector: "code, kbd, .cjk-pill",
* });
* autospace.apply(document.body);
* ```
*/
export interface CjkAutospaceOptions {
/** 行內塊(PILL)選擇器。預設 `"code, kbd"`。 */
pillSelector?: string;
/** 樣式標籤集合(shim 透明走過)。tagName 用大寫。 */
styleInlines?: readonly string[];
/** 段落級標籤集合(Pass A run 邊界)。tagName 用大寫。 */
blockTags?: readonly string[];
/** Skip-ancestor 標籤集合(subtree 整個跳過)。tagName 用大寫。 */
skipTags?: readonly string[];
/** Marker span 之 class 名。預設 `"cjk-autospace"`。 */
autospaceClass?: string;
/** Skip-ancestor 額外屬性檢查(任一祖先帶此屬性則 skip)。預設 `"data-md-key"`。 */
skipAttribute?: string;
/** 自訂 skip 判定(在內建判定前先檢查)。回傳 true 表示應跳過。 */
isSkipped?: (node: Node) => boolean;
}
export interface CjkAutospaceInstance {
/**
* 對指定 root(預設 `document.body`)套用 Pass A + Pass B。
* 在已注入 marker 之 DOM 上重跑為冪等(會跳過既有 `.cjk-autospace`)。
*/
apply(root?: ParentNode | Document): void;
}
export function createCjkAutospace(options?: CjkAutospaceOptions): CjkAutospaceInstance;
declare global {
var createCjkAutospace: typeof createCjkAutospace;
}