commit 92c37cf63e26a66640d4dc5e7dd5ea80a422d871 Author: commilitia Date: Tue Jun 2 01:41:35 2026 +0800 docs: 聚珍 HTML 文檔(使用文檔+變更紀錄) docs 分支僅含文檔,與程式碼歷史脫鉤(orphan,無 src/dist 等舊實現之提交)。 以 HTML manifest 模板(report 模式)構建為自含單檔,無外部依賴。 - docs/index.html 使用文檔:安裝/用法/功能/選項/halt 與 margin 後備/ 字型偏側與配字工作流/CSS 基礎設定/分頁器相容/v1 相容。 - docs/changelog.html 變更紀錄。 - *.src.html 為可編輯之文檔源。 程式碼正本與其歷史在 main;本分支不記錄任何實現。 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..879df49 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +node_modules/ +*.log diff --git a/docs/changelog.html b/docs/changelog.html new file mode 100644 index 0000000..66e96e8 --- /dev/null +++ b/docs/changelog.html @@ -0,0 +1,5685 @@ + + + + + + +變更紀錄(Changelog) + + + + + + +
+
+

變更紀錄(Changelog)

+

聚珍(Juzhen)/cjk-autospace 之版本變更紀錄。

+

· cjk-autospace · 變更紀錄

+
+
+ + + + + +
+
+ +
+ +

聚珍(Juzhen)/cjk-autospace 變更紀錄。← 回文檔

+ +

v2 切片 1 · 增補 2026-06

+

切片 1 之上的修補與強化,聚焦標點半形對缺 halt 字型之支援,及下游回饋之邊界/分頁器修復。

+ +

新增

+ + +

修復

+ + +

已知限制

+ + +

v2.0.0 切片 1 · 從零重寫

+

ARCHITECTURE.md 契約,從零重寫為「現代簡/繁中文網頁排版套件」。倉庫名 cjk-autospace 不變;公開 API 為 createJuzhen /全域 Juzhen;自訂元素前綴 jz-。v1 完整保留於 v1-autospace 分支。

+ +

新增

+ + +

相對 v1 之改進

+ + +

v1(cjk-autospace) · v1-autospace 分支

+

Pangu.js v7.2.1 風格之 CJK↔Latin 邊界自動間距 shim,工廠 createCjkAutospace(options).apply(root)

+ + +
+ + + + + + + + + + + diff --git a/docs/changelog.src.html b/docs/changelog.src.html new file mode 100644 index 0000000..b598715 --- /dev/null +++ b/docs/changelog.src.html @@ -0,0 +1,127 @@ + + + + + +變更紀錄(Changelog) + + + + + + +
+
+

變更紀錄(Changelog)

+

聚珍(Juzhen)/cjk-autospace 之版本變更紀錄。

+

· cjk-autospace · 變更紀錄

+
+
+ +
+
+ +
+ +

聚珍(Juzhen)/cjk-autospace 變更紀錄。← 回文檔

+ +

v2 切片 1 · 增補 2026-06

+

切片 1 之上的修補與強化,聚焦標點半形對缺 halt 字型之支援,及下游回饋之邊界/分頁器修復。

+ +

新增

+ + +

修復

+ + +

已知限制

+ + +

v2.0.0 切片 1 · 從零重寫

+

ARCHITECTURE.md 契約,從零重寫為「現代簡/繁中文網頁排版套件」。倉庫名 cjk-autospace 不變;公開 API 為 createJuzhen /全域 Juzhen;自訂元素前綴 jz-。v1 完整保留於 v1-autospace 分支。

+ +

新增

+ + +

相對 v1 之改進

+ + +

v1(cjk-autospace) · v1-autospace 分支

+

Pangu.js v7.2.1 風格之 CJK↔Latin 邊界自動間距 shim,工廠 createCjkAutospace(options).apply(root)

+ + +
+ + + + + + + + + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..6c25c83 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,5781 @@ + + + + + + +聚珍(Juzhen) + + + + + + +
+
+

聚珍(Juzhen)

+

現代簡/繁中文網頁排版套件——Han.css 之現代化重寫,複製乾淨、依 lang 全角/開明切換、justify 句末標點單份間距、跨瀏覽器一致。

+

· cjk-autospace · 使用文檔

+
+
+ + + + + +
+
+ +
+ +

聚珍(Juzhen)是現代簡/繁中文網頁排版套件,Han.css 之現代化重寫,沿其功能版圖,並針對四點作調整:複製乾淨(中西間隙不入剪貼板)、依 lang 全角/開明自動切換、justify 下句末標點只佔一份間距、跨瀏覽器一致。倉庫名仍為 cjk-autospace;公開 API 為 createJuzhen /全域 Juzhen;注入之自訂元素前綴 jz-

+ +

本版(2.x)為從零重寫。v1 之 createCjkAutospace API 由相容層保留,既有消費端不需改碼即可運行;v1 原始碼保存於 v1-autospace 分支。設計契約見 ARCHITECTURE.md

+ +

安裝與構建

+
npm install
+npm run build   # esbuild → dist/juzhen.{mjs,iife.js,css};tsc → dist/index.d.ts
+npm test        # jsdom DOM 正確性測試
+

產物(dist/,已入庫):juzhen.mjs(ESM,供打包器/TypeScript)、juzhen.iife.js(IIFE,全域 Juzhen,原生 <script> 直跑)、juzhen.css(合併樣式,必須引入)、index.d.ts(型別宣告)。

+ +

用法

+

原生 <script>

+
<link rel="stylesheet" href="dist/juzhen.css">
+<script src="dist/juzhen.iife.js"></script>
+<script>
+    const jz = Juzhen.createJuzhen({ scope: { include: ".prose" } });
+    jz.render();      // 對 document.body 套用(僅命中 .prose 子樹)
+    // jz.revert();    // 還原
+</script>
+

ESM/TypeScript

+
import { createJuzhen } from "cjk-autospace";
+import "cjk-autospace/css";
+
+createJuzhen({ lang: { default: "zh-Hant" } }).render(document.querySelector("main"));
+
JS 與 CSS 缺一不可 JS 只注入 jz-* 結構,所有視覺尺寸(間隙寬度、擠壓量、justify 原子化、字體堆疊)都在 juzhen.css。缺 CSS 則全部失效。
+ +

已實作功能

+ + + + + + + + + +
功能說明
中西間隙 spacingCJK↔西文邊界,margin 模型:包裹左側字、以 margin-right 留隙,不注入空白字元 → textContent 完全不變、複製緊湊、justify 不暴增、行首乾淨;行末由 gapTrim layout pass 去隙以齊右。含跨樣式邊界與 codekbd pill(pill 緊鄰標點時穿越 jz-jinze 仍補間隙)。贅餘作者空格一律正規化:CJK↔西文吸收為受管間隙、CJK↔CJK(含跨 inline 標籤)剝除不留隙。
長英文詞 longWord[A-Za-z]{6,} 包入 <span lang="en">,配合消費端 CSS hyphens:auto 原生斷詞(DOM 無連字符 → 複製不污染)。
標點擠壓 jiya標點 charify 為 jz-charbd-* class。三機制:baseline 政策(全角式不擠/開明式擠句內點號+括號引號/半角式全擠)+行內連續擠壓+行端擠壓。半形預設以字型 OpenType halt 渲染;缺 halt 字型可切 margin 後備模式(見下)。
禁則 jinze行首行末避頭尾:閉類/點號綁前一字(不置行首)、開類綁後一字(不置行末);只隔離邊界詞元,長引文中段仍可斷。亦為 justify 綁定載體。
justify 單份間距每個 jz-charinline-block 原子,句末標點只貢獻一份對齊伸縮量。
+

後續(架構已預留,不返工):標點懸掛、標點修正(簡↔繁)、著重號、注音/Ruby。

+ +

選項

+
createJuzhen({
+    lang: {
+        default: "zh-Hant",                        // 無 lang 祖先時之預設語言標籤
+        style: "kaiming",                          // 全域擠壓預設:quanjiao|kaiming|banjiao
+        policy: { "zh-Hant": "quanjiao" },         // 逐 lang 覆寫(最高優先)
+    },
+    scope: { root: document.body, include: ".prose", avoid: "blockquote.raw" },
+    spacing: true,
+    longWord: { minLength: 6, lang: "en" },
+    jiya: true,                                    // 或物件:{ halfWidth: "halt"|"margin", bias }
+    jinze: true,
+    justifyAtoms: true,                            // 分頁器下設 false 改 inline(見下)
+    blocks: [ { selector: ".code-comment", features: [ "spacing" ] } ],
+});
+

擠壓政策優先序:逐 lang policy > 全域 style > 內建預設(繁→全角、簡→開明)。

+

分塊功能選擇(HTML 屬性,就近繼承)

+
<p data-juzhen="spacing jiya">…</p>      <!-- 白名單:僅此二功能 -->
+<p data-juzhen-off="jiya">…</p>          <!-- 黑名單:停用 jiya,其餘繼承 -->
+<div lang="zh-Hans">…</div>              <!-- lang 驅動全角/開明 -->
+ +

標點半形:halt 預設與 margin 後備

+

開明/半角式把標點收成「半形」,有兩種渲染機制:

+ + + + + + +
機制設定原理適用
halt(預設)jiya: true字型 OpenType halt,由字型按字形正確定位、不重疊字型含 halt(Noto CJK/思源系列)
margin(後備)jiya: { halfWidth: "margin" }width:0.5em +字身依墨色偏側溢出定位(以 CSS 重現 halt)字型 halt(多數系統字型、GBK 老字型如方正書宋 GBK、PingFang)
+
為何需要後備 halt 缺席時開明式擠壓「完全無效」(標點仍佔全形)。實測方正書宋 GBK 僅含 vert、無 halt → halt 模式不擠;切 margin 後備後,同句行寬 24.0em → 19.5em、單一標點 1.0em → 0.5em,半形生效。
+ +

激活與粒度

+

模式由 data-jz-halfwidth 屬性所在子樹決定(CSS 後代選擇器),故粒度極靈活:

+ +
<!-- 全頁 halt(預設),此塊改用無 halt 字型 → 局部 margin 後備 -->
+<section data-jz-halfwidth="margin" style="font-family: '方正书宋_GBK'">…</section>
+ +

機制與字形偏側表(margin 模式專用,可覆寫)

+

margin 模式把標點 jz-char 之 inline-block 寬收為 0.5em(真半形 advance),字身(jz-inner)以 overflow 溢出該盒,再依墨色偏側左移、使墨色落於 0.5em 盒內、空白溢向外側——即以 CSS 盒模型重現 halt 之「收字身寬+按字形定位」。相鄰兩標點各 0.5em、合佔 1em,無鄰接疊加或單側重疊問題。

+

偏側依每字墨色中心。聚珍內建參考表(依方正書宋 GBK 實測之 glyph ink 位):簡體點號 ,、。;:!? 偏左;繁體點號居中;彎引號 “”‘’、角括號 「」、尖括號 〈〉 墨色強偏一側(開→right、閉→left);圓/方/書名等括號 ()【】《》… 墨色近中→center。可逐 lang 逐字覆寫:

+
createJuzhen({
+    jiya: {
+        halfWidth: "margin",
+        bias: {
+            "zh-Hans": { ",": "center", "(": "right" },  // 覆寫參考預設
+            "zh-Hant": { "。": "center" },
+        },
+    },
+});
+// 偏側值(決定字身於 0.5em 盒內之左移):
+//   left   墨偏左 → 不移(字身左對齊)
+//   center 墨居中 → 左移 0.25em
+//   right  墨偏右 → 左移 0.5em(右半入盒)
+//   full   無可壓縮空白 → 不收、維持全形
+ +

字型適配工作流(margin 模式配字)

+

換用新字型時,依下列步驟確認半形渲染:

+
    +
  1. haltpython3 tools/measure-bias.py <font.ttf>(需 pip install fonttools)。首行報該字型是否含 OpenType halt。有則直接用預設(halt 模式),到此為止;無則用 margin 後備,續下。
  2. +
  3. 取偏側建議:同一工具量各標點 glyph 之墨色中心、印出建議偏側表與可貼入 jiya.bias 之 JSON。
  4. +
  5. 套用createJuzhen({ jiya: { halfWidth: "margin", bias: <貼入 JSON> } });多數宋體系 GBK 字型與內建參考表相符,未必需覆寫。
  6. +
  7. 目視微調:與原文對照逐字檢查——標點與鄰字重疊則偏側往「不移」方向調(right→center→left);標點與內容仍有空隙則往「多移」方向調(left→center→right);某標點無可壓空白則設 full
  8. +
  9. 記錄:把該字型之 bias 覆寫存入專案設定,作為該字型之適配結果。
  10. +
+

偏側是「字身於 0.5em 盒內左移多少」的三檔量化(0/0.25/0.5em);量測值近門檻時以目視為準。halt 字型由字型精確定位,無此配字需求——margin 配字僅為缺 halt 字型之務實近似。

+ +

CSS 基礎設定(消費端須知)

+

JS 只注入 jz-* 結構,所有視覺尺寸在 juzhen.css。消費端須備妥:

+
    +
  1. 引入樣式(必須)<link rel="stylesheet" href="dist/juzhen.css">(或 ESM import "cjk-autospace/css")。
  2. +
  3. 設定 lang(強烈建議):內容容器標 lang="zh-Hans""zh-Hant""ja",驅動全角/開明政策與字形 locl
  4. +
  5. 作用域類:若設 scope.include: ".juzhen",須給內容容器加對應 class;juzhen.css 之 normalize/字型堆疊亦收斂於此域。
  6. +
  7. 長英文詞斷字:須由消費端 CSS 提供 hyphens: auto(含 -webkit-hyphens)。
  8. +
  9. justify(選用):欲兩端對齊則自設 text-align: justify;句末標點單份間距與行末去隙由聚珍處理。
  10. +
  11. 字型(影響擠壓):半形預設依字型 halt;含 halt 字型(Noto CJK/思源)即可,缺則用 margin 後備。juzhen.css 內建依 :lang 之 Noto CJK 字型堆疊,但僅作後備(全包 :where() 零特異度、只命中帶 lang 屬性之元素、不直接覆寫標點字面容器)——消費端 font-family 恆優先,標點亦隨之以消費端字型渲染。
  12. +
  13. 自動處理juzhen.css 已於 .juzhen 範圍內以 @supports 關閉 Blink 原生 text-spacing-trimtext-autospace,並令注入間隙 user-select: none(複製乾淨)。
  14. +
+ +

分頁器(Paged.js 等)相容:justifyAtoms

+

預設 jz-charjz-jinzeinline-block,作 justify 之單一對齊原子。但分頁器(如 Paged.js)之對齊引擎會把每個 inline-block 邊界當伸縮點、與 CJK inter-ideograph 疊加,於窄欄混排時字距失控、整段散架。此時設 justifyAtoms: false——jz-charjz-jinzedisplay:inline(半形 halt 與禁則 nowrap 綁定均保留)。常規流式版面無需設定。

+
注意 margin 後備半形依賴 inline-blockwidth:0.5em),故 justifyAtoms:falsemargin 模式不可兼得——分頁器場景請用含 halt 之字型。
+ +

v1 向下相容

+
const cjk = createCjkAutospace({ pillSelector: "code, kbd" });
+cjk.apply(document.body);   // → render
+

IIFE 另掛 globalThis.createCjkAutospace 別名。與 v1 之差異(行為等價、不要求逐位一致):間隙由 <span> +真實空格改為 jz-hws margin(複製更乾淨);擠壓改由 juzhen.css 託管,預設仍以字型 halt 渲染半形(同 v1 機制),缺 halt 字型可切 margin 後備。

+ +

目視驗證

+

demo/index.html 載入 dist/ 產物,簡繁並列、可切 justify、附 copy-clean 測試區。demo/fallback.html 以方正書宋 GBK(無 halt)對照 halt 失效 vs margin 後備生效。版面相關結論(justify 單份間距、擠壓視覺量、行端、inline-block 基線)須於 Chrome/Safari/Firefox 三引擎目視核對——jsdom 僅驗證 DOM 結構正確性。

+ +
+ + + + + + + +``` + +JS 只注入 `jz-*` 結構,所有視覺尺寸在 juzhen.css,缺一不可。 + +## 已實作功能 + +- spacing 中西間隙(margin 模型,copy-clean;含 pill 與作者空格正規化) +- longWord 長英文詞包裝(`` + hyphens:auto) +- jiya 標點擠壓(全角/開明/半角;半形 halt 預設、margin 後備) +- jinze 禁則(避頭尾、justify 綁定) +- justify 句末標點單份間距(jz-char inline-block 原子) + +## 標點半形:halt 預設與 margin 後備 + +- halt(預設,`jiya: true`):字型 OpenType halt 定位,需字型支援。 +- margin(`jiya: { halfWidth: "margin" }`):width:0.5em+字身依墨色偏側溢出定位,以 CSS 重現 halt;供缺 halt 字型(如方正書宋 GBK,僅含 vert)。 +- 模式由 `data-jz-halfwidth` 子樹屬性決定,可逐區塊/lang。 +- 偏側 inkBias 給 left/center/right/full,可 `jiya.bias` 逐 lang 逐字覆寫。 + +### 字型適配工作流 + +1. `python3 tools/measure-bias.py ` 驗 halt、量偏側。 +2. 有 halt → 用預設;無 halt → margin 後備+偏側表。 +3. 套用 jiya.bias,瀏覽器目視微調(重疊→往不移;有隙→往多移)。 + +## CSS 基礎設定 + +引入 juzhen.css(必須);設 lang;scope class;hyphens:auto;text-align:justify(選用);含 halt 字型或 margin 後備。juzhen.css 之 Noto 字型堆疊僅作後備,消費端 font-family 恆優先。 + +## 分頁器相容 + +`justifyAtoms: false` → jz-char/jz-jinze 改 display:inline,相容 Paged.js。margin 後備與 justifyAtoms:false 不可兼得。 + +## v1 相容 + +`createCjkAutospace(opts).apply(root)` 經相容層映射至 createJuzhen,零改動可跑。 + +MIT。借鑑 Han.css/Heti 思路與分類表,成品自含。 + + + + + + diff --git a/docs/index.src.html b/docs/index.src.html new file mode 100644 index 0000000..0405965 --- /dev/null +++ b/docs/index.src.html @@ -0,0 +1,223 @@ + + + + + +聚珍(Juzhen) + + + + + + +
+
+

聚珍(Juzhen)

+

現代簡/繁中文網頁排版套件——Han.css 之現代化重寫,複製乾淨、依 lang 全角/開明切換、justify 句末標點單份間距、跨瀏覽器一致。

+

· cjk-autospace · 使用文檔

+
+
+ +
+
+ +
+ +

聚珍(Juzhen)是現代簡/繁中文網頁排版套件,Han.css 之現代化重寫,沿其功能版圖,並針對四點作調整:複製乾淨(中西間隙不入剪貼板)、依 lang 全角/開明自動切換、justify 下句末標點只佔一份間距、跨瀏覽器一致。倉庫名仍為 cjk-autospace;公開 API 為 createJuzhen /全域 Juzhen;注入之自訂元素前綴 jz-

+ +

本版(2.x)為從零重寫。v1 之 createCjkAutospace API 由相容層保留,既有消費端不需改碼即可運行;v1 原始碼保存於 v1-autospace 分支。設計契約見 ARCHITECTURE.md

+ +

安裝與構建

+
npm install
+npm run build   # esbuild → dist/juzhen.{mjs,iife.js,css};tsc → dist/index.d.ts
+npm test        # jsdom DOM 正確性測試
+

產物(dist/,已入庫):juzhen.mjs(ESM,供打包器/TypeScript)、juzhen.iife.js(IIFE,全域 Juzhen,原生 <script> 直跑)、juzhen.css(合併樣式,必須引入)、index.d.ts(型別宣告)。

+ +

用法

+

原生 <script>

+
<link rel="stylesheet" href="dist/juzhen.css">
+<script src="dist/juzhen.iife.js"></script>
+<script>
+    const jz = Juzhen.createJuzhen({ scope: { include: ".prose" } });
+    jz.render();      // 對 document.body 套用(僅命中 .prose 子樹)
+    // jz.revert();    // 還原
+</script>
+

ESM/TypeScript

+
import { createJuzhen } from "cjk-autospace";
+import "cjk-autospace/css";
+
+createJuzhen({ lang: { default: "zh-Hant" } }).render(document.querySelector("main"));
+
JS 與 CSS 缺一不可 JS 只注入 jz-* 結構,所有視覺尺寸(間隙寬度、擠壓量、justify 原子化、字體堆疊)都在 juzhen.css。缺 CSS 則全部失效。
+ +

已實作功能

+ + + + + + + + + +
功能說明
中西間隙 spacingCJK↔西文邊界,margin 模型:包裹左側字、以 margin-right 留隙,不注入空白字元 → textContent 完全不變、複製緊湊、justify 不暴增、行首乾淨;行末由 gapTrim layout pass 去隙以齊右。含跨樣式邊界與 codekbd pill(pill 緊鄰標點時穿越 jz-jinze 仍補間隙)。贅餘作者空格一律正規化:CJK↔西文吸收為受管間隙、CJK↔CJK(含跨 inline 標籤)剝除不留隙。
長英文詞 longWord[A-Za-z]{6,} 包入 <span lang="en">,配合消費端 CSS hyphens:auto 原生斷詞(DOM 無連字符 → 複製不污染)。
標點擠壓 jiya標點 charify 為 jz-charbd-* class。三機制:baseline 政策(全角式不擠/開明式擠句內點號+括號引號/半角式全擠)+行內連續擠壓+行端擠壓。半形預設以字型 OpenType halt 渲染;缺 halt 字型可切 margin 後備模式(見下)。
禁則 jinze行首行末避頭尾:閉類/點號綁前一字(不置行首)、開類綁後一字(不置行末);只隔離邊界詞元,長引文中段仍可斷。亦為 justify 綁定載體。
justify 單份間距每個 jz-charinline-block 原子,句末標點只貢獻一份對齊伸縮量。
+

後續(架構已預留,不返工):標點懸掛、標點修正(簡↔繁)、著重號、注音/Ruby。

+ +

選項

+
createJuzhen({
+    lang: {
+        default: "zh-Hant",                        // 無 lang 祖先時之預設語言標籤
+        style: "kaiming",                          // 全域擠壓預設:quanjiao|kaiming|banjiao
+        policy: { "zh-Hant": "quanjiao" },         // 逐 lang 覆寫(最高優先)
+    },
+    scope: { root: document.body, include: ".prose", avoid: "blockquote.raw" },
+    spacing: true,
+    longWord: { minLength: 6, lang: "en" },
+    jiya: true,                                    // 或物件:{ halfWidth: "halt"|"margin", bias }
+    jinze: true,
+    justifyAtoms: true,                            // 分頁器下設 false 改 inline(見下)
+    blocks: [ { selector: ".code-comment", features: [ "spacing" ] } ],
+});
+

擠壓政策優先序:逐 lang policy > 全域 style > 內建預設(繁→全角、簡→開明)。

+

分塊功能選擇(HTML 屬性,就近繼承)

+
<p data-juzhen="spacing jiya">…</p>      <!-- 白名單:僅此二功能 -->
+<p data-juzhen-off="jiya">…</p>          <!-- 黑名單:停用 jiya,其餘繼承 -->
+<div lang="zh-Hans">…</div>              <!-- lang 驅動全角/開明 -->
+ +

標點半形:halt 預設與 margin 後備

+

開明/半角式把標點收成「半形」,有兩種渲染機制:

+ + + + + + +
機制設定原理適用
halt(預設)jiya: true字型 OpenType halt,由字型按字形正確定位、不重疊字型含 halt(Noto CJK/思源系列)
margin(後備)jiya: { halfWidth: "margin" }width:0.5em +字身依墨色偏側溢出定位(以 CSS 重現 halt)字型 halt(多數系統字型、GBK 老字型如方正書宋 GBK、PingFang)
+
為何需要後備 halt 缺席時開明式擠壓「完全無效」(標點仍佔全形)。實測方正書宋 GBK 僅含 vert、無 halt → halt 模式不擠;切 margin 後備後,同句行寬 24.0em → 19.5em、單一標點 1.0em → 0.5em,半形生效。
+ +

激活與粒度

+

模式由 data-jz-halfwidth 屬性所在子樹決定(CSS 後代選擇器),故粒度極靈活:

+
    +
  • 全域jiya: { halfWidth: "margin" }render() 於處理 root 自動掛屬性。
  • +
  • 逐區塊/逐語言:在 HTML 任一祖先手寫 data-jz-halfwidth="margin"(或 "halt"),即令該子樹用對應機制,無需另建實例。常見如「全頁 halt,某用無 halt 字型之區塊掛 margin」,或反之(margin 頁中嵌一塊 halt 島)。
  • +
+
<!-- 全頁 halt(預設),此塊改用無 halt 字型 → 局部 margin 後備 -->
+<section data-jz-halfwidth="margin" style="font-family: '方正书宋_GBK'">…</section>
+ +

機制與字形偏側表(margin 模式專用,可覆寫)

+

margin 模式把標點 jz-char 之 inline-block 寬收為 0.5em(真半形 advance),字身(jz-inner)以 overflow 溢出該盒,再依墨色偏側左移、使墨色落於 0.5em 盒內、空白溢向外側——即以 CSS 盒模型重現 halt 之「收字身寬+按字形定位」。相鄰兩標點各 0.5em、合佔 1em,無鄰接疊加或單側重疊問題。

+

偏側依每字墨色中心。聚珍內建參考表(依方正書宋 GBK 實測之 glyph ink 位):簡體點號 ,、。;:!? 偏左;繁體點號居中;彎引號 “”‘’、角括號 「」、尖括號 〈〉 墨色強偏一側(開→right、閉→left);圓/方/書名等括號 ()【】《》… 墨色近中→center。可逐 lang 逐字覆寫:

+
createJuzhen({
+    jiya: {
+        halfWidth: "margin",
+        bias: {
+            "zh-Hans": { ",": "center", "(": "right" },  // 覆寫參考預設
+            "zh-Hant": { "。": "center" },
+        },
+    },
+});
+// 偏側值(決定字身於 0.5em 盒內之左移):
+//   left   墨偏左 → 不移(字身左對齊)
+//   center 墨居中 → 左移 0.25em
+//   right  墨偏右 → 左移 0.5em(右半入盒)
+//   full   無可壓縮空白 → 不收、維持全形
+ +

字型適配工作流(margin 模式配字)

+

換用新字型時,依下列步驟確認半形渲染:

+
    +
  1. haltpython3 tools/measure-bias.py <font.ttf>(需 pip install fonttools)。首行報該字型是否含 OpenType halt。有則直接用預設(halt 模式),到此為止;無則用 margin 後備,續下。
  2. +
  3. 取偏側建議:同一工具量各標點 glyph 之墨色中心、印出建議偏側表與可貼入 jiya.bias 之 JSON。
  4. +
  5. 套用createJuzhen({ jiya: { halfWidth: "margin", bias: <貼入 JSON> } });多數宋體系 GBK 字型與內建參考表相符,未必需覆寫。
  6. +
  7. 目視微調:與原文對照逐字檢查——標點與鄰字重疊則偏側往「不移」方向調(right→center→left);標點與內容仍有空隙則往「多移」方向調(left→center→right);某標點無可壓空白則設 full
  8. +
  9. 記錄:把該字型之 bias 覆寫存入專案設定,作為該字型之適配結果。
  10. +
+

偏側是「字身於 0.5em 盒內左移多少」的三檔量化(0/0.25/0.5em);量測值近門檻時以目視為準。halt 字型由字型精確定位,無此配字需求——margin 配字僅為缺 halt 字型之務實近似。

+ +

CSS 基礎設定(消費端須知)

+

JS 只注入 jz-* 結構,所有視覺尺寸在 juzhen.css。消費端須備妥:

+
    +
  1. 引入樣式(必須)<link rel="stylesheet" href="dist/juzhen.css">(或 ESM import "cjk-autospace/css")。
  2. +
  3. 設定 lang(強烈建議):內容容器標 lang="zh-Hans""zh-Hant""ja",驅動全角/開明政策與字形 locl
  4. +
  5. 作用域類:若設 scope.include: ".juzhen",須給內容容器加對應 class;juzhen.css 之 normalize/字型堆疊亦收斂於此域。
  6. +
  7. 長英文詞斷字:須由消費端 CSS 提供 hyphens: auto(含 -webkit-hyphens)。
  8. +
  9. justify(選用):欲兩端對齊則自設 text-align: justify;句末標點單份間距與行末去隙由聚珍處理。
  10. +
  11. 字型(影響擠壓):半形預設依字型 halt;含 halt 字型(Noto CJK/思源)即可,缺則用 margin 後備。juzhen.css 內建依 :lang 之 Noto CJK 字型堆疊,但僅作後備(全包 :where() 零特異度、只命中帶 lang 屬性之元素、不直接覆寫標點字面容器)——消費端 font-family 恆優先,標點亦隨之以消費端字型渲染。
  12. +
  13. 自動處理juzhen.css 已於 .juzhen 範圍內以 @supports 關閉 Blink 原生 text-spacing-trimtext-autospace,並令注入間隙 user-select: none(複製乾淨)。
  14. +
+ +

分頁器(Paged.js 等)相容:justifyAtoms

+

預設 jz-charjz-jinzeinline-block,作 justify 之單一對齊原子。但分頁器(如 Paged.js)之對齊引擎會把每個 inline-block 邊界當伸縮點、與 CJK inter-ideograph 疊加,於窄欄混排時字距失控、整段散架。此時設 justifyAtoms: false——jz-charjz-jinzedisplay:inline(半形 halt 與禁則 nowrap 綁定均保留)。常規流式版面無需設定。

+
注意 margin 後備半形依賴 inline-blockwidth:0.5em),故 justifyAtoms:falsemargin 模式不可兼得——分頁器場景請用含 halt 之字型。
+ +

v1 向下相容

+
const cjk = createCjkAutospace({ pillSelector: "code, kbd" });
+cjk.apply(document.body);   // → render
+

IIFE 另掛 globalThis.createCjkAutospace 別名。與 v1 之差異(行為等價、不要求逐位一致):間隙由 <span> +真實空格改為 jz-hws margin(複製更乾淨);擠壓改由 juzhen.css 託管,預設仍以字型 halt 渲染半形(同 v1 機制),缺 halt 字型可切 margin 後備。

+ +

目視驗證

+

demo/index.html 載入 dist/ 產物,簡繁並列、可切 justify、附 copy-clean 測試區。demo/fallback.html 以方正書宋 GBK(無 halt)對照 halt 失效 vs margin 後備生效。版面相關結論(justify 單份間距、擠壓視覺量、行端、inline-block 基線)須於 Chrome/Safari/Firefox 三引擎目視核對——jsdom 僅驗證 DOM 結構正確性。

+ +
+ +
+

本頁為聚珍(Juzhen)使用文檔。所有文檔操作均於 docs 分支進行;main 僅存一份未追蹤之本地鏡像。MIT 授權;借鑑 Han.css/Heti 之思路與分類表,成品自含。

+
+ + + + + +``` + +JS 只注入 `jz-*` 結構,所有視覺尺寸在 juzhen.css,缺一不可。 + +## 已實作功能 + +- spacing 中西間隙(margin 模型,copy-clean;含 pill 與作者空格正規化) +- longWord 長英文詞包裝(`` + hyphens:auto) +- jiya 標點擠壓(全角/開明/半角;半形 halt 預設、margin 後備) +- jinze 禁則(避頭尾、justify 綁定) +- justify 句末標點單份間距(jz-char inline-block 原子) + +## 標點半形:halt 預設與 margin 後備 + +- halt(預設,`jiya: true`):字型 OpenType halt 定位,需字型支援。 +- margin(`jiya: { halfWidth: "margin" }`):width:0.5em+字身依墨色偏側溢出定位,以 CSS 重現 halt;供缺 halt 字型(如方正書宋 GBK,僅含 vert)。 +- 模式由 `data-jz-halfwidth` 子樹屬性決定,可逐區塊/lang。 +- 偏側 inkBias 給 left/center/right/full,可 `jiya.bias` 逐 lang 逐字覆寫。 + +### 字型適配工作流 + +1. `python3 tools/measure-bias.py ` 驗 halt、量偏側。 +2. 有 halt → 用預設;無 halt → margin 後備+偏側表。 +3. 套用 jiya.bias,瀏覽器目視微調(重疊→往不移;有隙→往多移)。 + +## CSS 基礎設定 + +引入 juzhen.css(必須);設 lang;scope class;hyphens:auto;text-align:justify(選用);含 halt 字型或 margin 後備。juzhen.css 之 Noto 字型堆疊僅作後備,消費端 font-family 恆優先。 + +## 分頁器相容 + +`justifyAtoms: false` → jz-char/jz-jinze 改 display:inline,相容 Paged.js。margin 後備與 justifyAtoms:false 不可兼得。 + +## v1 相容 + +`createCjkAutospace(opts).apply(root)` 經相容層映射至 createJuzhen,零改動可跑。 + +MIT。借鑑 Han.css/Heti 思路與分類表,成品自含。 + + + + + +