68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import { Plugin, PluginKey } from "prosemirror-state";
|
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
import Storage from "../../utils/Storage";
|
|
import { headingToPersistenceKey } from "../lib/headingToSlug";
|
|
import { findBlockNodes } from "../queries/findChildren";
|
|
import findCollapsedNodes from "../queries/findCollapsedNodes";
|
|
|
|
export class FoldingHeadersPlugin extends Plugin {
|
|
constructor(documentId: string | undefined) {
|
|
const plugin = new PluginKey("folding");
|
|
let loaded = false;
|
|
|
|
super({
|
|
key: plugin,
|
|
view: (view) => {
|
|
loaded = false;
|
|
view.dispatch(view.state.tr.setMeta("folding", { loaded: true }));
|
|
return {};
|
|
},
|
|
appendTransaction: (transactions, oldState, newState) => {
|
|
if (loaded) {
|
|
return;
|
|
}
|
|
if (
|
|
!transactions.some((transaction) => transaction.getMeta("folding"))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
let modified = false;
|
|
const tr = newState.tr;
|
|
const blocks = findBlockNodes(newState.doc);
|
|
|
|
for (const block of blocks) {
|
|
if (block.node.type.name === "heading") {
|
|
const persistKey = headingToPersistenceKey(block.node, documentId);
|
|
const persistedState = Storage.get(persistKey);
|
|
|
|
if (persistedState === "collapsed") {
|
|
tr.setNodeMarkup(block.pos, undefined, {
|
|
...block.node.attrs,
|
|
collapsed: true,
|
|
});
|
|
modified = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
loaded = true;
|
|
return modified ? tr : null;
|
|
},
|
|
props: {
|
|
decorations: (state) => {
|
|
const { doc } = state;
|
|
const decorations: Decoration[] = findCollapsedNodes(doc).map(
|
|
(block) =>
|
|
Decoration.node(block.pos, block.pos + block.node.nodeSize, {
|
|
class: "folded-content",
|
|
})
|
|
);
|
|
|
|
return DecorationSet.create(doc, decorations);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
}
|