editor: render block ids on page elements so the viewport can track them

This commit is contained in:
Ammar Ahmed
2026-08-25 22:13:17 +05:00
parent 131583097c
commit af1687c366
2 changed files with 30 additions and 3 deletions

View File

@@ -116,6 +116,29 @@ describe("paged virtualization", () => {
editor.destroy();
});
test("a materialized page still carries its block id", async () => {
const editor = createEditor();
await created();
const first = editor.view.dom.children[0] as HTMLElement;
expect(first.hasAttribute("data-virtual-placeholder")).toBe(false);
// Without this the viewport window loses sight of a page the moment it
// renders, and it flips between rendered and blank on every frame.
expect(first.getAttribute("data-block-id")).toBe(
editor.state.doc.child(0).attrs.blockId
);
editor.destroy();
});
test("placeholder and rendered pages are tracked the same way", async () => {
const editor = createEditor();
await created();
for (const element of Array.from(editor.view.dom.children))
expect(element.getAttribute("data-block-id")).toBeTruthy();
editor.destroy();
});
test("the page holding the caret is never a placeholder", async () => {
const editor = createEditor();
await created();

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Node } from "@tiptap/core";
import { Node, mergeAttributes } from "@tiptap/core";
export const PAGE_NODE = "page";
@@ -33,7 +33,11 @@ export const Page = Node.create({
group: "page",
selectable: false,
renderHTML() {
return ["div", { "data-page": "true" }, 0];
// The block id must survive onto the element: the viewport plugin tracks
// pages by `data-block-id`, and a page that renders without one is invisible
// to it -- it materializes, disappears from the window, and dematerializes
// again on the next frame.
renderHTML({ HTMLAttributes }) {
return ["div", mergeAttributes(HTMLAttributes, { "data-page": "true" }), 0];
}
});