# 聚珍消費端更新 目前用法與標記契約以 [README](./README.md#用法) 為準;本檔只記錄升級影響與所需動作。 ## 2026-10-03:全專案掃描後的行緣、回退與語言修復 - **基線/範圍**:以 `024ad5d`(套件 2.0.0、ruleset 1.0.0)為掃描基線,修復 Web adapter、demo、量測工具及文件。套件版本仍為 2.0.0。 - **交付狀態**:本次修復已提交並推送至 `main`,倉庫含配套 JS/CSS 與型別宣告。 未進行 npm 發佈、下游更新或部署;既有安裝及網站不會自動更新。 ### 可見行為與升級影響 1. **物理行緣**:`jz-orphan` 包裹不再把同行開括號誤當行首;自訂 isolate/opaque 的實際 inline/inline-block/contents 盒可攀出,block 仍是邊界。可見 `br` 作為 強制行緣,隱藏 `br` 可穿越。修正影響行端半形及同行/行末間隙判斷,邏輯隔離政策不變。 2. **切分回退**:splitoff 不再只憑前兄弟標籤合併。私有切分/合併鏈證明同源、仍相鄰 且作者屬性一致時才併回,支援多實例再次切分;外部插入、替換來源或改樣式時保留 片段元素、樣式及字序並撤銷本庫標記/憑證。受外部干預後不承諾恢復歷史 DOM 快照。 3. **語言**:自身及祖先最近的 `lang=""` 表示未知(`other`),僅屬性缺失才繼承/回退; `lang.default: ""` 亦表示未知。script/region 只按 BCP 47 的位置判讀,私用或擴展 內容不再冒充腳本,如 `zh-Hans-x-hant` 為簡體、`zh-TW-x-hans` 為繁體。四個分類鍵、 裸 `zh` 預設繁體及逐元素樣式優先序不變。依賴舊錯誤行為者須改成明確語言或樣式。 4. **demo 控制**:主 demo 對齊/寬度切換顯式重排,revert 後控制保持停用;拖曳頁 八個框各自作為 render 根,寬度觀察及對齊刷新不再只依賴 body 尺寸變化。 5. **字型後備**:`margin`+逐語言分類/逐字 `jiya.bias`(left/center/right/full) 完整保留。工具補量 `.`(U+FF0E),並明示只量預設 cmap、未做 shaping/`locl`; 語言參數僅選 JSON 分類鍵,`halt` 特性存在不保證逐字覆蓋。目標字型與語言下仍須目視微調。 共享規則升為 **1.0.1 patch**:澄清既有 explicit-script/region 契約並新增七個反例向量, 原有 55 個向量結果、字符集合、政策、schema 及 adapter 義務均不變。Web 修正違反既有 契約的解析錯誤,不另立 Web 專用分類政策;其他 adapter 須核對全部 62 個向量。 本次未驗收 XeLaTeX 或其他 adapter。版本依據見 [共享規則](./rules/README.md#101-語言契約澄清)。 取用本次倉庫修改時,一起更新配套 JS/CSS/型別及共享規則;公開入口與選項名稱不變。 文件另修正 Finder 快取生命週期、no-op 懸掛說明、功能級別預設、樣式優先序及 `charClass` 輸入格式:cjk/western 是 regex 字元類片段,biaodian 是逐碼點字串, `"①-③"` 不代表三個圈碼,應寫 `"①②③"`。 ### 本地驗證 - `npm run build`:JS/CSS 與 TypeScript 型別宣告完整構建通過。 - `npm test`:**376/376 通過,0 失敗、0 跳過**;含 strict schema/常數對照、 全部 62 個語義向量、外部插入/替換/改樣式、observer 回退及多實例切分 36 個組合。 - `npm run test:wkwebview`:最終構建 **64/64 通過**,failures 為空;新增行緣、 語言、外部同標籤兄弟及多實例切分用例均在真實 WKWebView 執行。 - 最終產物另以原生宿主載入兩個 demo 副本:主頁 4 項、拖曳頁 5 項通過,核對 對齊後與手動重排一致、revert 停用,以及框寬變化實際改變行端決策。 以上是本地 DOM/原生幾何及控制驗證,不代表三引擎目視、所有字型地域字形或真實下游 頁面驗收。本次未重新驗收 Chrome/Edge;**Firefox 依用戶要求暫緩**,不安裝或作相容性結論。 ## 2026-10-02:Web 模組邊界、半形模式與局部生命週期修復 - **基線/範圍**:以 `1c2fb0e`(套件 2.0.0、ruleset 1.0.0)為修復前基線;本次為 Web/CSS adapter 修復,公開入口、選項與共享規則版本不變。 - **交付狀態**:修復已以 [`b1a16c4`](https://git.commilitia.net/admin/cjk-autospace/commit/b1a16c49698dc418aa733e41a04bdbc9922927be) 提交並推送至 `main`,可從倉庫取得配套 JS、CSS 與型別宣告。未進行 npm 發佈; 既有 npm 安裝或任何下游網站不會因此自動更新。 ### 半形模式 舊版以後代選擇器切換 `data-jz-halfwidth`,外層 halt 會蓋過內層 margin;從 margin 切回 halt 也會殘留 inline-block 內盒。現在由最近有效標記決定模式,可交替巢狀, 切回 halt 同時復原內盒與偏移。margin 的偏側位移僅作用於已壓縮標點;全形標點不再偏移。 既有缺半形特性字型的逐字相容方案仍保留:`margin` 後備搭配 `jiya.bias`,可按語言分類、 逐標點選 `left`/`center`/`right`/`full`;字型量測與目視微調流程見 README。 **受影響者**:混用含 halt 與缺 halt 字型、巢狀半形模式,或 margin 區域含全形標點的消費端。 標記與呼叫方式無需更換。若曾加 CSS workaround 抵銷舊版行為,更新後須確認其是否仍需要。 ### 局部回退與觀察更新 舊版局部 `revert` 子樹含獨立 render 根時,可能只還原子根而漏掉由祖根處理的兄弟內容。 現在撤回完整請求子樹中本實例的產物,保留作者及其他實例的所有權。 舊版手動 `render`/`revert`/`rerender` 暫停 observer 時會丟掉未交付的變更。 現在先結算待交付更新,再執行手動操作;兄弟區塊仍更新,手動回退不被舊記錄重新打開。 **時機注意**:手動操作可能先處理其他已變動區塊,因此消費端的 `isSkipped` 等鉤子也可能 在該呼叫期間執行。observer 結算失敗仍走宿主非同步錯誤通道,不成為手動 API 的同步例外。 增量更新按目前觀察根的包含關係判定,未掛入 document 的根仍可更新;同批新增後 移到根外,或舊記錄目標已離開根時不再排版。舊版分別會漏掉前者、誤處理後者。 ### 元素參與、Unicode 原子與源文本 舊版 standalone 遍歷可能進入 pill 內部的塊;禁則與避孤字也可能把 avoid、text 或 關閉該功能的內容帶入 `nowrap`。現在 pill 內部保持原樣,禁則同時檢查兩側及整綁 範圍,行內 render 根不向外綁定。避孤字只計算排除邊界之後的合法段末區域;不足 N 字,或不可切容器還含排除內容時不綁。pill 仍可作完整單元參與外部交界。 跨透明文本節點的 surrogate pair 及 base+VS 現在共用完整原子映射,間隙建於完整 字符之後,禁則不在原子內造斷點,避孤字只計一字。pill 兩側隔著一個 ASCII 作者 空格的鄰字也以完整原子查找;第二個空格、換行或排除邊界仍中斷。 標點 charify 也先將跨透明 Text 的 base+VS/surrogate 合為一個標點載體,讓鄰接 擠壓作用於完整字符。作者元素與監聽器保留,回退任一來源端會還原完整原子的分布。 作者克隆/刪除載體或替換來源父節點後,舊回退記錄不會復活已移除文字。 自訂標點集合含非 BMP 字符時,孤立 surrogate 不再被錯認為該字符;被排除的空 Text 也會中斷標點鄰接,普通空 Text 仍透明。 舊版固定內部標記可能把原文私用區字符(如 U+E000~U+E003)或貌似 placeholder 的內容誤當排版指令。現在每個 run 選擇源文本未使用、且字符規則不會匹配的標記, 原文保持作者內容。若自訂字符規則/源文本用盡全部候選,間隙回放前報錯。 **受影響者**:pill 中有塊級內容、混用參與標記、Unicode 字符被模板拆到不同節點, 或源文本含私用區字符的消費端。API 與標記無需變更;依賴舊版越界綁定的頁面, 須重新檢查段末斷行。 ### 語言腳本匹配 `Hans`/`Hant` 以完整子標籤匹配,避免 `zh-CN-x-shant`/`zh-TW-x-hansford` 等 標籤被局部字串誤判為相反腳本。一般 `zh-Hans`/`zh-Hant`、地區回退及共享規則不變。 ### 混合字號的行末去隙及 layout 生命週期 舊版去隙以相鄰矩形 top 差判斷換行,同行小字或下標也可能被判為下一行,導致 中西間隙消失。現在與行端標點一致,以垂直區間判斷;實際下一行仍去隙。 重排/回退也使舊 layout 安裝的字型完成及已排隊回調失效,避免再次掃描新產物。 **受影響者**:正文中混合字號、下標,或字型仍在載入時反覆重排的消費端。 有效選項與呼叫方式無需變更;曾以額外空格或 CSS 補償間隙的頁面須檢查原 workaround。 ### 數值選項防護 `longWord.minLength` 現在要求 ≥2 的有限安全整數,無效值回退既有預設 6;舊版 小數/Infinity 等可能被拼成無效計數量詞,讓長詞功能靜默失效。`orphan.chars` 排除非有限值,無效值回退 2;合法小數仍照既有行為向下取整。 使用合法選項的消費端無需修改。若由外部設定輸入閾值,請依 README 的範圍檢查。 ### 系統交互補查 已排版塊搬到不同級別/功能/語言的祖先後,舊版可能保留原產物與祖先快取。 現在觀察器先撤回搬入塊的舊效果,再按目前環境排版;純新增塊仍只處理自身範圍。 舊版 spacing 只按 block 門控,普通行內白名單/黑名單仍會被補隙或刪作者空格, 禁用塊中的子白名單也未能恢復間隙。現在以逐來源功能邊界處理;pill 鄰字查詢也 遵守兩側門控。空功能禁用元素會中斷 spacing/jiya,重新啟用的子樹自成脈絡。 `scope.include` 選到行內子樹時,間隙不再因父塊未命中而漏處理。 跨節點間隙載體被作者克隆/刪除、來源父被替換後,舊版回退可能重複或復活文字; 現在保留作者當前內容。這也修正舊回歸中「刪除載體後回退另一端便恢復整顆字」的 預期:**刪除載體即刪除其中原文,revert 不補回**。若要撤回排版再編輯原文,先 revert, 再修改;整根脫離文檔與正常搬移的恢復仍保留。 其他實例合法解包來源父時,本庫現在透過私有受控解包鏈更新記錄;兩/三實例 任意回退次序不再因舊父已撤回而丟 VS。作者自行解包或可偽造屬性不會獲得此憑證。 重用已撤回容器會使舊位置記錄失效;重定向鏈有環檢測,不能以循環來源指引恢復。 **受影響者**:搬移已排版 DOM、行內功能標記/opt-in、外部替換載體及多實例 疊加的消費端。公開入口、選項及共享規則不變;段落搬移仍使用既有 observe 或 rerender。 ### 消費端動作與驗證 1. 透過既有安裝/打包方式一併更新 JS 與 CSS;只換 JS 不會得到半形模式修復。 2. 保留既有 pill/isolate/avoid、text/paragraph 及半形模式標記。 3. 自訂 `scope.include` 的容器仍須加 `.juzhen` 以使用內建原生間距禁用樣式, 如 `class="prose juzhen"`;JS 選擇器不會自動改寫 CSS 作用域。 4. 用 [E2E 頁面](./demo/e2e.html) 檢查嵌套模式、全形偏移、混合根回退與待交付更新; macOS 原生入口為 `npm run test:wkwebview`。DOM 回歸見 `test/observer-recovery.test.mjs` 與 `test/revert-ownership.test.mjs`;模組邊界見 `test/participation-boundaries.test.mjs`、 `test/spacing-boundaries.test.mjs` 與 `test/shared-rules.test.mjs`。修復提交 `b1a16c4` 已通過 353 項 Node 測試、發佈構建及原生 WKWebView 53 項驗收;layout/數值回歸見 `test/layout-lifecycle.test.mjs` 與 `test/numeric-options.test.mjs`;觀察根及跨節點標點 回歸見 `test/observer-boundaries.test.mjs` 與 `test/punctuation-atoms.test.mjs`。 系統交互新增 42 項回歸見 `test/systematic-interactions.test.mjs`。修復過程中的中間快照 另通過 32 組功能開關×10 類結構共 320 個 DOM 組合及 splitoff 多實例 36 個組合; 這兩組為調查階段證據,不列為最終提交的獨立復驗。最終快照驗收為上述 353/53 項。 真實下游頁面仍須自行驗證其字型與版面。