Files
cjk-autospace/demo/showcase.html
T
admin f3fe2399a7 demo: 功能分級+垂懸字效果演示(showcase 定寬對照 + resize-check)
新增 demo/showcase.html:定寬文本框並排對照,逐場景演示功能分級(標題標 data-jz-level=text
僅文本級)與垂懸字(關閉/開啟孤字對照、chars=3、標點不計入 N),工具列描出 jz-orphan/
中西間隙/半形標點;附「標點懸掛已停用」說明節。逐框 render(該框) 隔離屬性。
resize-check.html:增垂懸字(orphan)拖曳檢查+關閉對照。標點懸掛已停用,兩頁均不含懸掛。
2026-06-09 23:29:20 +08:00

149 lines
11 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>聚珍(Juzhen)— 新功能效果演示(定寬對照)</title>
<link rel="stylesheet" href="../dist/juzhen.css">
<style>
/* 全頁定寬定字以確保一致:Noto Sans CJK,20px/行高 2.2。各文本框寬度經 headless
校準,配此字型可穩定重現所述效果(換字型時斷行點略異,效果方向不變)。 */
html { font: 20px/2.2 "Noto Sans CJK SC", "Noto Sans SC", "Noto Sans CJK TC", "Noto Sans TC", sans-serif; }
body { max-width: 64em; margin: 2rem auto; padding: 0 1.2rem; color: #1a1a1a; }
.juzhen:lang(zh-Hant), .juzhen [lang]:lang(zh-Hant) { font-family: "Noto Sans CJK TC", "Noto Sans TC", sans-serif; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.15rem; margin: 2.2rem 0 .3rem; color: #036; border-bottom: 1px solid #e0e0e0; padding-bottom: .2rem; }
h3 { font-size: .98rem; margin: 1.2rem 0 .3rem; color: #225; }
p.lede, p.hint { color: #555; font-size: .82rem; line-height: 1.7; }
p.lede { font-size: .9rem; color: #333; }
.look { color: #a0522d; font-size: .8rem; margin: .2rem 0 .5rem; }
.look::before { content: "看點 "; font-weight: bold; }
.note { background: #fff8e6; border: 1px solid #e8d8a0; border-radius: 4px; padding: .5rem .8rem; font-size: .82rem; color: #6a5400; line-height: 1.7; }
code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .85em; background: rgba(0,0,0,.05); padding: 0 .25em; border-radius: 3px; }
.toolbar { position: sticky; top: 0; z-index: 9; background: #fff; border-bottom: 1px solid #ddd; padding: .5rem 0; margin-bottom: 1rem; font-size: .82rem; }
.toolbar label { margin-right: 1.2rem; cursor: pointer; white-space: nowrap; }
/* 對照網格:左右並排兩框。 */
.cmp { display: flex; flex-wrap: wrap; gap: 1.4rem; align-items: flex-start; margin: .4rem 0 .6rem; }
.cell { font-size: .8rem; color: #444; }
.cell .tag { display: inline-block; font-weight: bold; margin-bottom: .25rem; }
.tag.on { color: #1a7f37; } .tag.off { color: #b04; } .tag.warn { color: #a60; }
/* 定寬文本框(不可拖動,確保一致)。寬度由各框 inline style 給定。 */
.box { border: 1px solid #bbb; border-radius: 4px; padding: .45rem .6rem; background: #fafafa; }
.box p { margin: 0; text-align: justify; }
/* 顯示標記(可由工具列切換)。 */
body.show-orphan jz-orphan { outline: 1px dashed rgba(170,30,170,.7); background: rgba(170,30,170,.08); }
body.show-gaps jz-hws { background: rgba(220,30,30,.12); outline: 1px solid rgba(220,30,30,.4); }
body.show-half jz-char.jz-half jz-inner, body.show-half jz-char.jz-half-le jz-inner { background: rgba(30,90,220,.14); }
</style>
</head>
<body>
<h1>聚珍 — 新功能效果演示(定寬對照)</h1>
<p class="lede">本頁以<strong>定寬文本框</strong>(不可拖動)並排對照,逐場景展示兩項新功能:<strong>功能分級</strong>(文本級/段落級)、<strong>垂懸字避免</strong><code>orphan</code>)。各框寬度經 headless 校準,配 Noto Sans CJK 可穩定重現所述效果。勾選下方開關可描出聚珍注入之結構(紫=垂懸字綁定、紅=中西間隙、藍=半形標點)。第三項曾規劃之「標點懸掛」經實測停用,說明見文末。</p>
<div class="toolbar">
<label><input type="checkbox" id="t-orphan"> 顯示垂懸字綁定(紫 <code>jz-orphan</code></label>
<label><input type="checkbox" id="t-gaps"> 顯示中西間隙(紅 <code>jz-hws</code></label>
<label><input type="checkbox" id="t-half"> 顯示半形標點(藍)</label>
</div>
<!-- ===================== 一、功能分級 ===================== -->
<h2>一、功能分級:文本級 vs 段落級</h2>
<p class="hint">功能分兩級——<strong>文本級</strong>(中西間隙 <code>spacing</code>、標點擠壓 <code>jiya</code>)僅依字符鄰接,<strong>任意文本片段</strong>(標題、按鈕、單行)皆適用;<strong>段落級</strong>(禁則 <code>jinze</code>、垂懸字 <code>orphan</code>、長詞 <code>longWord</code>)依賴行/段布局。塊級元素預設全功能;標 <code>data-jz-level="text"</code> 之子樹(或選項 <code>level:{text:"選擇器"}</code>)僅跑文本級。</p>
<div>
<h3>標題標為文本級(仍有間隙與半形,但不參與禁則/垂懸字)</h3>
<div class="cmp">
<div class="cell"><span class="tag on">data-jz-level="text"(標題典型)</span>
<div class="box s-std" style="width:16em"><h3 data-jz-level="text" lang="zh-Hant" style="margin:0;font:inherit;color:inherit">用 Neovim 寫程式(v0.10)真的很順手。</h3></div>
<p class="look">中西間隙(<code>Neovim</code><code>v0.10</code> 兩側)與標點半形照常;但此子樹<strong></strong>跑垂懸字/禁則(無 <code>jz-orphan</code><code>jz-jinze</code>)。</p>
</div>
<div class="cell"><span class="tag off">預設段落級(同內容,作正文)</span>
<div class="box s-std" style="width:16em"><p lang="zh-Hant">用 Neovim 寫程式(v0.10)真的很順手。</p></div>
<p class="look">同樣有間隙與半形,但<strong>另含</strong>禁則綁定與垂懸字(開啟「顯示垂懸字綁定」可見紫框)。</p>
</div>
</div>
<p class="hint">即:把標題/按鈕標為文本級——要中西間隙與標點半形、不要避孤字/避頭尾(那些對單行無意義)。</p>
</div>
<!-- ===================== 二、垂懸字避免 ===================== -->
<h2>二、垂懸字避免(<code>orphan</code>,方案 C</h2>
<p class="hint">保證段末行 CJK <strong>實義字數 ≥ N</strong>(預設 2;標點/符號不計)。機制:把段末「第 N 個實義字起至段末」(含尾隨標點)包入 <code>jz-orphan</code><code>white-space:nowrap</code>)成不可斷整體 → 末行恒含之 ⇒ 末行實義字 ≥ N,<strong>無需量測版面</strong>、任意寬度成立。<strong>預設開</strong></p>
<div>
<h3>關閉 vs 開啟(同寬同文:末行從「孤字」變為保留兩字)</h3>
<div class="cmp">
<div class="cell"><span class="tag off">orphan 關閉(<code>data-juzhen-off="orphan"</code></span>
<div class="box s-std" style="width:14em"><p lang="zh-Hant" data-juzhen-off="orphan">春天來了萬物復甦大地生機盎然處處鳥語花香令人神往心曠神怡。</p></div>
<p class="look">末行僅剩孤字「<strong>怡。</strong>」——單字垂懸,版面失衡。</p>
</div>
<div class="cell"><span class="tag on">orphan 開啟(預設 chars=2</span>
<div class="box s-std" style="width:14em"><p lang="zh-Hant">春天來了萬物復甦大地生機盎然處處鳥語花香令人神往心曠神怡。</p></div>
<p class="look">末行保留「<strong>神怡。</strong>」兩個實義字(開「顯示垂懸字綁定」見紫框=被綁之尾段)。</p>
</div>
</div>
<h3>調整保留字數(<code>orphan:{ chars: 3 }</code></h3>
<div class="cmp">
<div class="cell"><span class="tag on">chars = 3(同前文、同寬 14em</span>
<div class="box s-chars3" style="width:14em"><p lang="zh-Hant">春天來了萬物復甦大地生機盎然處處鳥語花香令人神往心曠神怡。</p></div>
<p class="look">末行保留「<strong>曠神怡。</strong>」三個實義字(較預設 chars=2 之「神怡。」多拉一字下來)。</p>
</div>
</div>
<h3>標點/符號不計入字數(句末多個標點不佔 N)</h3>
<div class="cmp">
<div class="cell"><span class="tag off">orphan 關閉</span>
<div class="box s-std" style="width:14em"><p lang="zh-Hant" data-juzhen-off="orphan">他想了好久最後終於對著大家堅定地說出了那三個字「我願意」。</p></div>
<p class="look">末行=「<strong>意」。</strong>」——僅 <strong>1 個實義字</strong>(意),其後 <code>」。</code> 兩個標點<strong>不計入</strong>字數。</p>
</div>
<div class="cell"><span class="tag on">orphan 開啟(chars=2</span>
<div class="box s-std" style="width:14em"><p lang="zh-Hant">他想了好久最後終於對著大家堅定地說出了那三個字「我願意」。</p></div>
<p class="look">末行=「<strong>願意」。</strong>」——保 <strong>2 個實義字</strong>(願意);尾隨 <code>」。</code> 隨尾段綁入但不佔 N(開紫框見綁定範圍含標點,且整個 <code>「我願意」</code> 禁則群組跨 <code>jz-jinze</code> 不被切割)。</p>
</div>
</div>
<p class="hint">邊界:段落實義字 &lt; N(或單行段)→ 不綁、無副作用。極窄容器(&lt;N 字寬)→ 該尾段可能溢出(罕見)。</p>
</div>
<!-- ===================== 三、標點懸掛(已停用) ===================== -->
<h2>三、標點懸掛(<code>hanging</code>)— 已評估停用</h2>
<p class="note">原計劃之標點懸掛(行端標點凸出版心)經 headless + 真實瀏覽器實測<strong>確認不可行</strong>,已<strong>全面停用</strong><code>hanging</code> 選項仍被接受但無任何效果)。原因:純負 <code>margin</code> 機制下,句號墨色偏字框左下角,安全凸出量(&lt; 1em)只把空白半框推出版心、墨色仍在內(視覺不懸掛);凸出滿 1em 又釋放一整字寬、把下一字拉上本行致重疊;且 <code>ResizeObserver</code> 重排時標記錯亂。真正的解是原生 CSS <code>hanging-punctuation</code>,惟 Chrome 至今不支援、且與本庫 inline-block 對齊原子結構衝突。程式碼與 CSS 保留休眠,俟原生支援成熟再議。詳見 <code>ARCHITECTURE.md §6.5.6</code></p>
<footer style="margin-top:2.4rem;color:#888;font-size:.78rem;border-top:1px solid #eee;padding-top:.6rem">
聚珍(Juzhen)· 新功能效果演示。另見 <a href="./resize-check.html">resize-check.html</a>(可拖動容器之穩定性檢查)。寬度配 Noto Sans CJK 校準;換字型時斷行點略異,效果方向不變。
</footer>
<script src="../dist/juzhen.iife.js"></script>
<script>
// 各場景以獨立實例 **逐框 render(該框)** 渲染:屬性就近設於各框、由 CSS 後代選擇器
// 隔離(若 render(body) 則屬性落 body、跨框互相污染)。一致性:定寬 + 固定配置 + 同字型。
function renderEach(selector, opts)
{
var jz = Juzhen.createJuzhen(opts);
document.querySelectorAll(selector).forEach(function (el) { jz.render(el); });
}
// 功能分級+垂懸字(預設 orphan chars=2):繁全角/簡開明。
renderEach(".s-std", { lang: { policy: { "zh-Hant": "quanjiao", "zh-Hans": "kaiming" } } });
// 垂懸字 chars=3。
renderEach(".s-chars3", { lang: { default: "zh-Hant", style: "quanjiao" }, orphan: { chars: 3 } });
// 工具列開關。
var toggles = { "t-orphan": "show-orphan", "t-gaps": "show-gaps", "t-half": "show-half" };
Object.keys(toggles).forEach(function (id) {
var cb = document.getElementById(id);
if (cb.checked) { document.body.classList.add(toggles[id]); }
cb.addEventListener("change", function (e) {
document.body.classList.toggle(toggles[id], e.target.checked);
});
});
</script>
</body>
</html>