mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-24 04:00:59 +01:00
editor: improve headingUpdatePlugin performance
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import { Heading as TiptapHeading } from "@tiptap/extension-heading";
|
||||
import { Node } from "@tiptap/pm/model";
|
||||
import { Plugin, PluginKey, Selection, Transaction } from "@tiptap/pm/state";
|
||||
import { Callout } from "../callout/callout.js";
|
||||
import { changedDescendants } from "../../utils/prosemirror.js";
|
||||
|
||||
const COLLAPSIBLE_BLOCK_TYPES = [
|
||||
"paragraph",
|
||||
@@ -408,12 +409,10 @@ const headingUpdatePlugin = new Plugin({
|
||||
const newDoc = newState.doc;
|
||||
let modified = false;
|
||||
|
||||
newDoc.descendants((newNode, pos) => {
|
||||
if (pos >= oldDoc.content.size) return;
|
||||
function check(newNode: Node, pos: number, oldNode?: Node) {
|
||||
if (!oldNode) return;
|
||||
|
||||
const oldNode = oldDoc.nodeAt(pos);
|
||||
if (
|
||||
oldNode &&
|
||||
oldNode.type.name === "heading" &&
|
||||
oldNode.attrs.level !== newNode.attrs.level
|
||||
) {
|
||||
@@ -432,7 +431,9 @@ const headingUpdatePlugin = new Plugin({
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
changedDescendants(oldDoc, newDoc, 0, check);
|
||||
|
||||
return modified ? tr : null;
|
||||
}
|
||||
|
||||
@@ -8,44 +8,13 @@ import { EditorState, PluginKey, Transaction } from "prosemirror-state";
|
||||
import { tableNodeTypes, TableRole } from "./schema.js";
|
||||
import { TableMap } from "./tablemap.js";
|
||||
import { CellAttrs, removeColSpan } from "./util.js";
|
||||
import { changedDescendants } from "../../../utils/prosemirror.js";
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const fixTablesKey = new PluginKey<{ fixTables: boolean }>("fix-tables");
|
||||
|
||||
/**
|
||||
* Helper for iterating through the nodes in a document that changed
|
||||
* compared to the given previous document. Useful for avoiding
|
||||
* duplicate work on each transaction.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
function changedDescendants(
|
||||
old: Node,
|
||||
cur: Node,
|
||||
offset: number,
|
||||
f: (node: Node, pos: number) => void
|
||||
): void {
|
||||
const oldSize = old.childCount,
|
||||
curSize = cur.childCount;
|
||||
outer: for (let i = 0, j = 0; i < curSize; i++) {
|
||||
const child = cur.child(i);
|
||||
for (let scan = j, e = Math.min(oldSize, i + 3); scan < e; scan++) {
|
||||
if (old.child(scan) == child) {
|
||||
j = scan + 1;
|
||||
offset += child.nodeSize;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
f(child, offset);
|
||||
if (j < oldSize && old.child(j).sameMarkup(child))
|
||||
changedDescendants(old.child(j), child, offset + 1, f);
|
||||
else child.nodesBetween(0, child.content.size, f, offset + 1);
|
||||
offset += child.nodeSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspect all tables in the given state's document and return a
|
||||
* transaction that fixes them, if necessary. If `oldState` was
|
||||
|
||||
@@ -34,7 +34,8 @@ import {
|
||||
Slice,
|
||||
DOMParser,
|
||||
Schema,
|
||||
Fragment
|
||||
Fragment,
|
||||
Node
|
||||
} from "prosemirror-model";
|
||||
import { EditorState, Selection, Transaction } from "prosemirror-state";
|
||||
import TextStyle from "@tiptap/extension-text-style";
|
||||
@@ -410,3 +411,42 @@ export function ensureLeadingParagraph(node: Node, schema: Schema): Fragment {
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for iterating through the nodes in a document that changed
|
||||
* compared to the given previous document. Useful for avoiding
|
||||
* duplicate work on each transaction.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function changedDescendants(
|
||||
old: Node,
|
||||
cur: Node,
|
||||
offset: number,
|
||||
f: (newNode: Node, pos: number, oldNode?: Node) => void
|
||||
): void {
|
||||
const oldSize = old.childCount,
|
||||
curSize = cur.childCount;
|
||||
outer: for (let i = 0, j = 0; i < curSize; i++) {
|
||||
const child = cur.child(i);
|
||||
for (let scan = j, e = Math.min(oldSize, i + 3); scan < e; scan++) {
|
||||
if (old.child(scan) == child) {
|
||||
j = scan + 1;
|
||||
offset += child.nodeSize;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
f(child, offset, i < oldSize ? old.child(i) : undefined);
|
||||
if (j < oldSize && old.child(j).sameMarkup(child)) {
|
||||
changedDescendants(old.child(j), child, offset + 1, f);
|
||||
} else {
|
||||
child.nodesBetween(
|
||||
0,
|
||||
child.content.size,
|
||||
f as (node: Node, pos: number) => void,
|
||||
offset + 1
|
||||
);
|
||||
}
|
||||
offset += child.nodeSize;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user