2d42c7ecf2
從零重寫之第一垂直切片(依 ARCHITECTURE.md 契約),涵蓋並超越 v1 全部功能。 核心基座(src/core):unicode 字元表+標點子類+字形側位;locale 語言與 全角/開明政策(全域 lang.style +逐 lang policy);dom(jz-* 工廠+可還原 標記);finder 遍歷引擎(avoid/scope.include/邏輯 run/pill 鄰字/分塊閘); pass 聚合管線。 功能 pass(src/typeset): - spacing:中西間隙採 margin 模型——包裹邊界左側字、以 margin-right 留隙, 不注入空白字元(textContent 完全不變、複製緊湊、justify 不暴增、不撐框、 行首乾淨)。含跨樣式邊界、pill、原檔空格移除。 - gapTrim(lineedge):layout pass,行末去隙,修正 justify 右緣內縮。 - longword:長英文詞 <span lang> + hyphens。 - jiya:標點 charify + 全角/開明/半角(全域 + 逐 lang);半形以字型 OpenType halt 渲染(按字形正確定位、不重疊,居中字形 !? 與繁體 locl 句逗點號皆正確); 行內連續擠壓。 - jinze:行首行末避頭尾(閉類/點號綁前字、開類綁後字,以詞元為邊界、長引文 中段可斷);亦為 justify 綁定載體。 - lineedge:行端擠壓 layout pass(括號引號;ResizeObserver 重算,瀏覽器專用)。 §8 justify:jz-char inline-block 原子,句末標點單份間距。 v1 相容層(compat/v1):createCjkAutospace().apply 映射,IIFE 全域別名。 構建:esbuild → ESM/IIFE/CSS;tsc → d.ts。測試:39 個 jsdom 案例。 demo:簡繁並列+justify+強制繁體開明+標點寬度量測,載 Noto webfont 作參考 (擠壓依賴字型 halt)。間隔號 · 不觸發中西間隙;200% 等詞元不被禁則切斷。
61 lines
2.6 KiB
TypeScript
61 lines
2.6 KiB
TypeScript
import type { ResolvedOptions } from "../types.js";
|
||
/** 邏輯 run 中之單一字元來源位置。 */
|
||
export interface CharPos {
|
||
textNode: Text;
|
||
offset: number;
|
||
}
|
||
/** 一段邏輯文本:剝離樣式後之連續字元,及其逐字回映射。 */
|
||
export interface LogicalRun {
|
||
text: string;
|
||
map: CharPos[];
|
||
}
|
||
/** pill 鄰接之邏輯鄰字。 */
|
||
export interface AdjacentChar {
|
||
textNode: Text;
|
||
offset: number;
|
||
ch: string;
|
||
}
|
||
export declare class Finder {
|
||
private readonly opts;
|
||
private readonly styleSet;
|
||
private readonly blockSet;
|
||
private readonly skipSet;
|
||
private readonly pillSelector;
|
||
private readonly avoidSelector;
|
||
private readonly includeSelector;
|
||
private readonly skipAttr;
|
||
private readonly userIsSkipped;
|
||
private readonly featureCache;
|
||
constructor(opts: ResolvedOptions);
|
||
/** 該元素是否匹配 pill 選擇器(行內塊,如 code/kbd)。 */
|
||
pillMatches(el: Element): boolean;
|
||
/** 節點是否處於 avoid 子樹(內建 skip 名單 / SVG / contentEditable /
|
||
* data-jz-skip / 使用者 avoid 選擇器 / skipAttribute / isSkipped)。 */
|
||
isAvoided(node: Node): boolean;
|
||
/** scope.include 啟用判定:未設則恆 true;設則須有命中祖先(opt-in)。 */
|
||
inScope(node: Node): boolean;
|
||
/** 走訪 root 下所有「可處理」文本節點(已過濾 avoid / 非作用域)。 */
|
||
eachTextNode(root: Element, cb: (node: Text) => void): void;
|
||
/** 走訪 root 下所有 block 元素(含 root 本身若為 block)。 */
|
||
eachBlock(root: Element, cb: (block: Element) => void): void;
|
||
/**
|
||
* 收集 block 之邏輯文本 run(架構 §4.1,I7):樣式行內元素與 wrap 類
|
||
* jz-* 透明穿越;block/pill/avoid/間隙 marker(jz-hws)中斷 run。
|
||
* 回傳 text.length >= 2 之 run(短於 2 無間隙可言)。
|
||
*/
|
||
collectRuns(block: Element): LogicalRun[];
|
||
/**
|
||
* pill 之邏輯鄰字(架構 §4.1):經樣式鏈遞迴,遇 pill/block/avoid/間隙
|
||
* marker 即止。direction = -1 取前鄰字,+1 取後鄰字。
|
||
*/
|
||
adjacentLogicalChar(el: Element, direction: -1 | 1): AdjacentChar | null;
|
||
/**
|
||
* 解析節點對某功能之有效啟用狀態(§3.6,per-node 閘)。向上找最近帶
|
||
* 功能指令之祖先(data-juzhen 白名單 / data-juzhen-off 黑名單 / 命中
|
||
* blocks 選擇器),無則回退全域 features。結果以元素為鍵快取。
|
||
*/
|
||
featureEnabledFor(node: Node, name: string): boolean;
|
||
private globalFeature;
|
||
private resolveFeature;
|
||
}
|