Files
cjk-autospace/README.md
T
admin 2d42c7ecf2 feat: 聚珍切片 1 — 中西間隙/標點擠壓/禁則 + v1 相容層
從零重寫之第一垂直切片(依 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% 等詞元不被禁則切斷。
2026-06-01 21:31:07 +08:00

140 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 聚珍(Juzhen
> 現代簡/繁中文網頁排版套件。Han.css 之現代化重寫,沿其功能版圖,並針對
> 數種情況作調整:**複製乾淨**(中西間隙不入剪貼板)、**依 `lang` 全角/開明
> 自動切換**、**`justify` 下句末標點只佔一份間距**、**跨瀏覽器一致**
> ChromeEdgeSafariWebKitFirefox)。
倉庫名仍為 `cjk-autospace`;公開 API 為 `createJuzhen` / 全域 `Juzhen`;注入之
自訂元素前綴 `jz-`。完整設計見 [`ARCHITECTURE.md`](./ARCHITECTURE.md)。
> 本版(2.x)為從零重寫。v1 之 `createCjkAutospace` API 由相容層保留(見下),
> 既有消費端不需改碼即可運行;v1 原始碼保存於 `v1-autospace` 分支。
---
## 安裝與構建
```sh
npm install
npm run build # esbuild → dist/juzhen.{mjs,iife.js,css}tsc → dist/index.d.ts
npm test # jsdom DOM 正確性測試
```
產物(`dist/`,已入庫):
| 檔 | 用途 |
|---|---|
| `dist/juzhen.mjs` | ESM,供打包器/TypeScript |
| `dist/juzhen.iife.js` | IIFE,全域 `Juzhen`,原生 `<script>` 直跑 |
| `dist/juzhen.css` | 合併樣式(**必須引入**,視覺尺寸全在此) |
| `dist/index.d.ts` | TypeScript 型別宣告 |
---
## 用法
### 原生 `<script>`
```html
<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>
```
### ESMTypeScript
```ts
import { createJuzhen } from "cjk-autospace";
import "cjk-autospace/css";
const jz = createJuzhen({ lang: { default: "zh-Hant" } });
jz.render(document.querySelector("main"));
```
**JS 與 CSS 缺一不可**JS 只注入 `jz-*` 結構,所有視覺尺寸(間隙寬度、擠壓量、
`justify` 原子化、字體堆疊)都在 `juzhen.css`
---
## 切片 1 已實作功能
| 功能 | 說明 |
|---|---|
| **中西間隙** `spacing` | CJK↔西文邊界插入 copy-clean 之 `jz-hws``user-select:none`,剪貼板跳過)。含跨樣式行內邊界與 `code``kbd` pill 邊界。 |
| **長英文詞** `longWord` | `[A-Za-z]{6,}` 包入 `<span lang="en">`,配合 CSS `hyphens:auto` 原生斷詞(DOM 無連字符 → 複製不污染)。 |
| **標點擠壓** `jiya` | 標點 charify 為 `jz-char``bd-*` class。三機制:①baseline 政策(全角式不擠/開明式擠句內點號+括號引號/半角式全擠);②行內連續擠壓(相鄰標點對向側收);③行端擠壓(`lineedge` layout pass)。半形以字型 `halt` 渲染(按字形正確定位,居中字形如 `!?`/繁體 `。,` 不重疊;不依賴 `text-spacing-trim`)。 |
| **禁則** `jinze` | 行首行末避頭尾:閉類/點號綁前一字(不置行首)、開類綁後一字(不置行末),只隔離邊界字故長引文中段仍可斷。亦為 `justify` 綁定載體。 |
| **justify 單份間距** | 每個 `jz-char``inline-block` 原子項,句末標點只貢獻一份對齊伸縮量。 |
後續(架構已預留,不返工):標點懸掛、標點修正(簡↔繁)、著重號、注音/Ruby。
---
## 選項
```ts
createJuzhen({
lang: {
default: "zh-Hant", // 無 lang 祖先時之預設
policy: { "zh-Hant": "quanjiao", "zh-Hans": "kaiming" }, // 全角/開明/半角
},
scope: {
root: document.body, // 處理根;render(root) 可逐次覆寫
include: ".prose", // 啟用選擇器(opt-in):僅處理命中子樹
avoid: "blockquote.raw", // 追加排除選擇器
},
spacing: true,
longWord: { minLength: 6, lang: "en" },
jiya: true,
jinze: true,
blocks: [ // 分塊功能選擇
{ selector: ".code-comment", features: [ "spacing" ] },
],
});
```
### 分塊功能選擇(HTML 屬性,就近繼承)
```html
<p data-juzhen="spacing jiya"></p> <!-- 白名單:僅此二功能 -->
<p data-juzhen-off="jiya"></p> <!-- 黑名單:停用 jiya,其餘繼承 -->
<div lang="zh-Hans"></div> <!-- lang 驅動全角/開明 -->
```
---
## v1 向下相容
```js
// 既有消費端零改動:
const cjk = createCjkAutospace({ pillSelector: "code, kbd" });
cjk.apply(document.body);
```
IIFE 構建另掛 `globalThis.createCjkAutospace` 別名。**與 v1 之差異**(行為等價、
不要求逐位一致):
- 間隙標記由 `<span class="cjk-autospace">` 變為 `<jz-hws class="cjk-autospace">`
(仍帶原 class,既有 `.cjk-autospace{user-select:none}` CSS 仍命中)。
- 標點擠壓由消費端 `font-feature-settings:"halt"` 改為 `juzhen.css` 之負 `margin`
(需改用 `juzhen.css`;機制不同,同為開明式「句內點號半形」之效果)。
---
## 目視驗證
`demo/index.html` 載入 `dist/` 產物,簡繁並列、可切 `justify`、附 copy-clean 測試區。
版面相關結論(justify 單份間距、擠壓視覺量、行端、`inline-block` 基線)須於
ChromeSafariFirefox 三引擎目視核對——jsdom 僅驗證 DOM 結構正確性。
---
## 授權
MIT。借鑑 Han.cssHeti 之思路與分類表(MIT),成品自含、不依賴其執行期程式碼。