aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/SummaryView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/SummaryView.tsx')
-rw-r--r--src/client/views/nodes/formattedText/SummaryView.tsx51
1 files changed, 25 insertions, 26 deletions
diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx
index 238267f6e..eeb604b57 100644
--- a/src/client/views/nodes/formattedText/SummaryView.tsx
+++ b/src/client/views/nodes/formattedText/SummaryView.tsx
@@ -1,12 +1,11 @@
import { TextSelection } from 'prosemirror-state';
-import { Fragment, Node, Slice } from 'prosemirror-model';
+import { Attrs, Fragment, Node, Slice } from 'prosemirror-model';
import * as ReactDOM from 'react-dom/client';
import * as React from 'react';
+import { EditorView } from 'prosemirror-view';
-interface ISummaryView {}
// currently nothing needs to be rendered for the internal view of a summary.
-// eslint-disable-next-line react/prefer-stateless-function
-export class SummaryViewInternal extends React.Component<ISummaryView> {
+export class SummaryViewInternal extends React.Component<object> {
render() {
return null;
}
@@ -18,30 +17,30 @@ export class SummaryViewInternal extends React.Component<ISummaryView> {
// method instead of changing prosemirror's text when the expand/elide buttons are clicked.
export class SummaryView {
dom: HTMLSpanElement; // container for label and value
- root: any;
+ root: ReactDOM.Root;
- constructor(node: any, view: any, getPos: any) {
+ constructor(node: Node, view: EditorView, getPos: () => number | undefined) {
this.dom = document.createElement('span');
this.dom.className = this.className(node.attrs.visibility);
- this.dom.onpointerdown = (e: any) => {
+ this.dom.onpointerdown = (e: PointerEvent) => {
this.onPointerDown(e, node, view, getPos);
};
- this.dom.onkeypress = function (e: any) {
+ this.dom.onkeypress = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onkeydown = function (e: any) {
+ this.dom.onkeydown = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onkeyup = function (e: any) {
+ this.dom.onkeyup = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onmousedown = function (e: any) {
+ this.dom.onmousedown = function (e: MouseEvent) {
e.stopPropagation();
};
const js = node.toJSON;
- node.toJSON = function (...args: any[]) {
- return js.apply(this, args);
+ node.toJSON = function (...args: unknown[]) {
+ return js.apply(this, args as []);
};
this.root = ReactDOM.createRoot(this.dom);
@@ -54,18 +53,21 @@ export class SummaryView {
}
selectNode() {}
- updateSummarizedText(start: any, view: any) {
+ updateSummarizedText(start: number, view: EditorView) {
const mtype = view.state.schema.marks.summarize;
const mtypeInc = view.state.schema.marks.summarizeInclusive;
let endPos = start;
const visited = new Set();
- for (let i: number = start + 1; i < view.state.doc.nodeSize - 1; i++) {
+ const summarized = new Set();
+ const isSummary = (node: Node) => summarized.has(node) || node.marks.find(m => m.type === mtype || m.type === mtypeInc);
+ for (let i = start + 1; i < view.state.doc.nodeSize - 1; i++) {
let skip = false;
// eslint-disable-next-line no-loop-func
view.state.doc.nodesBetween(start, i, (node: Node /* , pos: number, parent: Node, index: number */) => {
+ isSummary(node) && Array.from(node.children).forEach(child => summarized.add(child));
if (node.isLeaf && !visited.has(node) && !skip) {
- if (node.marks.find((m: any) => m.type === mtype || m.type === mtypeInc)) {
+ if (summarized.has(node) || isSummary(node)) {
visited.add(node);
endPos = i + node.nodeSize - 1;
} else skip = true;
@@ -75,21 +77,18 @@ export class SummaryView {
return TextSelection.create(view.state.doc, start, endPos);
}
- onPointerDown = (e: any, node: any, view: any, getPos: any) => {
+ onPointerDown = (e: PointerEvent, node: Node, view: EditorView, getPos: () => number | undefined) => {
const visible = !node.attrs.visibility;
- const attrs = { ...node.attrs, visibility: visible };
- let textSelection = TextSelection.create(view.state.doc, getPos() + 1);
- if (!visible) {
- // update summarized text and save in attrs
- textSelection = this.updateSummarizedText(getPos() + 1, view);
- attrs.text = textSelection.content();
- attrs.textslice = attrs.text.toJSON();
- }
+ const textSelection = visible //
+ ? TextSelection.create(view.state.doc, (getPos() ?? 0) + 1)
+ : this.updateSummarizedText((getPos() ?? 0) + 1, view); // update summarized text and save in attrs
+ const text = textSelection.content();
+ const attrs = { ...node.attrs, visibility: visible, ...(!visible ? { text, textslice: text.toJSON() } : {}) } as Attrs;
view.dispatch(
view.state.tr
.setSelection(textSelection) // select the current summarized text (or where it will be if its collapsed)
.replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : node.attrs.text) // collapse/expand it
- .setNodeMarkup(getPos(), undefined, attrs)
+ .setNodeMarkup(getPos() ?? 0, undefined, attrs)
); // update the attrs
e.preventDefault();
e.stopPropagation();