2d42c7ecf2
從零重寫之第一垂直切片(依 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% 等詞元不被禁則切斷。
81 lines
3.4 KiB
JavaScript
81 lines
3.4 KiB
JavaScript
// 針對性驗證:v1 之「行內塊(pill)邊界空格」與「原檔多餘空格收斂」是否
|
||
// 在新引擎落地(回應使用者提問)。
|
||
|
||
import assert from "node:assert/strict";
|
||
import { test } from "node:test";
|
||
|
||
import { setupDom, countTag } from "./helpers.mjs";
|
||
import { createJuzhen } from "../dist/juzhen.mjs";
|
||
|
||
const SPACING_ONLY = { jiya: false, longWord: false, jinze: false };
|
||
|
||
// ----- 原檔多餘空格收斂(STRIP_CJK_SPACE_ANS / STRIP_ANS_SPACE_CJK)-----
|
||
|
||
test("strip:CJK↔Latin 間之作者空格被移除(間隙改由 margin,複製緊湊)", () =>
|
||
{
|
||
const { document } = setupDom("<p>用 Neovim 寫</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
const p = document.querySelector("p");
|
||
assert.equal(p.textContent, "用Neovim寫", "作者空格移除,間隙改由 jz-hws margin(copy 緊湊)");
|
||
assert.equal(countTag(p, "jz-hws"), 2);
|
||
});
|
||
|
||
test("strip:間隙 copy-clean(無注入空白,textContent 不含中西間空白)", () =>
|
||
{
|
||
const { document } = setupDom("<p>裝 fzf 工具</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
const p = document.querySelector("p");
|
||
assert.equal(p.textContent, "裝fzf工具", "中西間隙不入 textContent(純 copy-clean)");
|
||
assert.equal(countTag(p, "jz-hws"), 2);
|
||
});
|
||
|
||
test("strip:全流程(含 charify)下作者空格仍收斂、不雙空格", () =>
|
||
{
|
||
const { document } = setupDom('<p lang="zh-Hans">用 TypeScript 寫,很好</p>');
|
||
createJuzhen({}).render(document.body);
|
||
const p = document.querySelector("p");
|
||
assert.ok(!/ {2,}/.test(p.textContent), "無雙空格:" + JSON.stringify(p.textContent));
|
||
});
|
||
|
||
// ----- 行內塊(pill)邊界空格(Pass B)-----
|
||
|
||
test("pill:code 與 CJK 緊鄰兩側各插一 jz-hws", () =>
|
||
{
|
||
const { document } = setupDom("<p>用<code>vim</code>編輯</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
assert.equal(countTag(document.querySelector("p"), "jz-hws"), 2);
|
||
});
|
||
|
||
test("pill:code 與 Latin 緊鄰亦插間隙(PILL_NEIGHBOR 含 A-Za-z0-9)", () =>
|
||
{
|
||
const { document } = setupDom("<p>看<code>x</code>嗎</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
assert.equal(countTag(document.querySelector("p"), "jz-hws"), 2);
|
||
});
|
||
|
||
test("pill:已有作者空格時收斂為單一 jz-hws(不雙空格)", () =>
|
||
{
|
||
const { document } = setupDom("<p>用 <code>vim</code> 編輯</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
const p = document.querySelector("p");
|
||
assert.ok(!/ {2,}/.test(p.textContent), "無雙空格:" + JSON.stringify(p.textContent));
|
||
assert.equal(countTag(p, "jz-hws"), 2);
|
||
});
|
||
|
||
test("pill:標點與 code 之間不強插間隙(鄰字非 PILL_NEIGHBOR)", () =>
|
||
{
|
||
const { document } = setupDom("<p>他說:<code>vim</code>很好</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
// : 非 PILL_NEIGHBOR → 左側不插;code|很 右側插 1。
|
||
assert.equal(countTag(document.querySelector("p"), "jz-hws"), 1);
|
||
});
|
||
|
||
// ----- 間隔號 ·(U+00B7)不觸發中西間隙 -----
|
||
|
||
test("間隔號:姓名 · 兩側不插 jz-hws(· 屬 CJK 標點,非西文)", () =>
|
||
{
|
||
const { document } = setupDom("<p>卡尔·马克思</p>");
|
||
createJuzhen(SPACING_ONLY).render(document.body);
|
||
assert.equal(countTag(document.querySelector("p"), "jz-hws"), 0, "· 兩側皆不應有間隙");
|
||
});
|