feat(rules): 建立共享排版契约并收束 WebKit 与 Unicode 基线

This commit is contained in:
2026-09-04 21:44:11 +08:00
parent 8ee9895247
commit 993cf576c6
42 changed files with 8511 additions and 1422 deletions
+10 -4
View File
@@ -1,6 +1,6 @@
/** jz-* 自訂元素名(皆含連字號,合法 custom element,預設 inline)。 */
export type JzTag = "jz-hws" | "jz-char" | "jz-inner" | "jz-cs" | "jz-jinze" | "jz-orphan" | "jz-em" | "jz-ruby" | "jz-rb" | "jz-rt";
type JzKind = "marker" | "wrap";
type JzKind = "wrap";
export interface CreateOptions {
/** 追加之 class(空白分隔或陣列)。 */
classes?: string | string[];
@@ -8,16 +8,22 @@ export interface CreateOptions {
text?: string;
}
/** 造一個帶 pass 標記之 jz-* 元素。 */
export declare function createJz(tag: JzTag, pass: string, kind: JzKind, opts?: CreateOptions): HTMLElement;
export declare function createJz(ownedElements: WeakSet<Element>, tag: JzTag, pass: string, kind: JzKind, opts?: CreateOptions): HTMLElement;
/** 記錄後寫屬性;同實例重寫時仍保留最初原值。 */
export declare function setOwnedAttribute(el: Element, name: string, value: string, owner: object): void;
/** 僅當 DOM 仍是本實例最後寫入之值時還原;外部變更時 fail closed。 */
export declare function revertOwnedAttribute(el: Element, name: string, owner: object): void;
/** 還原 owner 於 root 本身或子樹寫入之指定屬性,包括已被外部刪除者。 */
export declare function revertOwnedAttributes(root: Element, name: string, owner: object): void;
/**
* 還原某 pass 之全部產物(I6)。以 data-jz 定址,逆文件序處理(先內層後
* 外層),marker 移除、wrap 解包,最後 normalize 受影響父節點合併文本。
* 外層),wrap 解包,最後 normalize 受影響父節點合併文本。
*
* splitoff(克隆切分之邊界詞元,見 core/split.ts)須在 wrap 全部解包**之後**才併回:
* 否則其前兄弟可能仍是 wrap 殼(如 jz-jinze)而非原元素。故主迴圈跳過 splitoff,於
* 解包後第二階段以文件序逐一併回前兄弟(同標籤元素),還原為單一元素(I6 一致)。
*/
export declare function revertPass(pass: string, root: ParentNode): void;
export declare function revertPass(pass: string, root: ParentNode, ownedElements: WeakSet<Element>): void;
/** 讀取 jz-char 之 bd-* 子類(無則 null)。 */
export declare function bdClassOf(el: Element): string | null;
/** 該元素是否為某/任一 pass 之 jz 產物。 */
+15 -4
View File
@@ -1,15 +1,26 @@
import type { FeatureLevel, ResolvedOptions } from "../types.js";
/** 邏輯 run 中之單一字元來源位置。 */
/** 邏輯 run 中之單一 base+optional-VS 來源 UTF-16 位置。 */
export interface CharPos {
textNode: Text;
offset: number;
}
/** 一段邏輯文本:剝離樣式後之連續字元,及其逐字回映射。 */
/** 邏輯字元在單一 Text 節點內之 UTF-16 區間。 */
export interface TextSpan {
textNode: Text;
start: number;
end: number;
}
/** 邏輯字元之完整 DOM 來源跨度;base 與 VS 可分居多個 Text 節點。 */
export interface CharSpan {
text: string;
parts: TextSpan[];
}
/** 一段邏輯文本:剝離樣式後之連續字元,及其逐邏輯字元回映射。 */
export interface LogicalRun {
text: string;
map: CharPos[];
map: CharSpan[];
}
/** pill 鄰接之邏輯鄰字。 */
/** pill 鄰接之邏輯鄰字(base+optional-VS)。 */
export interface AdjacentChar {
textNode: Text;
offset: number;
+2 -2
View File
@@ -6,9 +6,9 @@ import type { Finder } from "./finder.js";
* · 不可切/無法定位切點/整元素即該詞元 → 回 el 本身(綁整個元素,退化但安全)。
* 切出之克隆標 splitoff,由 revertPass 併回;故 render→revert 還原一致(I6)。
*/
export declare function isolateBoundaryToken(el: Element, side: "head" | "tail", anyCjk: RegExp, pass: string, finder: Finder): Element;
export declare function isolateBoundaryToken(el: Element, side: "head" | "tail", anyCjk: RegExp, pass: string, finder: Finder, ownedElements: WeakSet<Element>): Element;
/**
* 把 el 之**指定切點**(精確字位)起至末尾剝入克隆並回傳(供 orphan:自實義字綁至塊末)。
* 不可切或切點在最起點 → 回 null(呼叫端綁整個直接子)。
*/
export declare function splitElementAt(el: Element, textNode: Text, offset: number, pass: string, finder: Finder): Element | null;
export declare function splitElementAt(el: Element, textNode: Text, offset: number, pass: string, finder: Finder, ownedElements: WeakSet<Element>): Element | null;
+17
View File
@@ -1,6 +1,23 @@
import type { LangClass } from "./locale.js";
/** CJK 表意文字/假名/注音等範圍(沿用並擴充 v1 之 PANGU_CJK)。 */
export declare const CJK: string;
/** Unicode variation selector 字元類片段;僅可作緊隨 base 的後綴。 */
export declare const VARIATION_SELECTORS = "\\uFE00-\\uFE0F\\u{E0100}-\\u{E01EF}";
/** 取 UTF-16 offset 處的完整 Unicode code point;越界時回空字串。 */
export declare function codePointAtUtf16(text: string, offset: number): string;
/** 回傳 `offset` 之前一個 code point 的 UTF-16 起始位置。 */
export declare function previousCodePointStart(text: string, offset: number): number;
/** 是否為 Unicode variation selector(BMP VS1–VS16 或補充 VS17–VS256)。 */
export declare function isVariationSelector(ch: string): boolean;
/**
* 取 UTF-16 offset 處之邏輯字元:一個 base code point,加上緊隨的單一 VS。
* 孤立 VS 只回自身,不反向吞併;回傳字串長度仍是 UTF-16 code units。
*/
export declare function variationSequenceAtUtf16(text: string, offset: number): string;
/** 回傳 `offset` 之前一個 base+optional-VS 邏輯字元的 UTF-16 起點。 */
export declare function previousVariationSequenceStart(text: string, offset: number): number;
/** 以 base+optional-VS 為單位切分字串;孤立 VS 仍是單獨單位。 */
export declare function splitVariationSequences(text: string): string[];
/** 西文字母與數字。 */
export declare const ALNUM = "A-Za-z0-9";
/** 西文字母。 */
+6
View File
@@ -24,6 +24,12 @@ jz-jinze {
jz-hws {
margin-right: 0.25em;
}
jz-hws[data-jz-cross-node-atom]::after {
content: "\200b";
font-size: 0;
-webkit-user-select: none;
user-select: none;
}
jz-hws.jz-hws-trim {
margin-right: 0;
}
+1163 -462
View File
File diff suppressed because it is too large Load Diff
+1163 -462
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -146,6 +146,12 @@ export interface RenderContext {
root: Element;
options: ResolvedOptions;
finder: Finder;
/** 當前 createJuzhen 實例造出之元素;DOM 屬性不能作為所有權憑證。 */
ownedElements: WeakSet<Element>;
/** 實例不可偽造之屬性寫者身分;狀態由 core/dom 共享堆疊管理。 */
ownerToken: object;
/** 寫入本實例產物之內部 class,並在觀察啟用時留下可精確核對之 mutation provenance。 */
setOwnedClass: (element: Element, className: string, present: boolean) => void;
}
/**
* charify 階段之包裝請求:把 node.data[start, end) 包進 build() 造出之元素。