mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-02 04:01:43 +02:00
editor: instrument block ids, table of contents and height map
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
AttributeUpdate,
|
||||
BatchAttributeStep
|
||||
} from "../../utils/batch-attribute-step.js";
|
||||
import { profiler } from "../../utils/profiler.js";
|
||||
|
||||
const NESTED_BLOCK_ID_TYPES = ["callout"];
|
||||
const BLOCK_ID_TYPES = [
|
||||
@@ -78,40 +79,49 @@ export const BlockId = Extension.create({
|
||||
const isDocChanged = transactions.some((tr) => tr.docChanged);
|
||||
if (!isDocChanged) return null;
|
||||
|
||||
const blockIds = new Set<string>();
|
||||
const updates: AttributeUpdate[] = [];
|
||||
const { tr } = newState;
|
||||
return profiler.time("blockId.appendTransaction", () => {
|
||||
const blockIds = new Set<string>();
|
||||
const updates: AttributeUpdate[] = [];
|
||||
const { tr } = newState;
|
||||
let scanned = 0;
|
||||
|
||||
tr.doc.forEach(function addBlockId(n, offset) {
|
||||
if (!n.isBlock || !BLOCK_ID_TYPES.includes(n.type.name)) return;
|
||||
tr.doc.forEach(function addBlockId(n, offset) {
|
||||
if (!n.isBlock || !BLOCK_ID_TYPES.includes(n.type.name)) return;
|
||||
|
||||
const currentId = n.attrs.blockId;
|
||||
const shouldUpdateId = !currentId || blockIds.has(currentId);
|
||||
const finalId = shouldUpdateId ? nanoid(8) : currentId;
|
||||
scanned++;
|
||||
const currentId = n.attrs.blockId;
|
||||
const shouldUpdateId = !currentId || blockIds.has(currentId);
|
||||
const finalId = shouldUpdateId ? nanoid(8) : currentId;
|
||||
|
||||
if (shouldUpdateId) {
|
||||
updates.push({
|
||||
pos: offset,
|
||||
attrName: "blockId",
|
||||
value: finalId
|
||||
});
|
||||
if (shouldUpdateId) {
|
||||
updates.push({
|
||||
pos: offset,
|
||||
attrName: "blockId",
|
||||
value: finalId
|
||||
});
|
||||
}
|
||||
|
||||
blockIds.add(finalId);
|
||||
|
||||
if (NESTED_BLOCK_ID_TYPES.includes(n.type.name))
|
||||
n.forEach((n, pos) => addBlockId(n, offset + pos + 1));
|
||||
});
|
||||
|
||||
profiler.count("blockId.blocksScanned", scanned);
|
||||
profiler.gauge("blockId.blocksPerScan", scanned);
|
||||
|
||||
if (updates.length > 0) {
|
||||
profiler.count("blockId.idsAssigned", updates.length);
|
||||
profiler.count("blockId.transactionsAppended");
|
||||
tr.step(new BatchAttributeStep(updates));
|
||||
tr.setMeta("ignoreEdit", true);
|
||||
// Transaction.addStep always clears storedMarks
|
||||
if (newState.storedMarks) tr.setStoredMarks(newState.storedMarks);
|
||||
return tr;
|
||||
}
|
||||
|
||||
blockIds.add(finalId);
|
||||
|
||||
if (NESTED_BLOCK_ID_TYPES.includes(n.type.name))
|
||||
n.forEach((n, pos) => addBlockId(n, offset + pos + 1));
|
||||
return null;
|
||||
});
|
||||
|
||||
if (updates.length > 0) {
|
||||
tr.step(new BatchAttributeStep(updates));
|
||||
tr.setMeta("ignoreEdit", true);
|
||||
// Transaction.addStep always clears storedMarks
|
||||
if (newState.storedMarks) tr.setStoredMarks(newState.storedMarks);
|
||||
return tr;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
})
|
||||
];
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Node as ProsemirrorNode } from "@tiptap/pm/model";
|
||||
import { profiler } from "../../utils/profiler.js";
|
||||
|
||||
const DEFAULT_ESTIMATES: Record<string, number> = {
|
||||
paragraph: 24,
|
||||
@@ -49,8 +50,10 @@ export class HeightMap {
|
||||
heightFor(node: ProsemirrorNode): number {
|
||||
const blockId = node.attrs.blockId as string | undefined;
|
||||
if (blockId && this.measured.has(blockId)) {
|
||||
profiler.count("virtualization.heightMap.hit");
|
||||
return this.measured.get(blockId) as number;
|
||||
}
|
||||
profiler.count("virtualization.heightMap.miss");
|
||||
return this.estimate(node);
|
||||
}
|
||||
|
||||
@@ -58,6 +61,7 @@ export class HeightMap {
|
||||
const blockId = node.attrs.blockId as string | undefined;
|
||||
if (!blockId || !Number.isFinite(height) || height <= 0) return;
|
||||
this.measured.set(blockId, Math.round(height));
|
||||
profiler.gauge("virtualization.heightMap.size", this.measured.size);
|
||||
}
|
||||
|
||||
toJSON(): Record<string, number> {
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Node as ProsemirrorNode } from "@tiptap/pm/model";
|
||||
import { profiler } from "./profiler.js";
|
||||
|
||||
export type TOCItem = {
|
||||
level: number;
|
||||
@@ -57,6 +58,7 @@ export function getTableOfContents(
|
||||
doc: ProsemirrorNode,
|
||||
content: HTMLElement
|
||||
): TOCItem[] {
|
||||
const end = profiler.start("toc.build");
|
||||
const tableOfContents: TOCItem[] = [];
|
||||
let level = -1;
|
||||
let prevHeading = 0;
|
||||
@@ -91,6 +93,9 @@ export function getTableOfContents(
|
||||
});
|
||||
});
|
||||
|
||||
end();
|
||||
profiler.count("toc.builds");
|
||||
profiler.gauge("toc.headings", tableOfContents.length);
|
||||
return tableOfContents;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user