aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-04-24 18:12:30 -0400
committerbobzel <zzzman@gmail.com>2024-04-24 18:12:30 -0400
commitb1376d401e709515cee078cc08b05fd3fb89caeb (patch)
treed9ed253a539d506589a6c4251b9598dd5d0111f7 /src/client/views/nodes/formattedText
parentaa4f7b37483c516b92181d3374d3151972b98383 (diff)
completing eslint pass
Diffstat (limited to 'src/client/views/nodes/formattedText')
-rw-r--r--src/client/views/nodes/formattedText/DashDocCommentView.tsx159
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx123
-rw-r--r--src/client/views/nodes/formattedText/EquationEditor.tsx3
-rw-r--r--src/client/views/nodes/formattedText/EquationView.tsx93
-rw-r--r--src/client/views/nodes/formattedText/FootnoteView.tsx8
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx24
-rw-r--r--src/client/views/nodes/formattedText/OrderedListView.tsx9
-rw-r--r--src/client/views/nodes/formattedText/ParagraphNodeSpec.ts101
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts15
-rw-r--r--src/client/views/nodes/formattedText/SummaryView.tsx24
10 files changed, 282 insertions, 277 deletions
diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
index a72ed1813..3ec49fa27 100644
--- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
@@ -1,60 +1,11 @@
import { TextSelection } from 'prosemirror-state';
import * as ReactDOM from 'react-dom/client';
-import { Doc } from '../../../../fields/Doc';
-import { DocServer } from '../../../DocServer';
import * as React from 'react';
import { IReactionDisposer, computed, reaction } from 'mobx';
+import { Doc } from '../../../../fields/Doc';
+import { DocServer } from '../../../DocServer';
import { NumCast } from '../../../../fields/Types';
-// creates an inline comment in a note when '>>' is typed.
-// the comment sits on the right side of the note and vertically aligns with its anchor in the text.
-// the comment can be toggled on/off with the '<-' text anchor.
-export class DashDocCommentView {
- dom: HTMLDivElement; // container for label and value
- root: any;
- node: any;
-
- constructor(node: any, view: any, getPos: any) {
- this.node = node;
- this.dom = document.createElement('div');
- this.dom.style.width = node.attrs.width;
- this.dom.style.height = node.attrs.height;
- this.dom.style.fontWeight = 'bold';
- this.dom.style.position = 'relative';
- this.dom.style.display = 'inline-block';
- this.dom.onkeypress = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onkeydown = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onkeyup = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onmousedown = function (e: any) {
- e.stopPropagation();
- };
-
- this.root = ReactDOM.createRoot(this.dom);
- this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} setHeight={this.setHeight} docId={node.attrs.docId} />);
- (this as any).dom = this.dom;
- }
-
- setHeight = (hgt: number) => {
- !this.node.attrs.reflow && DocServer.GetRefField(this.node.attrs.docId).then(doc => doc instanceof Doc && (this.dom.style.height = hgt + ''));
- };
-
- destroy() {
- this.root.unmount();
- }
- deselectNode() {
- this.dom.classList.remove('ProseMirror-selectednode');
- }
- selectNode() {
- this.dom.classList.add('ProseMirror-selectednode');
- }
-}
-
interface IDashDocCommentViewInternal {
docId: string;
view: any;
@@ -65,9 +16,6 @@ interface IDashDocCommentViewInternal {
export class DashDocCommentViewInternal extends React.Component<IDashDocCommentViewInternal> {
_reactionDisposer: IReactionDisposer | undefined;
- @computed get _dashDoc() {
- return DocServer.GetRefField(this.props.docId);
- }
constructor(props: any) {
super(props);
this.onPointerLeaveCollapsed = this.onPointerLeaveCollapsed.bind(this);
@@ -77,58 +25,62 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
}
componentDidMount(): void {
this._reactionDisposer?.();
- this._dashDoc.then(
- doc =>
- doc instanceof Doc &&
- (this._reactionDisposer = reaction(
+ this._dashDoc.then(doc => {
+ if (doc instanceof Doc) {
+ this._reactionDisposer = reaction(
() => NumCast((doc as Doc)._height),
hgt => this.props.setHeight(hgt),
- {
- fireImmediately: true,
- }
- ))
- );
+ { fireImmediately: true }
+ );
+ }
+ });
}
componentWillUnmount(): void {
this._reactionDisposer?.();
}
- onPointerLeaveCollapsed(e: any) {
+ @computed get _dashDoc() {
+ return DocServer.GetRefField(this.props.docId);
+ }
+
+ onPointerLeaveCollapsed = (e: any) => {
this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight());
e.preventDefault();
e.stopPropagation();
- }
+ };
- onPointerEnterCollapsed(e: any) {
+ onPointerEnterCollapsed = (e: any) => {
this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false));
e.preventDefault();
e.stopPropagation();
- }
+ };
- onPointerUpCollapsed(e: any) {
+ onPointerUpCollapsed = (e: any) => {
const target = this.targetNode();
if (target) {
const expand = target.hidden;
- const tr = this.props.view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true });
+ const tr = this.props.view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: !target.node.attrs.hidden });
this.props.view.dispatch(tr.setSelection(TextSelection.create(tr.doc, this.props.getPos() + (expand ? 2 : 1)))); // update the attrs
setTimeout(() => {
expand && this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc));
try {
this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1))));
- } catch (e) {}
+ } catch (err) {
+ /* empty */
+ }
}, 0);
}
e.stopPropagation();
- }
+ };
- onPointerDownCollapsed(e: any) {
+ onPointerDownCollapsed = (e: any) => {
e.stopPropagation();
- }
+ };
targetNode = () => {
// search forward in the prosemirror doc for the attached dashDocNode that is the target of the comment anchor
- const state = this.props.view.state;
+ const { state } = this.props.view;
for (let i = this.props.getPos() + 1; i < state.doc.content.size; i++) {
const m = state.doc.nodeAt(i);
if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docId === this.props.docId) {
@@ -141,7 +93,9 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
setTimeout(() => {
try {
this.props.view.dispatch(state.tr.setSelection(TextSelection.create(state.tr.doc, this.props.getPos() + 2)));
- } catch (e) {}
+ } catch (err) {
+ /* empty */
+ }
}, 0);
return undefined;
};
@@ -154,7 +108,60 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
onPointerLeave={this.onPointerLeaveCollapsed}
onPointerEnter={this.onPointerEnterCollapsed}
onPointerUp={this.onPointerUpCollapsed}
- onPointerDown={this.onPointerDownCollapsed}></span>
+ onPointerDown={this.onPointerDownCollapsed}
+ />
);
}
}
+
+// creates an inline comment in a note when '>>' is typed.
+// the comment sits on the right side of the note and vertically aligns with its anchor in the text.
+// the comment can be toggled on/off with the '<-' text anchor.
+export class DashDocCommentView {
+ dom: HTMLDivElement; // container for label and value
+ root: any;
+ node: any;
+
+ constructor(node: any, view: any, getPos: any) {
+ this.node = node;
+ this.dom = document.createElement('div');
+ this.dom.style.width = node.attrs.width;
+ this.dom.style.height = node.attrs.height;
+ this.dom.style.fontWeight = 'bold';
+ this.dom.style.position = 'relative';
+ this.dom.style.display = 'inline-block';
+ this.dom.onkeypress = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onkeydown = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onkeyup = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onmousedown = function (e: any) {
+ e.stopPropagation();
+ };
+
+ this.root = ReactDOM.createRoot(this.dom);
+ this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} setHeight={this.setHeight} docId={node.attrs.docId} />);
+ (this as any).dom = this.dom;
+ }
+
+ setHeight = (hgt: number) => {
+ !this.node.attrs.reflow &&
+ DocServer.GetRefField(this.node.attrs.docId).then(doc => {
+ doc instanceof Doc && (this.dom.style.height = hgt + '');
+ });
+ };
+
+ destroy() {
+ this.root.unmount();
+ }
+ deselectNode() {
+ this.dom.classList.remove('ProseMirror-selectednode');
+ }
+ selectNode() {
+ this.dom.classList.add('ProseMirror-selectednode');
+ }
+}
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index dee7d70bb..f311b3cdd 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -1,10 +1,10 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { NodeSelection } from 'prosemirror-state';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
-import { Utils } from '../../../../Utils';
-import { returnFalse } from '../../../../ClientUtils';
+import { ClientUtils, returnFalse } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { Height, Width } from '../../../../fields/DocSymbols';
import { NumCast } from '../../../../fields/Types';
@@ -16,63 +16,7 @@ import { DocumentView } from '../DocumentView';
import { FocusViewOptions } from '../FieldView';
import { FormattedTextBox } from './FormattedTextBox';
-var horizPadding = 3; // horizontal padding to container to allow cursor to show up on either side.
-export class DashDocView {
- dom: HTMLSpanElement; // container for label and value
- root: any;
-
- constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
- this.dom = document.createElement('span');
- this.dom.style.position = 'relative';
- this.dom.style.textIndent = '0';
- this.dom.style.width = (+node.attrs.width.toString().replace('px', '') + horizPadding).toString();
- this.dom.style.height = node.attrs.height;
- this.dom.style.display = node.attrs.hidden ? 'none' : 'inline-block';
- (this.dom.style as any).float = node.attrs.float;
- this.dom.onkeypress = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onkeydown = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onkeyup = function (e: any) {
- e.stopPropagation();
- };
- this.dom.onmousedown = function (e: any) {
- e.stopPropagation();
- };
-
- this.root = ReactDOM.createRoot(this.dom);
- this.root.render(
- <DashDocViewInternal
- docId={node.attrs.docId}
- embedding={node.attrs.embedding}
- width={node.attrs.width}
- height={node.attrs.height}
- hidden={node.attrs.hidden}
- fieldKey={node.attrs.fieldKey}
- tbox={tbox}
- view={view}
- node={node}
- getPos={getPos}
- />
- );
- }
- destroy() {
- setTimeout(() => {
- try {
- this.root.unmount();
- } catch {}
- });
- }
- deselectNode() {
- this.dom.style.backgroundColor = '';
- }
- selectNode() {
- this.dom.style.backgroundColor = 'rgb(141, 182, 247)';
- }
-}
-
+const horizPadding = 3; // horizontal padding to container to allow cursor to show up on either side.
interface IDashDocViewInternal {
docId: string;
embedding: string;
@@ -85,6 +29,7 @@ interface IDashDocViewInternal {
node: any;
getPos: any;
}
+
@observer
export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewInternal> {
_spanRef = React.createRef<HTMLDivElement>();
@@ -158,7 +103,7 @@ export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewIn
getDocTransform = () => {
if (!this._spanRef.current) return Transform.Identity();
- const { scale, translateX, translateY } = Utils.GetScreenTransform(this._spanRef.current);
+ const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._spanRef.current);
return new Transform(-translateX, -translateY, 1).scale(1 / scale);
};
outerFocus = (target: Doc, options: FocusViewOptions) => this._textBox.focus(target, options); // ideally, this would scroll to show the focus target
@@ -227,3 +172,61 @@ export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewIn
);
}
}
+
+export class DashDocView {
+ dom: HTMLSpanElement; // container for label and value
+ root: any;
+
+ constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ this.dom = document.createElement('span');
+ this.dom.style.position = 'relative';
+ this.dom.style.textIndent = '0';
+ this.dom.style.width = (+node.attrs.width.toString().replace('px', '') + horizPadding).toString();
+ this.dom.style.height = node.attrs.height;
+ this.dom.style.display = node.attrs.hidden ? 'none' : 'inline-block';
+ (this.dom.style as any).float = node.attrs.float;
+ this.dom.onkeypress = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onkeydown = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onkeyup = function (e: any) {
+ e.stopPropagation();
+ };
+ this.dom.onmousedown = function (e: any) {
+ e.stopPropagation();
+ };
+
+ this.root = ReactDOM.createRoot(this.dom);
+ this.root.render(
+ <DashDocViewInternal
+ docId={node.attrs.docId}
+ embedding={node.attrs.embedding}
+ width={node.attrs.width}
+ height={node.attrs.height}
+ hidden={node.attrs.hidden}
+ fieldKey={node.attrs.fieldKey}
+ tbox={tbox}
+ view={view}
+ node={node}
+ getPos={getPos}
+ />
+ );
+ }
+ destroy() {
+ setTimeout(() => {
+ try {
+ this.root.unmount();
+ } catch {
+ /* empty */
+ }
+ });
+ }
+ deselectNode() {
+ this.dom.style.backgroundColor = '';
+ }
+ selectNode() {
+ this.dom.style.backgroundColor = 'rgb(141, 182, 247)';
+ }
+}
diff --git a/src/client/views/nodes/formattedText/EquationEditor.tsx b/src/client/views/nodes/formattedText/EquationEditor.tsx
index b4102e08e..d9b1a2cf8 100644
--- a/src/client/views/nodes/formattedText/EquationEditor.tsx
+++ b/src/client/views/nodes/formattedText/EquationEditor.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable react/require-default-props */
import React, { Component, createRef } from 'react';
// Import JQuery, required for the functioning of the equation editor
@@ -5,11 +6,9 @@ import $ from 'jquery';
import './EquationEditor.scss';
-// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
window.jQuery = $;
-// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
require('mathquill/build/mathquill');
diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx
index b90653acc..5167c8f2a 100644
--- a/src/client/views/nodes/formattedText/EquationView.tsx
+++ b/src/client/views/nodes/formattedText/EquationView.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { IReactionDisposer } from 'mobx';
import { observer } from 'mobx-react';
import { TextSelection } from 'prosemirror-state';
@@ -10,44 +11,6 @@ import EquationEditor from './EquationEditor';
import { FormattedTextBox } from './FormattedTextBox';
import { DocData } from '../../../../fields/DocSymbols';
-export class EquationView {
- dom: HTMLDivElement; // container for label and value
- root: any;
- tbox: FormattedTextBox;
- view: any;
- constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
- this.tbox = tbox;
- this.view = view;
- this.dom = document.createElement('div');
- this.dom.style.width = node.attrs.width;
- this.dom.style.height = node.attrs.height;
- this.dom.style.position = 'relative';
- this.dom.style.display = 'inline-block';
- this.dom.onmousedown = function (e: any) {
- e.stopPropagation();
- };
-
- this.root = ReactDOM.createRoot(this.dom);
- this.root.render(<EquationViewInternal fieldKey={node.attrs.fieldKey} width={node.attrs.width} height={node.attrs.height} getPos={getPos} setEditor={this.setEditor} tbox={tbox} />);
- }
- _editor: EquationEditor | undefined;
- setEditor = (editor?: EquationEditor) => (this._editor = editor);
- destroy() {
- this.root.unmount();
- }
- setSelection() {
- this._editor?.mathField.focus();
- }
- selectNode() {
- this.tbox._applyingChange = this.tbox.fieldKey; // setting focus will make prosemirror lose focus, which will cause it to change its selection to a text selection, which causes this view to get rebuilt but it's no longer node selected, so the equationview won't have focus
- setTimeout(() => {
- this._editor?.mathField.focus();
- setTimeout(() => (this.tbox._applyingChange = ''));
- });
- }
- deselectNode() {}
-}
-
interface IEquationViewInternal {
fieldKey: string;
tbox: FormattedTextBox;
@@ -70,12 +33,12 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
this._textBoxDoc = props.tbox.Document;
}
- componentWillUnmount() {
- this._reactionDisposer?.();
- }
componentDidMount() {
this.props.setEditor(this._ref.current ?? undefined);
}
+ componentWillUnmount() {
+ this._reactionDisposer?.();
+ }
render() {
return (
@@ -100,12 +63,56 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
<EquationEditor
ref={this._ref}
value={StrCast(this._textBoxDoc[DocData][this._fieldKey])}
- onChange={(str: any) => (this._textBoxDoc[DocData][this._fieldKey] = str)}
+ onChange={(str: any) => {
+ this._textBoxDoc[DocData][this._fieldKey] = str;
+ }}
autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
autoOperatorNames="sin cos tan"
- spaceBehavesLikeTab={true}
+ spaceBehavesLikeTab
/>
</div>
);
}
}
+
+export class EquationView {
+ dom: HTMLDivElement; // container for label and value
+ root: any;
+ tbox: FormattedTextBox;
+ view: any;
+ constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ this.tbox = tbox;
+ this.view = view;
+ this.dom = document.createElement('div');
+ this.dom.style.width = node.attrs.width;
+ this.dom.style.height = node.attrs.height;
+ this.dom.style.position = 'relative';
+ this.dom.style.display = 'inline-block';
+ this.dom.onmousedown = function (e: any) {
+ e.stopPropagation();
+ };
+
+ this.root = ReactDOM.createRoot(this.dom);
+ this.root.render(<EquationViewInternal fieldKey={node.attrs.fieldKey} width={node.attrs.width} height={node.attrs.height} getPos={getPos} setEditor={this.setEditor} tbox={tbox} />);
+ }
+ _editor: EquationEditor | undefined;
+ setEditor = (editor?: EquationEditor) => {
+ this._editor = editor;
+ };
+ destroy() {
+ this.root.unmount();
+ }
+ setSelection() {
+ this._editor?.mathField.focus();
+ }
+ selectNode() {
+ this.tbox._applyingChange = this.tbox.fieldKey; // setting focus will make prosemirror lose focus, which will cause it to change its selection to a text selection, which causes this view to get rebuilt but it's no longer node selected, so the equationview won't have focus
+ setTimeout(() => {
+ this._editor?.mathField.focus();
+ setTimeout(() => {
+ this.tbox._applyingChange = '';
+ });
+ });
+ }
+ deselectNode() {}
+}
diff --git a/src/client/views/nodes/formattedText/FootnoteView.tsx b/src/client/views/nodes/formattedText/FootnoteView.tsx
index b327e5137..4641da2e9 100644
--- a/src/client/views/nodes/formattedText/FootnoteView.tsx
+++ b/src/client/views/nodes/formattedText/FootnoteView.tsx
@@ -2,9 +2,9 @@ import { EditorView } from 'prosemirror-view';
import { EditorState } from 'prosemirror-state';
import { keymap } from 'prosemirror-keymap';
import { baseKeymap, toggleMark } from 'prosemirror-commands';
-import { schema } from './schema_rts';
import { redo, undo } from 'prosemirror-history';
import { StepMap } from 'prosemirror-transform';
+import { schema } from './schema_rts';
export class FootnoteView {
innerView: any;
@@ -100,8 +100,8 @@ export class FootnoteView {
this.innerView.updateState(state);
if (!tr.getMeta('fromOutside')) {
- const outerTr = this.outerView.state.tr,
- offsetMap = StepMap.offset(this.getPos() + 1);
+ const outerTr = this.outerView.state.tr;
+ const offsetMap = StepMap.offset(this.getPos() + 1);
for (const transaction of transactions) {
for (const step of transaction.steps) {
outerTr.step(step.map(offsetMap));
@@ -115,7 +115,7 @@ export class FootnoteView {
if (!node.sameMarkup(this.node)) return false;
this.node = node;
if (this.innerView) {
- const state = this.innerView.state;
+ const { state } = this.innerView;
const start = node.content.findDiffStart(state.doc.content);
if (start !== null) {
let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 52d93ec38..01c46edeb 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -19,20 +19,22 @@ export function findLinkMark(marks: readonly Mark[]): Mark | undefined {
return marks.find(m => m.type === schema.marks.autoLinkAnchor || m.type === schema.marks.linkAnchor);
}
export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: readonly Mark[]) => Mark | undefined) {
- let before = 0,
- nbef = rpos.nodeBefore;
+ let before = 0;
+ let nbef = rpos.nodeBefore;
while (nbef && finder(nbef.marks)) {
before += nbef.nodeSize;
+ // eslint-disable-next-line no-param-reassign
rpos = view.state.doc.resolve(rpos.pos - nbef.nodeSize);
rpos && (nbef = rpos.nodeBefore);
}
return before;
}
export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: readonly Mark[]) => Mark | undefined) {
- let after = 0,
- naft = rpos.nodeAfter;
+ let after = 0;
+ let naft = rpos.nodeAfter;
while (naft && finder(naft.marks)) {
after += naft.nodeSize;
+ // eslint-disable-next-line no-param-reassign
rpos = view.state.doc.resolve(rpos.pos + naft.nodeSize);
rpos && (naft = rpos.nodeAfter);
}
@@ -80,10 +82,10 @@ export class FormattedTextBoxComment {
}
static showCommentbox(view: EditorView, nbef: number) {
- const state = view.state;
+ const { state } = view;
// These are in screen coordinates
- const start = view.coordsAtPos(state.selection.from - nbef),
- end = view.coordsAtPos(state.selection.from - nbef);
+ const start = view.coordsAtPos(state.selection.from - nbef);
+ const end = view.coordsAtPos(state.selection.from - nbef);
// The box in which the tooltip is positioned, to use as base
const box = (document.getElementsByClassName('mainView-container') as any)[0].getBoundingClientRect();
// Find a center-ish x position from the selection endpoints (when crossing lines, end may be more to the left)
@@ -110,14 +112,16 @@ export class FormattedTextBoxComment {
}
static setupPreview(view: EditorView, textBox: FormattedTextBox, hrefs?: string[], linkDoc?: string, noPreview?: boolean) {
- const state = view.state;
+ const { state } = view;
// this section checks to see if the insertion point is over text entered by a different user. If so, it sets ths comment text to indicate the user and the modification date
if (state.selection.$from) {
const nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
const naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
const noselection = state.selection.$from === state.selection.$to;
let child: any = null;
- state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
+ state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any /* , pos: number, parent: any */) => {
+ !child && node.marks.length && (child = node);
+ });
const mark = child && findOtherUserMark(child.marks);
if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) {
FormattedTextBoxComment.saveMarkRegion(textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark);
@@ -132,7 +136,7 @@ export class FormattedTextBoxComment {
if (state.selection.$from && hrefs?.length) {
const nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef;
- //nbef &&
+ // nbef &&
naft &&
LinkInfo.SetLinkInfo({
DocumentView: textBox.DocumentView,
diff --git a/src/client/views/nodes/formattedText/OrderedListView.tsx b/src/client/views/nodes/formattedText/OrderedListView.tsx
index c3595e59b..dbc60f7bf 100644
--- a/src/client/views/nodes/formattedText/OrderedListView.tsx
+++ b/src/client/views/nodes/formattedText/OrderedListView.tsx
@@ -1,8 +1,7 @@
export class OrderedListView {
-
- update(node: any) {
- // if attr's of an ordered_list (e.g., bulletStyle) change,
+ update() {
+ // if attr's of an ordered_list (e.g., bulletStyle) change,
// return false forces the dom node to be recreated which is necessary for the bullet labels to update
- return false;
+ return false;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts b/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
index 30da91710..6c88a0d29 100644
--- a/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
+++ b/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
@@ -1,18 +1,19 @@
+/* eslint-disable import/extensions */
+import { Node, DOMOutputSpec } from 'prosemirror-model';
import clamp from '../../../util/clamp';
import convertToCSSPTValue from '../../../util/convertToCSSPTValue';
import toCSSLineSpacing from '../../../util/toCSSLineSpacing';
-import { Node, DOMOutputSpec } from 'prosemirror-model';
-//import type { NodeSpec } from './Types';
+// import type { NodeSpec } from './Types';
type NodeSpec = {
- attrs?: { [key: string]: any },
- content?: string,
- draggable?: boolean,
- group?: string,
- inline?: boolean,
- name?: string,
- parseDOM?: Array<any>,
- toDOM?: (node: any) => DOMOutputSpec,
+ attrs?: { [key: string]: any };
+ content?: string;
+ draggable?: boolean;
+ group?: string;
+ inline?: boolean;
+ name?: string;
+ parseDOM?: Array<any>;
+ toDOM?: (node: any) => DOMOutputSpec;
};
// This assumes that every 36pt maps to one indent level.
@@ -25,41 +26,18 @@ export const EMPTY_CSS_VALUE = new Set(['', '0%', '0pt', '0px']);
const ALIGN_PATTERN = /(left|right|center|justify)/;
-// https://github.com/ProseMirror/prosemirror-schema-basic/blob/master/src/schema-basic.js
-// :: NodeSpec A plain paragraph textblock. Represented in the DOM
-// as a `<p>` element.
-export const ParagraphNodeSpec: NodeSpec = {
- attrs: {
- align: { default: null },
- color: { default: null },
- id: { default: null },
- indent: { default: null },
- inset: { default: null },
- lineSpacing: { default: null },
- // TODO: Add UI to let user edit / clear padding.
- paddingBottom: { default: null },
- // TODO: Add UI to let user edit / clear padding.
- paddingTop: { default: null },
- },
- content: 'inline*',
- group: 'block',
- parseDOM: [{ tag: 'p', getAttrs }],
- toDOM,
-};
+function convertMarginLeftToIndentValue(marginLeft: string): number {
+ const ptValue = convertToCSSPTValue(marginLeft);
+ return clamp(MIN_INDENT_LEVEL, Math.floor(ptValue / INDENT_MARGIN_PT_SIZE), MAX_INDENT_LEVEL);
+}
function getAttrs(dom: HTMLElement): Object {
- const {
- lineHeight,
- textAlign,
- marginLeft,
- paddingTop,
- paddingBottom,
- } = dom.style;
+ const { lineHeight, textAlign, marginLeft, paddingTop, paddingBottom } = dom.style;
let align = dom.getAttribute('align') || textAlign || '';
- align = ALIGN_PATTERN.test(align) ? align : "";
+ align = ALIGN_PATTERN.test(align) ? align : '';
- let indent = parseInt(dom.getAttribute(ATTRIBUTE_INDENT) || "", 10);
+ let indent = parseInt(dom.getAttribute(ATTRIBUTE_INDENT) || '', 10);
if (!indent && marginLeft) {
indent = convertMarginLeftToIndentValue(marginLeft);
@@ -74,15 +52,7 @@ function getAttrs(dom: HTMLElement): Object {
}
function toDOM(node: Node): DOMOutputSpec {
- const {
- align,
- indent,
- inset,
- lineSpacing,
- paddingTop,
- paddingBottom,
- id,
- } = node.attrs;
+ const { align, indent, inset, lineSpacing, paddingTop, paddingBottom, id } = node.attrs;
const attrs: { [key: string]: any } | null = {};
let style = '';
@@ -128,16 +98,29 @@ function toDOM(node: Node): DOMOutputSpec {
return ['p', attrs, 0];
}
+// https://github.com/ProseMirror/prosemirror-schema-basic/blob/master/src/schema-basic.js
+// :: NodeSpec A plain paragraph textblock. Represented in the DOM
+// as a `<p>` element.
+export const ParagraphNodeSpec: NodeSpec = {
+ attrs: {
+ align: { default: null },
+ color: { default: null },
+ id: { default: null },
+ indent: { default: null },
+ inset: { default: null },
+ lineSpacing: { default: null },
+ // TODO: Add UI to let user edit / clear padding.
+ paddingBottom: { default: null },
+ // TODO: Add UI to let user edit / clear padding.
+ paddingTop: { default: null },
+ },
+ content: 'inline*',
+ group: 'block',
+ parseDOM: [{ tag: 'p', getAttrs }],
+ toDOM,
+};
+
export const toParagraphDOM = toDOM;
export const getParagraphNodeAttrs = getAttrs;
-export function convertMarginLeftToIndentValue(marginLeft: string): number {
- const ptValue = convertToCSSPTValue(marginLeft);
- return clamp(
- MIN_INDENT_LEVEL,
- Math.floor(ptValue / INDENT_MARGIN_PT_SIZE),
- MAX_INDENT_LEVEL
- );
-}
-
-export default ParagraphNodeSpec; \ No newline at end of file
+export default ParagraphNodeSpec;
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 88adab66e..c107a6724 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -14,6 +14,7 @@ import { CollectionView } from '../../collections/CollectionView';
import { ContextMenu } from '../../ContextMenu';
import { KeyValueBox } from '../KeyValueBox';
import { FormattedTextBox } from './FormattedTextBox';
+// eslint-disable-next-line import/extensions
import { wrappingInputRule } from './prosemirrorPatches';
import { RichTextMenu } from './RichTextMenu';
import { schema } from './schema_rts';
@@ -253,7 +254,7 @@ export class RichTextRules {
}
if (marks) {
const tr = state.tr.deleteRange(start, end);
- return marks ? Array.from(marks).reduce((tr, m) => tr.addStoredMark(m), tr) : tr;
+ return marks ? Array.from(marks).reduce((tr2, m) => tr2.addStoredMark(m), tr) : tr;
}
const isValidColor = (strColor: string) => {
@@ -283,7 +284,7 @@ export class RichTextRules {
return marks
? Array.from(marks)
.filter(m => m.type !== state.schema.marks.user_mark)
- .reduce((tr, m) => tr.removeStoredMark(m), tr)
+ .reduce((tr2, m) => tr2.removeStoredMark(m), tr)
: tr;
}),
@@ -309,11 +310,11 @@ export class RichTextRules {
teditor.dispatch(tstate.tr.setSelection(new TextSelection(tstate.doc.resolve(selection))));
}
};
- const getTitledDoc = (docTitle: string) => {
- if (!DocServer.FindDocByTitle(docTitle)) {
- Docs.Create.TextDocument('', { title: docTitle, _width: 400, _layout_fitWidth: true, _layout_autoHeight: true });
+ const getTitledDoc = (title: string) => {
+ if (!DocServer.FindDocByTitle(title)) {
+ Docs.Create.TextDocument('', { title: title, _width: 400, _layout_fitWidth: true, _layout_autoHeight: true });
}
- const titledDoc = DocServer.FindDocByTitle(docTitle);
+ const titledDoc = DocServer.FindDocByTitle(title);
return titledDoc ? Doc.BestEmbedding(titledDoc) : titledDoc;
};
const target = getTitledDoc(docTitle);
@@ -336,7 +337,7 @@ export class RichTextRules {
const assign = match[4] === ':' ? (match[4] = '') : match[4];
const value = match[5];
const dataDoc = value === undefined ? !fieldKey.startsWith('_') : !assign?.startsWith('=');
- const getTitledDoc = (docTitle: string) => DocServer.FindDocByTitle(docTitle);
+ const getTitledDoc = (title: string) => DocServer.FindDocByTitle(title);
// if the value has commas assume its an array (unless it's part of a chat gpt call indicated by '((' )
if (value?.includes(',') && !value.startsWith('((')) {
const values = value.split(',');
diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx
index 7ec296ed2..2c366b49b 100644
--- a/src/client/views/nodes/formattedText/SummaryView.tsx
+++ b/src/client/views/nodes/formattedText/SummaryView.tsx
@@ -3,6 +3,15 @@ import { Fragment, Node, Slice } from 'prosemirror-model';
import * as ReactDOM from 'react-dom/client';
import * as React from 'react';
+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> {
+ render() {
+ return null;
+ }
+}
+
// an elidable textblock that collapses when its '<-' is clicked and expands when its '...' anchor is clicked.
// this node actively edits prosemirror (as opposed to just changing how things are rendered) and thus doesn't
// really need a react view. However, it would be cleaner to figure out how to do this just as a react rendering
@@ -32,8 +41,8 @@ export class SummaryView {
};
const js = node.toJSON;
- node.toJSON = function () {
- return js.apply(this, arguments);
+ node.toJSON = function (...args: any[]) {
+ return js.apply(this, args);
};
this.root = ReactDOM.createRoot(this.dom);
@@ -54,7 +63,8 @@ export class SummaryView {
const visited = new Set();
for (let i: number = start + 1; i < view.state.doc.nodeSize - 1; i++) {
let skip = false;
- view.state.doc.nodesBetween(start, i, (node: Node, pos: number, parent: Node, index: number) => {
+ // eslint-disable-next-line no-loop-func
+ view.state.doc.nodesBetween(start, i, (node: Node /* , pos: number, parent: Node, index: number */) => {
if (node.isLeaf && !visited.has(node) && !skip) {
if (node.marks.find((m: any) => m.type === mtype || m.type === mtypeInc)) {
visited.add(node);
@@ -87,11 +97,3 @@ export class SummaryView {
this.dom.className = this.className(visible);
};
}
-
-interface ISummaryView {}
-// currently nothing needs to be rendered for the internal view of a summary.
-export class SummaryViewInternal extends React.Component<ISummaryView> {
- render() {
- return <> </>;
- }
-}