fix(web): 修復排版邊界與增量生命週期

This commit is contained in:
2026-10-02 19:08:02 +08:00
parent 1c2fb0ed59
commit b1a16c4969
39 changed files with 4763 additions and 673 deletions
+79
View File
@@ -0,0 +1,79 @@
import assert from "node:assert/strict";
import { test } from "node:test";
import { setupDom } from "./helpers.mjs";
import { createJuzhen } from "../dist/juzhen.mjs";
const tick = () => new Promise((resolve) => setTimeout(resolve, 0));
for (const scenario of [ "move-added-block", "detached-target-record" ])
{
test("observer scope:" + scenario + " 不排版已移出觀察根的作者內容", async () =>
{
const { dom, document } = setupDom('<main id="root"></main><aside id="outside"></aside>');
const root = document.getElementById("root");
const outside = document.getElementById("outside");
const p = document.createElement("p");
p.innerHTML = "新增ABC,作者文字。";
const jz = createJuzhen();
try
{
if (scenario === "detached-target-record") { root.appendChild(p); }
jz.observe(root);
if (scenario === "move-added-block") { root.appendChild(p); }
outside.appendChild(p);
if (scenario === "detached-target-record") { p.setAttribute("lang", "zh-Hans"); }
const original = p.outerHTML;
await tick();
assert.equal(p.outerHTML, original, "已移出內容不能因尚未派發的記錄被新排版");
const active = document.createElement("p");
active.textContent = "根內ABC,仍處理。";
root.appendChild(active);
await tick();
assert.ok(active.querySelector("jz-char"), "觀察根內後續更新保持正常");
}
finally { jz.revert(root); jz.disconnect(); dom.window.close(); }
});
}
for (const change of [ "text", "attribute", "new-block" ])
{
test("observer detached root:" + change + " 在未掛入 document 的根仍增量更新", async () =>
{
const { dom, document } = setupDom();
const root = document.createElement("main");
root.innerHTML = '<p lang="zh-Hant">原文,甲乙。</p>';
const jz = createJuzhen();
try
{
jz.render(root);
jz.observe(root);
const p = root.querySelector("p");
if (change === "text") { p.textContent = "新文ABC,丙丁。"; }
else if (change === "attribute") { p.setAttribute("data-jz-level", "text"); }
else
{
const added = document.createElement("p");
added.textContent = "追加ABC,戊己。";
root.appendChild(added);
}
await tick();
assert.equal(root.isConnected, false);
if (change === "attribute")
{
assert.equal(p.getAttribute("data-jz-block-level"), "text");
assert.equal(p.querySelector("jz-orphan"), null);
}
else
{
const target = change === "new-block" ? root.lastElementChild : p;
assert.ok(target.querySelector("jz-hws"));
assert.ok(target.querySelector("jz-char"));
}
const currentText = root.textContent;
jz.revert(root);
assert.equal(root.querySelector("[data-jz]"), null);
assert.equal(root.textContent, currentText);
}
finally { jz.revert(root); jz.disconnect(); dom.window.close(); }
});
}