refactor: 字型移出聚珍管理(移除 _lang.css),交消費端;半形顯式保留 locl
下游回饋之字型樹需求。決策:字型屬消費端領域,聚珍不應內建字型堆疊(原 _lang.css
之 Noto 後備係越權,且曾蓋掉消費端字型釀 bug)。採「完全移除、交消費端 CSS」(A 案),
否決「以參數管字型」(B 案——JS 管字型須注入 CSS、違反 JS 注入結構/CSS 給視覺之分工;
而缺 halt 字型須逐字型微調 margin 之指引,由既有 jiya.halfWidth/jiya.bias +文檔承擔)。
移除:
- 刪 src/css/_lang.css,juzhen.css 移除其 @import。dist/juzhen.css 現零 font-family
規則(3.1→2.5kb)。
聚珍保留之三項非管理性本分(確保不礙消費端字型與 locl):
- _normalize.css `jz-* { font: inherit }`:原子繼承消費端字型、不強加。
- _jiya.css 半形 font-feature-settings 顯式改 "locl" 1, "halt" 1(預設+halt-island 兩
處):確保泛 CJK 字型(思源/Noto CJK)之地域標點字形不因設 halt 而失。
- render 只讀不改 lang。body 文本之 locl 全由消費端字型+正確 lang 決定。
驗證(真實 Chromium):
- halt 模式:消費端逐 lang 字型生效並繼承至 jz-inner,無強制 Noto。
- margin 後備:半形盒 0.5em、字身依墨色偏側位移正確、jz-inner 繼承消費端字型、
feature normal(locl 既定開),皆不受字型移除影響。
- demo/index.html、resize-check.html 改示範「消費端逐 lang 設 font-family」之推薦範式;
fallback.html 更新註解。
- README 新增「字型與 locl」節+改寫 CSS 基礎設定字型項;ARCHITECTURE §6.9 改寫
(A 案決策、否決 B 案、三項本分)+檔案樹。
- test:新增 CSS 回歸(不內建 font-family、半形保留 locl)。57 測試通過。
- dist/ 重建(僅 juzhen.css 變動,JS 不變)。
This commit is contained in:
+17
-7
@@ -473,12 +473,22 @@ class 約定:`bd`(標點)、`bd-open/close/cop/stop/sep/liga`、`cjk`、`j
|
|||||||
- **我們**:基於原生 `<ruby>` + `jz-ruby/jz-rt` 處理注音符號直排與聲調定位。
|
- **我們**:基於原生 `<ruby>` + `jz-ruby/jz-rt` 處理注音符號直排與聲調定位。
|
||||||
- **預留**:獨立 pass,`order=80`;不影響其餘。
|
- **預留**:獨立 pass,`order=80`;不影響其餘。
|
||||||
|
|
||||||
### 6.9 樣式正常化/字體堆疊 — 貫穿(CSS)
|
### 6.9 樣式正常化/字型歸屬 — 貫穿(CSS)
|
||||||
|
|
||||||
- **我們**:`juzhen.css` 內以 `:where()`(零特異度,易被消費端覆寫)提供 CJK
|
- **normalize**:`juzhen.css` 內以 `@supports`/`:where()` 提供 CJK normalize(關閉
|
||||||
normalize 與依 `:lang` 之 Noto Sans/Serif CJK SC/TC/HK/JP 字體堆疊。非破壞、
|
與託管擠壓重複作用之原生 `text-spacing-trim`/`text-autospace`、間隙 `user-select`
|
||||||
opt-in(掛在 `.juzhen` 容器或 `[data-juzhen]` 下)。
|
等),限 `.juzhen` 域、非破壞。
|
||||||
- **跨瀏覽器**:`:where()`/`:lang()` 普遍支援。
|
- **字型不歸聚珍管(設計決策,下游回饋)**:曾內建依 `:lang` 之 Noto 字型堆疊作「後備」,
|
||||||
|
但字型屬消費端領域、內建即越權(且曾蓋掉消費端字型釀 bug)。故**移除 `_lang.css`**,
|
||||||
|
逐語言 `font-family` 完全交消費端 CSS。聚珍僅守三項非管理性本分:① `_normalize.css`
|
||||||
|
之 `jz-* { font: inherit }` 使原子繼承消費端字型、不強加;② `_jiya.css` 半形之
|
||||||
|
`font-feature-settings` 顯式併入 `"locl" 1`(連同 `halt`),確保泛 CJK 字型之地域標點
|
||||||
|
字形不因設 halt 而失;③ render 只讀不改 `lang`。body 文本之 `locl` 本就不受聚珍影響
|
||||||
|
(未設任何 feature),由消費端字型+正確 `lang` 決定。消費端範式見 README「字型與 locl」。
|
||||||
|
- **B 案(字型參數)之否決**:以 JS 參數管字型須注入 CSS、違反「JS 注入結構/CSS 給視覺」
|
||||||
|
分工;而「缺 halt 字型須逐字型微調 margin」之指引由既有 `jiya.halfWidth`/`jiya.bias`
|
||||||
|
參數+文檔承擔,無需新參數。
|
||||||
|
- **跨瀏覽器**:`:where()`/`:lang()`/`font-feature-settings` 普遍支援。
|
||||||
|
|
||||||
### 6.10 計數器/緊排(counter/well-knit)— 低優先
|
### 6.10 計數器/緊排(counter/well-knit)— 低優先
|
||||||
|
|
||||||
@@ -626,8 +636,8 @@ src/
|
|||||||
ruby.ts 注音/ruby [後續]
|
ruby.ts 注音/ruby [後續]
|
||||||
css/
|
css/
|
||||||
juzhen.css 入口(@import 各 partial)
|
juzhen.css 入口(@import 各 partial)
|
||||||
_normalize.css _lang.css _spacing.css _jiya.css _jinze.css
|
_normalize.css _spacing.css _jiya.css _jinze.css
|
||||||
_hanging.css _emphasis.css _ruby.css
|
_hanging.css _emphasis.css _ruby.css (字型不內建,交消費端)
|
||||||
test/ jsdom DOM 正確性測試
|
test/ jsdom DOM 正確性測試
|
||||||
demo/ 瀏覽器 layout/justify/簡繁 目視驗證頁
|
demo/ 瀏覽器 layout/justify/簡繁 目視驗證頁
|
||||||
build.mjs esbuild:ESM + IIFE + CSS;tsc:d.ts
|
build.mjs esbuild:ESM + IIFE + CSS;tsc:d.ts
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ jz.render(document.querySelector("main"));
|
|||||||
|
|
||||||
| 功能 | 說明 |
|
| 功能 | 說明 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **中西間隙** `spacing` | CJK↔西文邊界插入 copy-clean 之 `jz-hws`(`user-select:none`,剪貼板跳過)。含跨樣式行內邊界與 `code`/`kbd` pill 邊界(pill 緊鄰標點時穿越 `jz-jinze` 仍補間隙)。贅餘作者空格一律正規化:CJK↔西文吸收為受管間隙、CJK↔CJK(含跨 inline 標籤)剝除不留隙。 |
|
| **中西間隙** `spacing` | CJK↔西文邊界插入 copy-clean 之 `jz-hws`(`user-select:none`,剪貼板跳過)。「西文」涵蓋拉丁(含擴充 A/B,拼音聲調 `ā ǎ ē`)、希臘、西里爾、數字、貨幣(`€ ₩ ₿`)、數學運算符等;CJK 標點(`。,「」()……` 等)不誤判為西文、不生隙。含跨樣式行內邊界與 `code`/`kbd` pill 邊界(pill 緊鄰標點時穿越 `jz-jinze` 仍補間隙;pill 跨行右隙、間隙落行末之自我應驗皆已修)。贅餘作者空格一律正規化:CJK↔西文吸收為受管間隙、CJK↔CJK(含跨 inline 標籤)剝除不留隙。 |
|
||||||
| **長英文詞** `longWord` | `[A-Za-z]{6,}` 包入 `<span lang="en">`,配合 CSS `hyphens:auto` 原生斷詞(DOM 無連字符 → 複製不污染)。 |
|
| **長英文詞** `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`)。**字型缺 `halt` 時可切 `margin` 後備模式**(見下節)。 |
|
| **標點擠壓** `jiya` | 標點 charify 為 `jz-char`+`bd-*` class。三機制:①baseline 政策(全角式不擠/開明式擠句內點號+括號引號/半角式全擠);②行內連續擠壓(相鄰標點對向側收);③行端擠壓(`lineedge` layout pass)。半形預設以字型 `halt` 渲染(按字形正確定位,居中字形如 `!?`/繁體 `。,` 不重疊;不依賴 `text-spacing-trim`)。**字型缺 `halt` 時可切 `margin` 後備模式**(見下節)。 |
|
||||||
| **禁則** `jinze` | 行首行末避頭尾:閉類/點號綁前一字(不置行首)、開類綁後一字(不置行末),只隔離邊界字故長引文中段仍可斷。亦為 `justify` 綁定載體。 |
|
| **禁則** `jinze` | 行首行末避頭尾:閉類/點號綁前一字(不置行首)、開類綁後一字(不置行末),只隔離邊界字故長引文中段仍可斷。亦為 `justify` 綁定載體。 |
|
||||||
@@ -216,18 +216,18 @@ JS 只注入 `jz-*` 結構,**所有視覺尺寸在 `juzhen.css`**——故 CSS
|
|||||||
2. **設定 `lang`(強烈建議)**:在內容容器標 `lang="zh-Hans"`/`"zh-Hant"`/`"ja"`,
|
2. **設定 `lang`(強烈建議)**:在內容容器標 `lang="zh-Hans"`/`"zh-Hant"`/`"ja"`,
|
||||||
驅動全角/開明政策與字形 `locl`。無 `lang` 時回退 `options.lang.default`。
|
驅動全角/開明政策與字形 `locl`。無 `lang` 時回退 `options.lang.default`。
|
||||||
3. **作用域類(用 `scope.include` 時)**:若設 `scope.include: ".juzhen"`,須給內容
|
3. **作用域類(用 `scope.include` 時)**:若設 `scope.include: ".juzhen"`,須給內容
|
||||||
容器加對應 class(如 `class="juzhen"`);`juzhen.css` 之 normalize/字型堆疊亦
|
容器加對應 class(如 `class="juzhen"`);`juzhen.css` 之 normalize 亦收斂於此域,
|
||||||
收斂於此域,不外溢。
|
不外溢。
|
||||||
4. **長英文詞斷字**:`longWord` 包出 `<span lang="en">` 後,須由消費端 CSS 提供
|
4. **長英文詞斷字**:`longWord` 包出 `<span lang="en">` 後,須由消費端 CSS 提供
|
||||||
`hyphens: auto`(含 `-webkit-hyphens`)才會原生斷詞顯示連字符。
|
`hyphens: auto`(含 `-webkit-hyphens`)才會原生斷詞顯示連字符。
|
||||||
5. **`justify`(選用)**:欲兩端對齊則自行設 `text-align: justify`;句末標點單份間距
|
5. **`justify`(選用)**:欲兩端對齊則自行設 `text-align: justify`;句末標點單份間距
|
||||||
與行末去隙由聚珍處理,無需額外設定。
|
與行末去隙由聚珍處理,無需額外設定。
|
||||||
6. **字型(影響擠壓)**:開明/半角式半形預設依字型 `halt`。若用含 `halt` 之字型
|
6. **字型由消費端負責(聚珍不管字型)**:聚珍**不**內建任何 `font-family`/字型堆疊
|
||||||
(Noto CJK/思源),預設即可;若用缺 `halt` 之字型,改用 `margin` 後備模式(見
|
——逐語言字型完全由消費端 CSS 決定。聚珍只確保原子(`jz-*`)以 `font: inherit`
|
||||||
上節)。`juzhen.css` 內建依 `:lang` 之 Noto Sans/Serif CJK 字型堆疊,但**僅作
|
繼承消費端字型、絕不強加,並顯式保留 `locl`(見下「字型與 locl」一節)。半形擠壓
|
||||||
後備**(全包於 `:where()`、零特異度,且只命中帶 `lang` 屬性之元素、不直接覆寫標點
|
依字型 OpenType `halt`:含 `halt` 之字型(Noto CJK/思源)預設即可;**缺 `halt`
|
||||||
字面容器 `jz-inner`)——**消費端在 `.juzhen` 或任一祖先設 `font-family` 即恆優先**,
|
之字型**(如方正書宋 GBK)須改用 `jiya.halfWidth:"margin"` 後備,並按字型以
|
||||||
標點亦隨之以消費端字型渲染(故缺 `halt` 字型務必配 `margin` 後備,否則標點不擠)。
|
`jiya.bias` 逐字微調墨色偏側(見「字型適配工作流」)。
|
||||||
7. **自動處理、無需消費端介入**:`juzhen.css` 已在 `.juzhen` 範圍內以 `@supports`
|
7. **自動處理、無需消費端介入**:`juzhen.css` 已在 `.juzhen` 範圍內以 `@supports`
|
||||||
關閉 Blink 原生 `text-spacing-trim`/`text-autospace`(避免與託管擠壓重複作用),
|
關閉 Blink 原生 `text-spacing-trim`/`text-autospace`(避免與託管擠壓重複作用),
|
||||||
並令注入間隙 `user-select: none`(複製乾淨)。
|
並令注入間隙 `user-select: none`(複製乾淨)。
|
||||||
@@ -239,6 +239,29 @@ JS 只注入 `jz-*` 結構,**所有視覺尺寸在 `juzhen.css`**——故 CSS
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 字型與 locl(消費端設定)
|
||||||
|
|
||||||
|
聚珍**不管字型**;逐語言字型由你以 CSS 設定。推薦範式——逐 `lang` 設 `font-family`,
|
||||||
|
掛在 `.juzhen` 或帶 `lang` 之容器(**勿**直接設 `jz-inner`/`jz-char`,它們靠繼承取字型):
|
||||||
|
|
||||||
|
```css
|
||||||
|
.juzhen:lang(zh-Hans), .juzhen [lang]:lang(zh-Hans) { font-family: "Noto Serif SC", "Source Han Serif SC", serif; }
|
||||||
|
.juzhen:lang(zh-Hant), .juzhen [lang]:lang(zh-Hant) { font-family: "Noto Serif TC", "Source Han Serif TC", serif; }
|
||||||
|
.juzhen:lang(ja), .juzhen [lang]:lang(ja) { font-family: "Noto Serif JP", serif; }
|
||||||
|
```
|
||||||
|
|
||||||
|
要點:
|
||||||
|
|
||||||
|
- **字型須含 OpenType `halt`** 才能半形擠壓;否則用 `jiya.halfWidth:"margin"` + 按字型
|
||||||
|
以 `jiya.bias` 逐字微調墨色偏側(見「字型適配工作流」)。
|
||||||
|
- **locl(地域字形)**:泛 CJK 字型(思源/Noto CJK)以 `locl` 依 `lang` 選地域字形
|
||||||
|
(如「直/海/骨」之簡繁日差異)。聚珍**不改寫 `lang`、不關閉 locl**,故只要你 ①
|
||||||
|
正確標 `lang`、② 用支援 locl 之字型,locl 即正常。body 文本之 locl 全由你的字型+
|
||||||
|
`lang` 決定;標點(`jz-inner`)之 `halt` 已顯式併入 `locl`,地域標點字形不致失。
|
||||||
|
- 若只想全語言同一字型,直接 `.juzhen { font-family: … }` 即可(無需逐 `lang`)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v1 向下相容
|
## v1 向下相容
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|||||||
+3
-2
@@ -18,8 +18,9 @@
|
|||||||
/* 字型類獨立於 .juzhen:A 用裸 .cn(瀏覽器原生排版),B/C 才掛 .juzhen
|
/* 字型類獨立於 .juzhen:A 用裸 .cn(瀏覽器原生排版),B/C 才掛 .juzhen
|
||||||
(含 normalize 之 text-spacing-trim:space-all)。否則 A 之原生標點被 space-all
|
(含 normalize 之 text-spacing-trim:space-all)。否則 A 之原生標點被 space-all
|
||||||
撐開、顯得比 B 鬆,造成「B 似乎有效」之假象(實則 B 全形未擠、與真原文等寬)。 */
|
撐開、顯得比 B 鬆,造成「B 似乎有效」之假象(實則 B 全形未擠、與真原文等寬)。 */
|
||||||
/* 字型設於容器即可——_lang.css 修正後不再直接強制 jz-inner 之字型,故消費端
|
/* 字型設於容器即可——聚珍不管字型(無 _lang.css)、亦不強制 jz-inner(`font:
|
||||||
字型經繼承正確套到標點字面(標點亦以 FZShuSong 渲染,halt 確實缺席)。 */
|
inherit`),故消費端字型經繼承正確套到標點字面(標點亦以 FZShuSong 渲染,halt
|
||||||
|
確實缺席)。此即「字型由消費端負責」之示例。 */
|
||||||
.cn { font-family: "方正书宋_GBK", "FZShuSong-Z01", serif; font-size: 46px; line-height: 1.5; }
|
.cn { font-family: "方正书宋_GBK", "FZShuSong-Z01", serif; font-size: 46px; line-height: 1.5; }
|
||||||
.w { font-weight: 400; opacity: .85; }
|
.w { font-weight: 400; opacity: .85; }
|
||||||
h1 { font-size: 1rem; }
|
h1 { font-size: 1rem; }
|
||||||
|
|||||||
+7
-1
@@ -6,13 +6,19 @@
|
|||||||
<title>聚珍(Juzhen)切片 1 — 目视验证</title>
|
<title>聚珍(Juzhen)切片 1 — 目视验证</title>
|
||||||
<!-- 明确载入 Noto 系列 webfont 作参考:擠壓依赖字型 OpenType halt,
|
<!-- 明确载入 Noto 系列 webfont 作参考:擠壓依赖字型 OpenType halt,
|
||||||
系统 fallback 字型(如 PingFang)可能无 halt,Safari 下尤其表现为开明式无效。
|
系统 fallback 字型(如 PingFang)可能无 halt,Safari 下尤其表现为开明式无效。
|
||||||
Noto Serif/Sans SC/TC 含 halt,确保跨浏览器一致参考。 -->
|
Noto Serif/Sans SC/TC 含 halt,确保跨浏览器一致参考。
|
||||||
|
注意:字型由**消费端**自行设定——聚珍不再内建 _lang.css 字体堆叠。下方 <style>
|
||||||
|
之 `.juzhen:lang(...)` 即推荐范式(逐 lang 设 font-family,须含 halt)。 -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC&family=Noto+Sans+TC&family=Noto+Serif+SC&family=Noto+Serif+TC&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC&family=Noto+Sans+TC&family=Noto+Serif+SC&family=Noto+Serif+TC&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="../dist/juzhen.css">
|
<link rel="stylesheet" href="../dist/juzhen.css">
|
||||||
<style>
|
<style>
|
||||||
/* demo 自身样式(非套件之一)。 */
|
/* demo 自身样式(非套件之一)。 */
|
||||||
|
/* 消费端字型设定(推荐范式):逐 lang 设 font-family,置于 .juzhen 或带 lang 之
|
||||||
|
元素;字型须含 OpenType halt(Noto CJK 具备),否则用 jiya.halfWidth:"margin"。 */
|
||||||
|
.juzhen:lang(zh-Hans), .juzhen [lang]:lang(zh-Hans) { font-family: "Noto Serif SC", "Noto Serif CJK SC", serif; }
|
||||||
|
.juzhen:lang(zh-Hant), .juzhen [lang]:lang(zh-Hant) { font-family: "Noto Serif TC", "Noto Serif CJK TC", serif; }
|
||||||
body { margin: 0; padding: 2rem; font-size: 18px; line-height: 2; background: #fafafa; color: #1a1a1a; }
|
body { margin: 0; padding: 2rem; font-size: 18px; line-height: 2; background: #fafafa; color: #1a1a1a; }
|
||||||
h1 { font-size: 1.4rem; }
|
h1 { font-size: 1.4rem; }
|
||||||
.toolbar { position: sticky; top: 0; background: #fff; border: 1px solid #ddd; padding: .75rem 1rem; margin-bottom: 1.5rem; display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; z-index: 10; }
|
.toolbar { position: sticky; top: 0; background: #fff; border: 1px solid #ddd; padding: .75rem 1rem; margin-bottom: 1.5rem; display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; z-index: 10; }
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
<link rel="stylesheet" href="../dist/juzhen.css">
|
<link rel="stylesheet" href="../dist/juzhen.css">
|
||||||
<style>
|
<style>
|
||||||
body { font: 16px/1.9 serif; max-width: 60em; margin: 2rem auto; padding: 0 1rem; color: #1a1a1a; }
|
body { font: 16px/1.9 serif; max-width: 60em; margin: 2rem auto; padding: 0 1rem; color: #1a1a1a; }
|
||||||
|
/* 消費端字型(推薦範式:逐 lang 設,須含 halt)——聚珍不再內建字體堆疊。 */
|
||||||
|
.juzhen:lang(zh-Hant), .juzhen [lang]:lang(zh-Hant) { font-family: "Noto Serif TC", "Noto Serif CJK TC", "Source Han Serif TC", serif; }
|
||||||
|
.juzhen:lang(zh-Hans), .juzhen [lang]:lang(zh-Hans) { font-family: "Noto Serif SC", "Noto Serif CJK SC", "Source Han Serif SC", serif; }
|
||||||
h1 { font-size: 1.4rem; }
|
h1 { font-size: 1.4rem; }
|
||||||
h2 { font-size: 1.05rem; margin: 1.6rem 0 .4rem; color: #036; }
|
h2 { font-size: 1.05rem; margin: 1.6rem 0 .4rem; color: #036; }
|
||||||
.hint { color: #666; font-size: .85rem; margin: .2rem 0 .6rem; }
|
.hint { color: #666; font-size: .85rem; margin: .2rem 0 .6rem; }
|
||||||
|
|||||||
Vendored
+4
-37
@@ -20,39 +20,6 @@ jz-jinze {
|
|||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* src/css/_lang.css */
|
|
||||||
:where(.juzhen:lang(zh-Hans)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-Hans)) {
|
|
||||||
font-family:
|
|
||||||
"Noto Serif SC",
|
|
||||||
"Noto Serif CJK SC",
|
|
||||||
"Source Han Serif SC",
|
|
||||||
serif;
|
|
||||||
}
|
|
||||||
:where(.juzhen:lang(zh-Hant)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-Hant)) {
|
|
||||||
font-family:
|
|
||||||
"Noto Serif TC",
|
|
||||||
"Noto Serif CJK TC",
|
|
||||||
"Source Han Serif TC",
|
|
||||||
serif;
|
|
||||||
}
|
|
||||||
:where(.juzhen:lang(zh-HK)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-HK)) {
|
|
||||||
font-family:
|
|
||||||
"Noto Serif HK",
|
|
||||||
"Noto Serif CJK HK",
|
|
||||||
"Noto Serif TC",
|
|
||||||
serif;
|
|
||||||
}
|
|
||||||
:where(.juzhen:lang(ja)),
|
|
||||||
:where(.juzhen [lang]:lang(ja)) {
|
|
||||||
font-family:
|
|
||||||
"Noto Serif JP",
|
|
||||||
"Noto Serif CJK JP",
|
|
||||||
serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* src/css/_spacing.css */
|
/* src/css/_spacing.css */
|
||||||
jz-hws {
|
jz-hws {
|
||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
@@ -74,8 +41,8 @@ jz-inner {
|
|||||||
}
|
}
|
||||||
jz-char.jz-half jz-inner,
|
jz-char.jz-half jz-inner,
|
||||||
jz-char.jz-half-le jz-inner {
|
jz-char.jz-half-le jz-inner {
|
||||||
font-feature-settings: "halt" 1;
|
font-feature-settings: "locl" 1, "halt" 1;
|
||||||
-webkit-font-feature-settings: "halt" 1;
|
-webkit-font-feature-settings: "locl" 1, "halt" 1;
|
||||||
}
|
}
|
||||||
[data-jz-halfwidth=margin] jz-char.jz-half jz-inner,
|
[data-jz-halfwidth=margin] jz-char.jz-half jz-inner,
|
||||||
[data-jz-halfwidth=margin] jz-char.jz-half-le jz-inner {
|
[data-jz-halfwidth=margin] jz-char.jz-half-le jz-inner {
|
||||||
@@ -110,8 +77,8 @@ jz-char.jz-half-le jz-inner {
|
|||||||
}
|
}
|
||||||
[data-jz-halfwidth=halt] jz-char.jz-half jz-inner,
|
[data-jz-halfwidth=halt] jz-char.jz-half jz-inner,
|
||||||
[data-jz-halfwidth=halt] jz-char.jz-half-le jz-inner {
|
[data-jz-halfwidth=halt] jz-char.jz-half-le jz-inner {
|
||||||
font-feature-settings: "halt" 1;
|
font-feature-settings: "locl" 1, "halt" 1;
|
||||||
-webkit-font-feature-settings: "halt" 1;
|
-webkit-font-feature-settings: "locl" 1, "halt" 1;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
[data-jz-halfwidth=halt] jz-char.jz-half,
|
[data-jz-halfwidth=halt] jz-char.jz-half,
|
||||||
|
|||||||
+9
-5
@@ -32,12 +32,16 @@ jz-inner
|
|||||||
具備);缺 halt 之字型則維持全形(優雅降級,不重疊)。三機制(baseline 政策
|
具備);缺 halt 之字型則維持全形(優雅降級,不重疊)。三機制(baseline 政策
|
||||||
C/行內鄰接 A/行端 B)皆以「加半形 class」落地,並集疊加、不重壓。
|
C/行內鄰接 A/行端 B)皆以「加半形 class」落地,並集疊加、不重壓。
|
||||||
jz-half 來自 baseline+鄰接;jz-half-le 來自行端 layout pass(分用不同 class
|
jz-half 來自 baseline+鄰接;jz-half-le 來自行端 layout pass(分用不同 class
|
||||||
以便重算時僅清除行端結果,效果相同)。 */
|
以便重算時僅清除行端結果,效果相同)。
|
||||||
|
**顯式保留 locl**:`font-feature-settings` 為低階屬性,雖按規範不應關閉未列之預設
|
||||||
|
特性(locl 依 lang 選地域字形,泛 CJK 字型如思源/Noto CJK 賴之定位標點),但瀏覽器
|
||||||
|
實作有別;故同時列 `"locl" 1` 確保地域標點字形不因設 halt 而失(對無 locl 之字型亦
|
||||||
|
無害)。body 文本之 locl 不受聚珍影響(未設任何 feature),由消費端字型+正確 lang 決定。 */
|
||||||
jz-char.jz-half jz-inner,
|
jz-char.jz-half jz-inner,
|
||||||
jz-char.jz-half-le jz-inner
|
jz-char.jz-half-le jz-inner
|
||||||
{
|
{
|
||||||
font-feature-settings: "halt" 1;
|
font-feature-settings: "locl" 1, "halt" 1;
|
||||||
-webkit-font-feature-settings: "halt" 1;
|
-webkit-font-feature-settings: "locl" 1, "halt" 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* margin 後備模式(.feedback):消費端字型缺 halt 時,render() 於 root 設
|
/* margin 後備模式(.feedback):消費端字型缺 halt 時,render() 於 root 設
|
||||||
@@ -106,8 +110,8 @@ jz-char.jz-half-le jz-inner
|
|||||||
[data-jz-halfwidth="halt"] jz-char.jz-half jz-inner,
|
[data-jz-halfwidth="halt"] jz-char.jz-half jz-inner,
|
||||||
[data-jz-halfwidth="halt"] jz-char.jz-half-le jz-inner
|
[data-jz-halfwidth="halt"] jz-char.jz-half-le jz-inner
|
||||||
{
|
{
|
||||||
font-feature-settings: "halt" 1;
|
font-feature-settings: "locl" 1, "halt" 1;
|
||||||
-webkit-font-feature-settings: "halt" 1;
|
-webkit-font-feature-settings: "locl" 1, "halt" 1;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
/* 依 lang 之字體堆疊(§6.9)。**僅作預設後備**,消費端自訂字型恆優先。
|
|
||||||
兩項關鍵:
|
|
||||||
1. 整個選擇器包進 :where() → 零特異度,消費端任何 `.juzhen { font-family }`
|
|
||||||
(特異度 ≥ 0,1,0)即可覆寫。
|
|
||||||
2. 只命中**帶 `lang` 屬性之元素**(容器或內層區塊),**不**直接命中 jz-inner/
|
|
||||||
jz-char(它們無 lang 屬性,靠繼承取字型)——否則會在標點字面容器上強制 Noto,
|
|
||||||
蓋掉消費端字型(曾致 demo 失真:消費端設 FZShuSong 卻仍以 Noto 之 halt 擠壓)。
|
|
||||||
簡繁日各取對應 Noto CJK,使 locl 字形正確。名稱涵蓋 webfont(「Noto Serif SC」)
|
|
||||||
與本機(「Noto Serif CJK SC」「Source Han Serif SC」)。擠壓半形依字型 OpenType
|
|
||||||
`halt`:消費端若用缺 halt 之字型(如方正書宋 GBK),請改用 margin 後備模式
|
|
||||||
(見 README「halt/margin 後備」)。 */
|
|
||||||
|
|
||||||
:where(.juzhen:lang(zh-Hans)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-Hans))
|
|
||||||
{
|
|
||||||
font-family: "Noto Serif SC", "Noto Serif CJK SC", "Source Han Serif SC", serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(.juzhen:lang(zh-Hant)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-Hant))
|
|
||||||
{
|
|
||||||
font-family: "Noto Serif TC", "Noto Serif CJK TC", "Source Han Serif TC", serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(.juzhen:lang(zh-HK)),
|
|
||||||
:where(.juzhen [lang]:lang(zh-HK))
|
|
||||||
{
|
|
||||||
font-family: "Noto Serif HK", "Noto Serif CJK HK", "Noto Serif TC", serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(.juzhen:lang(ja)),
|
|
||||||
:where(.juzhen [lang]:lang(ja))
|
|
||||||
{
|
|
||||||
font-family: "Noto Serif JP", "Noto Serif CJK JP", serif;
|
|
||||||
}
|
|
||||||
+5
-3
@@ -1,9 +1,11 @@
|
|||||||
/* 聚珍(Juzhen)樣式入口。視覺尺寸一律在此(I2):JS 只注入 jz-* 結構,
|
/* 聚珍(Juzhen)樣式入口。視覺尺寸一律在此(I2):JS 只注入 jz-* 結構,
|
||||||
間隙寬度/擠壓量/原子化/字體堆疊皆由 CSS 給定。
|
間隙寬度/擠壓量/原子化皆由 CSS 給定。
|
||||||
切片 1:normalize(禁用層)+ lang(字體)+ spacing + jiya + jinze。 */
|
**字型不歸聚珍管**:逐語言 font-family 完全交由消費端 CSS(見 README「字型由消費端
|
||||||
|
負責」)。聚珍僅守三項非管理性本分:_normalize 之 `jz-* { font: inherit }` 使原子
|
||||||
|
繼承消費端字型、不強加;_jiya 之半形 feature 顯式保留 `locl`;render 不改寫 `lang`。
|
||||||
|
切片 1:normalize(禁用層)+ spacing + jiya + jinze。 */
|
||||||
|
|
||||||
@import "./_normalize.css";
|
@import "./_normalize.css";
|
||||||
@import "./_lang.css";
|
|
||||||
@import "./_spacing.css";
|
@import "./_spacing.css";
|
||||||
@import "./_jiya.css";
|
@import "./_jiya.css";
|
||||||
@import "./_jinze.css";
|
@import "./_jinze.css";
|
||||||
|
|||||||
@@ -497,3 +497,14 @@ test("CSS:jz-* 原子 text-decoration:inherit,補裝飾盒跳過原子致下
|
|||||||
const css = readFileSync(cssPath, "utf8");
|
const css = readFileSync(cssPath, "utf8");
|
||||||
assert.match(css, /text-decoration\s*:\s*inherit/, "構建 CSS 應含 text-decoration:inherit");
|
assert.match(css, /text-decoration\s*:\s*inherit/, "構建 CSS 應含 text-decoration:inherit");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("CSS:聚珍不內建 font-family(字型交消費端),半形顯式保留 locl(下游回饋)", () =>
|
||||||
|
{
|
||||||
|
// 字型屬消費端領域,聚珍不內建任何字型堆疊(移除 _lang.css);僅以 _normalize 之
|
||||||
|
// `font: inherit` 使原子繼承消費端字型、不強加,並於半形 feature 顯式併入 locl,
|
||||||
|
// 確保泛 CJK 字型之地域標點字形不因設 halt 而失。body locl 由消費端字型+lang 決定。
|
||||||
|
const cssPath = fileURLToPath(new URL("../dist/juzhen.css", import.meta.url));
|
||||||
|
const css = readFileSync(cssPath, "utf8");
|
||||||
|
assert.equal(/font-family/.test(css), false, "聚珍 CSS 不應內建任何 font-family");
|
||||||
|
assert.match(css, /font-feature-settings:\s*"locl"\s+1,\s*"halt"\s+1/, "半形 feature 應顯式保留 locl");
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user