diff --git a/docs/changelog.html b/docs/changelog.html index 66e96e8..adbd6e4 100644 --- a/docs/changelog.html +++ b/docs/changelog.html @@ -1,4 +1,4 @@ - + @@ -432,6 +432,43 @@ body font-feature-settings: "kern", "liga"; } +/* Inline 色塊 (background-bearing inline boxes: code / kbd / mark / badge) + need EXTERNAL breathing room from the preceding text, distinct from juzhen's + text autospace (jz-hws, 0.25em). Without it the box's own padding is the only + visible space — which reads as space ON the block, not BETWEEN text and block, + so the box crowds the preceding glyph (worst at slide scale). A left margin + is the right tool: it sits OUTSIDE the background box. Only margin-left — the + trailing side stays governed by the juzhen pill (jz-hws before following + content, tight before CJK punctuation), so a box-then-、 still hugs. Scoped to + prose containers so `pre code` / diff / code blocks are unaffected. */ +/* NB: NO `:is()` here — Paged.js's CSS parser (academic mode) splits selector + lists on commas INSIDE `:is(...)`, yielding invalid fragments that abort + pagination. Selectors are spelled out instead. */ +code, kbd, mark, .badge +{ + margin-left: 0.25em; +} +/* Code blocks / diff columns are byte-aligned mono — no leading margin. */ +pre code, .diff-block code, .diff-block kbd +{ + margin-left: 0; +} +/* …and NOT when the box follows CJK punctuation: juzhen binds a box+trailing- + punctuation into a `jz-jinze`, so a box-group right after another jz-jinze + (which ends in that punctuation), or a box right after a punctuation jz-char, + is punctuation-preceded — there the box must hug it (else 「、 資訊」 floats). */ +jz-char + code, +jz-char + kbd, +jz-char + mark, +jz-char + .badge, +jz-jinze + jz-jinze > code:first-child, +jz-jinze + jz-jinze > kbd:first-child, +jz-jinze + jz-jinze > mark:first-child, +jz-jinze + jz-jinze > .badge:first-child +{ + margin-left: 0; +} + /* Mono opt-out: lock weight back to Regular (body inherits Medium 500), disable all CJK width-substitution / typography features so diff / code / table columns stay byte-aligned, and revert any inherited @@ -831,35 +868,41 @@ jz-jinze, jz-em { font: inherit; color: inherit; + text-indent: 0; + hanging-punctuation: none; +} +jz-char, +jz-jinze { + text-decoration: inherit; } /* src/css/_lang.css */ -:where(.juzhen):lang(zh-Hans), -:where(.juzhen) :lang(zh-Hans) { +: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(zh-Hant) { +: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(zh-HK) { +: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(ja) { +:where(.juzhen:lang(ja)), +:where(.juzhen [lang]:lang(ja)) { font-family: "Noto Serif JP", "Noto Serif CJK JP", @@ -882,11 +925,55 @@ jz-char { jz-inner { display: inline; } +[data-jz-atoms=inline] jz-char { + display: inline; +} jz-char.jz-half jz-inner, jz-char.jz-half-le jz-inner { font-feature-settings: "halt" 1; -webkit-font-feature-settings: "halt" 1; } +[data-jz-halfwidth=margin] jz-char.jz-half jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half-le jz-inner { + font-feature-settings: normal; + -webkit-font-feature-settings: normal; +} +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-left, +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-center, +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-right, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-left, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-center, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-right { + width: 0.5em; + overflow: visible; +} +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-left jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-center jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half.jz-ink-right jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-left jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-center jz-inner, +[data-jz-halfwidth=margin] jz-char.jz-half-le.jz-ink-right jz-inner { + display: inline-block; +} +[data-jz-halfwidth=margin] jz-char.jz-ink-center jz-inner { + margin-left: -0.25em; +} +[data-jz-halfwidth=margin] jz-char.jz-ink-right jz-inner { + margin-left: -0.5em; +} +[data-jz-halfwidth=margin] jz-char jz-inner { + text-decoration: inherit; +} +[data-jz-halfwidth=halt] jz-char.jz-half jz-inner, +[data-jz-halfwidth=halt] jz-char.jz-half-le jz-inner { + font-feature-settings: "halt" 1; + -webkit-font-feature-settings: "halt" 1; + margin-left: 0; +} +[data-jz-halfwidth=halt] jz-char.jz-half, +[data-jz-halfwidth=halt] jz-char.jz-half-le { + width: auto; +} /* src/css/_jinze.css */ jz-jinze { @@ -894,6 +981,9 @@ jz-jinze { white-space: nowrap; vertical-align: baseline; } +[data-jz-atoms=inline] jz-jinze { + display: inline; +} /* src/css/juzhen.css */ @@ -980,23 +1070,37 @@ kbd color: var(--fg); } -/* ---------- Opt-in line numbers (
) ----------
-   behavior.js rebuilds each line as N
-   …line…, injecting the number as LITERAL TEXT (not a CSS counter) so
-   it survives Paged.js pagination — counters reset inside flowed content.
-   Inert unless the author adds class="lineno"; copy keeps the raw code only. */
+/* ---------- Line blocks () ----------
+   behavior.js rebuilds each code line as a block …line…
+   (prepending N only for opt-in 
).
+   Block-per-line so a paginator (Paged.js) fragments BETWEEN lines — never mid-
+   text-node — preserving each line's leading indent across page breaks, and the
+   literal-text line number survives pagination (CSS counters reset in flowed
+   content). academic line-blocks every 
; other modes only `.lineno`.
+   `break-inside: avoid` keeps a soft-wrapped line whole on one page. */
 pre.lineno > code { display: block; }
-pre.lineno .cl
+.cl
 {
     display: block;
     white-space: pre-wrap;
     text-indent: 0;
+    break-inside: avoid;
 }
-pre.lineno .lno
+/* 帶行號者:懸掛縮進——首行以負 text-indent 把行號拉進左側 gutter,折行的續行則
+   對齊 padding-left(即行號欄之後),不再溢到行號左側。gutter 寬 = .lno 之
+   width+padding+border+margin 之和(約 3.6em)。 */
+pre.lineno .cl
+{
+    padding-left: 3.6em;
+    text-indent: -3.6em;
+}
+.lno
 {
     display: inline-block;
-    width: 2.5em;
-    margin-right: 1em;
+    width: 2.4em;
+    padding-right: 0.6em;
+    margin-right: 0.6em;
+    border-right: 1px solid var(--border);   /* 行號與內文之間的清晰界線(逐行 border 堆疊成連續豎線) */
     text-align: right;
     color: var(--muted);
     opacity: 0.7;
@@ -2438,6 +2542,22 @@ main > *:nth-child(n+6)            { animation-delay: 0.46s; }
 
 

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

+

下游回饋修復批次 2026-06-03

+

聚焦 Peek.nvim 等下游回饋之原子透明與中西間隙正確性,皆以真實 Chromium 量測驗證(jsdom 之 TreeWalker/offset 失真,不可信)。

+ +

修復

+
    +
  • 原子透明(段落繼承屬性漏溢)jz-* inline-block 原子對消費端段落樣式透明——歸零會被原子重複套用之 text-indenthanging-punctuation(過套用),並令原子 text-decoration: inherit 以接續段落下劃線(欠套用)。段落首行縮排正常、下劃線連續不斷,消費端無需配置。
  • +
  • 中西間隙 · gapTrim 自我應驗:行末去隙原依「後字是否在更低行」判定,而後字落點受間隙自身(及下游間隙)之 margin 推擠,致行中間隙被誤 trim——表現為容器寬相關之「最後一個間隙消失」、行內 code pill 跨行時右側間隙消失。改為「起始全部 trim、由左至右逐一定案」,量測不受任何 margin 污染。
  • +
  • 中西間隙 · 西文字集完整化:補入貨幣符號( 等 U+20A0–20BF)、拉丁擴充 A/B(拼音聲調 ā ǎ ē)、西里爾、數學運算符,並把希臘補全至含 α-ω。鄰接 CJK 之手工空格遂正規化、邊界補隙。列舉法以 \uXXXX 表示、無需 regex flag,相容 2016/Windows 10 時代瀏覽器。
  • +
  • 標點誤隙:全角省略號 …… 後接 CJK 不再誤補隙(DOTS_CJK 移除 |…);收尾彎引號 ” 後接拉丁/數字不再補隙(移除 pangu QUOTE_AN 偏例,與 」』)》】〕 等所有收尾標點一致)。全部常用中文標點 × 簡繁共 104 例稽核,CJK 間皆 0 誤隙。
  • +
+ +

工具

+
    +
  • demo/resize-check.html:可拖曳容器檢查頁——拖動方框寬度,驗證中西間隙在各寬度下恆穩、標點無誤隙;可切 justify 與「顯示間隙」描邊。
  • +
+

v2 切片 1 · 增補 2026-06

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

@@ -2520,6 +2640,19 @@ main > *:nth-child(n+6) { animation-delay: 0.46s; }