甲ABC乙,丙。
正常ABC,文字。
import assert from "node:assert/strict";
import { test } from "node:test";
import { setupDom } from "./helpers.mjs";
import { createJuzhen } from "../dist/juzhen.mjs";
test("pill:塊本身與其後代塊的內部不進入 standalone pass", () =>
{
for (const html of [
' 甲ABC乙,丙。 正常ABC,文字。 甲ABC乙,丙。 正常ABC,文字。
' + protectedHtml + ',正常文字。
' : '正常文字(' + protectedHtml + '
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const protectedEl = document.querySelector("span"); const jz = createJuzhen({ spacing: false, orphan: false, longWord: false, isSkipped: skippedText }); try { jz.render(document.body); assert.equal(protectedEl.closest("jz-jinze"), null, label + "/" + side); assert.equal(protectedEl.innerHTML, "自管"); jz.revert(document.body); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } } } }); test("jinze:透明元素內的排除內容不可被整元素退化綁定帶入", () => { const html = '甲自管乙,正常。
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const protectedEl = document.querySelector("[data-jz-skip]"); const jz = createJuzhen({ spacing: false, orphan: false, longWord: false }); try { jz.render(document.body); assert.equal(protectedEl.closest("jz-jinze"), null); jz.revert(document.body); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } }); test("jinze:註解與空 Text 不阻斷禁則,回退保留註解身份和次序", () => { const html = '甲,乙。
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const p = document.querySelector("p"); const anchor = p.childNodes[1]; const empty = document.createTextNode(""); p.insertBefore(empty, anchor); const jz = createJuzhen({ spacing: false, orphan: false, longWord: false }); try { jz.render(p); const group = p.querySelector("jz-jinze"); assert.equal(group.textContent, "甲,"); assert.ok(group.contains(anchor)); assert.ok(group.contains(empty)); jz.revert(p); assert.equal(p.childNodes[1], anchor); assert.equal(anchor.previousSibling.textContent, "甲"); assert.equal(anchor.nextSibling.textContent, ",乙。"); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } }); test("jinze:行內 render 根不把外部兄弟搬入生成群組", () => { const html = '甲,乙。後文
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const root = document.getElementById("root"); const parent = root.parentNode; const before = root.previousSibling; const after = root.nextSibling; const jz = createJuzhen({ spacing: false, orphan: false, longWord: false }); try { jz.render(root); assert.equal(root.parentNode, parent); assert.equal(root.previousSibling, before); assert.equal(root.nextSibling, after); assert.equal(parent.querySelectorAll(":scope > jz-jinze").length, 0); jz.revert(root); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } }); test("orphan:排除/text/off 的尾部內容不計數,也不包裹", () => { for (const [ label, attr ] of exclusions) { const html = '正常文字自管文字
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const jz = createJuzhen({ spacing: false, jiya: false, jinze: false, longWord: false, isSkipped: skippedText }); try { jz.render(document.body); assert.equal(document.querySelector("jz-orphan"), null, label + " 尾部是綁定邊界"); jz.revert(document.body); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } } }); test("orphan:只綁最後排除邊界之後的合資格末尾", () => { for (const [ label, attr ] of exclusions) { for (const tail of [ "末", "最後" ]) { const html = '前文自管文字' + tail + '
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const jz = createJuzhen({ spacing: false, jiya: false, jinze: false, longWord: false, isSkipped: skippedText }); try { jz.render(document.body); const orphan = document.querySelector("jz-orphan"); assert.equal(orphan?.textContent ?? null, tail === "末" ? null : tail, label + "/" + tail); assert.equal(document.querySelector("span").closest("jz-orphan"), null); jz.revert(document.body); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } } } }); test("orphan:不可切容器不以整綁繞過排除邊界,可切容器只切合資格末尾", () => { for (const tag of [ 'span', 'a href="#"' ]) { const closeTag = tag.split(" ")[0]; const html = '前文<' + tag + '>自管最後' + closeTag + '>
'; const { dom, document } = setupDom(html); const original = document.body.innerHTML; const protectedEl = document.querySelector("[data-jz-skip]"); const jz = createJuzhen({ spacing: false, jiya: false, jinze: false, longWord: false }); try { jz.render(document.body); assert.equal(protectedEl.closest("jz-orphan"), null); assert.equal(document.querySelector("jz-orphan")?.textContent ?? null, closeTag === "span" ? "最後" : null); jz.revert(document.body); assert.equal(document.body.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } } }); test("jinze:完整跨節點 base/VS/surrogate 原子一起綁到閉標點", () => { for (const parts of [ [ "𠀀", "\u{E0100}" ], [ "\uD840", "\uDC00", "\uDB40", "\uDD00" ] ]) { const { dom, document } = setupDom(""); const p = document.querySelector("p"); p.append("前文"); const authors = parts.map((part) => { const span = document.createElement("span"); span.textContent = part; p.appendChild(span); return span; }); p.append(","); const original = p.innerHTML; const jz = createJuzhen({ spacing: false, orphan: false, longWord: false }); try { jz.render(p); assert.equal(p.querySelector("jz-jinze").textContent, "𠀀\u{E0100},"); const rendered = p.innerHTML; jz.render(p); assert.equal(p.innerHTML, rendered); jz.revert(p); assert.equal(p.innerHTML, original); assert.deepEqual(Array.from(p.querySelectorAll("span")), authors); } finally { jz.disconnect(); dom.window.close(); } } }); test("orphan:split surrogate 的補充平面字計為一個實義字", () => { const { dom, document } = setupDom('前文\uD840\uDC00末
'); const p = document.querySelector("p"); const original = p.innerHTML; const jz = createJuzhen({ spacing: false, jiya: false, jinze: false, longWord: false }); try { jz.render(p); assert.equal(p.querySelector("jz-orphan").textContent, "𠀀末"); jz.revert(p); assert.equal(p.innerHTML, original); } finally { jz.disconnect(); dom.window.close(); } });