aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
diff options
context:
space:
mode:
authorJoanne <zehan_ding@brown.edu>2025-05-12 20:58:01 -0400
committerJoanne <zehan_ding@brown.edu>2025-05-12 20:58:01 -0400
commitcd93c88b8fee83a99342eac4dc60f7b4373fa843 (patch)
treeb00d1f46c802752c90e54bb21be785a05e05195e /src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
parent4997c3de20a381eac30224a7a550afa66174f07d (diff)
parent3a733aa0fd24517e83649824dec0fc8bcc0bde43 (diff)
added tutorial tool, still need to integrate with metadatatool
Diffstat (limited to 'src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts')
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts209
1 files changed, 114 insertions, 95 deletions
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index 3c84e5a10..7ae1fc202 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -1,29 +1,30 @@
import { chainCommands, deleteSelection, exitCode, joinBackward, joinDown, joinUp, lift, newlineInCode, selectNodeBackward, setBlockType, splitBlockKeepMarks, toggleMark, wrapIn } from 'prosemirror-commands';
import { redo, undo } from 'prosemirror-history';
-import { Schema } from 'prosemirror-model';
+import { MarkType, Node, Schema } from 'prosemirror-model';
import { liftListItem, sinkListItem, splitListItem, wrapInList } from 'prosemirror-schema-list';
-import { EditorState, NodeSelection, TextSelection, Transaction } from 'prosemirror-state';
+import { Command, EditorState, NodeSelection, TextSelection, Transaction } from 'prosemirror-state';
import { liftTarget } from 'prosemirror-transform';
import { EditorView } from 'prosemirror-view';
import { ClientUtils } from '../../../../ClientUtils';
-import { Utils } from '../../../../Utils';
+import { numberRange, Utils } from '../../../../Utils';
import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols';
import { GetEffectiveAcl } from '../../../../fields/util';
import { Docs } from '../../../documents/Documents';
import { RTFMarkup } from '../../../util/RTFMarkup';
import { DocumentView } from '../DocumentView';
import { OpenWhere } from '../OpenWhere';
+import { FormattedTextBox } from './FormattedTextBox';
const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
-export type KeyMap = { [key: string]: any };
+export type KeyMap = { [key: string]: Command };
-export const updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle?: string, from?: number, to?: number) => {
+export function updateBullets(tx2: Transaction, schema: Schema, assignedMapStyle?: string, from?: number, to?: number) {
let mapStyle = assignedMapStyle;
- tx2.doc.descendants((node: any, offset: any /* , index: any */) => {
+ tx2.doc.descendants((node: Node, offset: number /* , index: any */) => {
if ((from === undefined || to === undefined || (from <= offset + node.nodeSize && to >= offset)) && (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item)) {
- const { path } = tx2.doc.resolve(offset) as any;
- let depth = Array.from(path).reduce((p: number, c: any) => p + (c.type === schema.nodes.ordered_list ? 1 : 0), 0);
+ const resolved = tx2.doc.resolve(offset);
+ let depth = [0, ...numberRange(resolved.depth)].reduce((p, c, idx) => p + (resolved.node(idx).type === schema.nodes.ordered_list ? 1 : 0), 0);
if (node.type === schema.nodes.ordered_list) {
if (depth === 0 && !assignedMapStyle) mapStyle = node.attrs.mapStyle;
depth++;
@@ -32,28 +33,29 @@ export const updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle
}
});
return tx2;
-};
+}
-export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMap {
- const keys: { [key: string]: any } = {};
+export function buildKeymap<S extends Schema<string>>(schema: S, tbox?: FormattedTextBox): KeyMap {
+ const keys: { [key: string]: Command } = {};
- function bind(key: string, cmd: any) {
+ function bind(key: string, cmd: Command) {
keys[key] = cmd;
}
function onKey(): boolean | undefined {
- // bcz: this is pretty hacky -- prosemirror doesn't send us the keyboard event, but the 'event' variable is in scope.. so we access it anyway
+ // bcz: hack -- prosemirror doesn't send us the keyboard event, but the 'event' variable is in scope.. so we access it anyway
// eslint-disable-next-line no-restricted-globals
- return props.onKey?.(event, props);
+ return event && tbox?._props.onKey?.(event as unknown as KeyboardEvent, tbox);
}
- const canEdit = (state: any) => {
- const permissions = GetEffectiveAcl(props.TemplateDataDocument ?? props.Document[DocData]);
- switch (permissions) {
+ const canEdit = (state: EditorState) => {
+ if (!tbox) return true;
+ switch (GetEffectiveAcl(tbox.dataDoc)) {
case AclAugment:
{
- const prevNode = state.selection.$cursor.nodeBefore;
- const prevUser = !prevNode ? ClientUtils.CurrentUserEmail() : prevNode.marks.lastElement()?.attrs.userid;
+ // previously used hack: (state.selection as any).$cursor.nodeBefore;
+ const prevNode = state.selection?.$anchor.nodeBefore;
+ const prevUser = !prevNode ? ClientUtils.CurrentUserEmail() : Array.from(prevNode.marks).lastElement()?.attrs.userid;
if (prevUser !== ClientUtils.CurrentUserEmail()) {
return false;
}
@@ -64,7 +66,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
return true;
};
- const toggleEditableMark = (mark: any) => (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && toggleMark(mark)(state, dispatch);
+ const toggleEditableMark = (mark: MarkType) => (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && toggleMark(mark)(state, dispatch);
// History commands
bind('Mod-z', undo);
@@ -84,13 +86,13 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
bind('Mod-U', toggleEditableMark(schema.marks.underline));
// Commands for lists
- bind('Ctrl-i', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state as any, dispatch as any));
+ bind('Ctrl-i', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state, dispatch));
bind('Ctrl-Tab', () => onKey() || true);
bind('Alt-Tab', () => onKey() || true);
bind('Meta-Tab', () => onKey() || true);
bind('Meta-Enter', () => onKey() || true);
- bind('Tab', (state: EditorState, dispatch: (tx: Transaction) => void) => {
+ bind('Tab', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
if (onKey()) return true;
if (!canEdit(state)) return true;
const ref = state.selection;
@@ -101,13 +103,13 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
const tx3 = updateBullets(tx2, schema);
marks && tx3.ensureMarks([...marks]);
marks && tx3.setStoredMarks([...marks]);
- dispatch(tx3);
+ dispatch?.(tx3);
})
) {
// couldn't sink into an existing list, so wrap in a new one
const newstate = state.applyTransaction(state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end)));
if (
- !wrapInList(schema.nodes.ordered_list)(newstate.state as any, (tx2: Transaction) => {
+ !wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
const tx25 = updateBullets(tx2, schema);
const olNode = tx25.doc.nodeAt(range!.start)!;
const tx3 = tx25.setNodeMarkup(range!.start, olNode.type, olNode.attrs, marks);
@@ -115,16 +117,16 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
marks && tx3.ensureMarks([...marks]);
marks && tx3.setStoredMarks([...marks]);
const tx4 = tx3.setSelection(TextSelection.near(tx3.doc.resolve(state.selection.to + 2)));
- dispatch(tx4);
+ dispatch?.(tx4);
})
) {
console.log('bullet promote fail');
}
}
- return undefined;
+ return false;
});
- bind('Shift-Tab', (state: EditorState, dispatch: (tx: Transaction) => void) => {
+ bind('Shift-Tab', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
if (onKey()) return true;
if (!canEdit(state)) return true;
const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
@@ -134,119 +136,136 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
const tx3 = updateBullets(tx2, schema);
marks && tx3.ensureMarks([...marks]);
marks && tx3.setStoredMarks([...marks]);
- dispatch(tx3);
+ dispatch?.(tx3);
})
) {
console.log('bullet demote fail');
}
- return undefined;
+ return false;
});
// Command to create a new Tab with a PDF of all the command shortcuts
- bind('Mod-/', () => {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ bind('Mod-/', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
const newDoc = Docs.Create.PdfDocument(ClientUtils.prepend('/assets/cheat-sheet.pdf'), { _width: 300, _height: 300 });
- props.addDocTab(newDoc, OpenWhere.addRight);
+ tbox?._props.addDocTab(newDoc, OpenWhere.addRight);
+ return false;
});
// Commands to modify BlockType
- bind('Ctrl->', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state && wrapIn(schema.nodes.blockquote)(state as any, dispatch as any)));
- bind('Alt-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state as any, dispatch as any));
- bind('Shift-Ctrl-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.code_block)(state as any, dispatch as any));
+ bind('Ctrl->', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && wrapIn(schema.nodes.blockquote)(state, dispatch));
+ bind('Alt-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state, dispatch));
+ bind('Shift-Ctrl-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.code_block)(state, dispatch));
- bind('Ctrl-m', (state: EditorState, dispatch: (tx: Transaction) => void) => {
+ bind('Ctrl-m', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
if (canEdit(state)) {
const tr = state.tr.replaceSelectionWith(schema.nodes.equation.create({ fieldKey: 'math' + Utils.GenerateGuid() }));
- dispatch(tr.setSelection(new NodeSelection(tr.doc.resolve(tr.selection.$from.pos - 1))));
+ dispatch?.(tr.setSelection(new NodeSelection(tr.doc.resolve(tr.selection.$from.pos - 1))));
+ return true;
}
+ return false;
});
for (let i = 1; i <= 6; i++) {
- bind('Shift-Ctrl-' + i, (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state as any, dispatch as any));
+ bind('Shift-Ctrl-' + i, (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state, dispatch));
}
// Command to create a horizontal break line
const hr = schema.nodes.horizontal_rule;
- bind('Mod-_', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()));
+ bind('Mod-_', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ if (canEdit(state)) {
+ dispatch?.(state.tr.replaceSelectionWith(hr.create()).scrollIntoView());
+ return true;
+ }
+ return false;
+ });
// Command to unselect all
- bind('Escape', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
- (document.activeElement as any).blur?.();
+ bind('Escape', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ dispatch?.(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
+ (document.activeElement as HTMLElement)?.blur?.();
DocumentView.DeselectAll();
+ return true;
});
bind('Alt-Enter', () => onKey() || true);
bind('Ctrl-Enter', () => onKey() || true);
- bind('Cmd-a', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1))));
+ bind('Cmd-a', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ dispatch?.(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1))));
return true;
});
bind('Cmd-?', () => {
RTFMarkup.Instance.setOpen(true);
return true;
});
- bind('Cmd-e', (state: EditorState, dispatch: (tx: Transaction) => void) => {
+ bind('Cmd-e', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
if (!state.selection.empty) {
const mark = state.schema.marks.summarizeInclusive.create();
const tr = state.tr.addMark(state.selection.$from.pos, state.selection.$to.pos, mark);
const content = tr.selection.content();
- tr.selection.replaceWith(tr, schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }));
- dispatch(tr);
+ tr.selection.replaceWith(tr, schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }, undefined, state.selection.$anchor.marks() ?? []));
+ dispatch?.(tr);
}
return true;
});
- bind('Cmd-]', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- const resolved = state.doc.resolve(state.selection.from) as any;
- const { tr } = state;
- if (resolved?.parent.type.name === 'paragraph') {
- tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks);
+ bind('Cmd-]', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ const {
+ tr,
+ selection: { $from },
+ } = state;
+ if ($from?.parent.type.name === 'paragraph') {
+ tr.setNodeMarkup(state.selection.from - state.selection.$from.parentOffset - 1, schema.nodes.paragraph, { ...$from.parent.attrs, align: 'right' }, $from.parent.marks);
} else {
- const node = resolved.nodeAfter;
+ const node = $from.nodeAfter;
const sm = state.storedMarks || undefined;
if (node) {
tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'right' })).setStoredMarks([...node.marks, ...(sm || [])]);
}
}
- dispatch(tr);
+ dispatch?.(tr);
return true;
});
- bind('Cmd-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- const resolved = state.doc.resolve(state.selection.from) as any;
- const { tr } = state;
- if (resolved?.parent.type.name === 'paragraph') {
- tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks);
+ bind('Cmd-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ const {
+ tr,
+ selection: { $from },
+ } = state;
+ if ($from?.parent.type.name === 'paragraph') {
+ tr.setNodeMarkup(state.selection.from - state.selection.$from.parentOffset - 1, schema.nodes.paragraph, { ...$from.parent.attrs, align: 'center' }, $from.parent.marks);
} else {
- const node = resolved.nodeAfter;
+ const node = $from.nodeAfter;
const sm = state.storedMarks || undefined;
if (node) {
tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'center' })).setStoredMarks([...node.marks, ...(sm || [])]);
}
}
- dispatch(tr);
+ dispatch?.(tr);
return true;
});
- bind('Cmd-[', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- const resolved = state.doc.resolve(state.selection.from) as any;
- const { tr } = state;
- if (resolved?.parent.type.name === 'paragraph') {
- tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks);
+ bind('Cmd-[', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ const {
+ tr,
+ selection: { $from },
+ } = state;
+ if ($from?.parent.type.name === 'paragraph') {
+ tr.setNodeMarkup(state.selection.from - state.selection.$from.parentOffset - 1, schema.nodes.paragraph, { ...$from.parent.attrs, align: 'left' }, $from.parent.marks);
} else {
- const node = resolved.nodeAfter;
+ const node = $from.nodeAfter;
const sm = state.storedMarks || undefined;
if (node) {
tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'left' })).setStoredMarks([...node.marks, ...(sm || [])]);
}
}
- dispatch(tr);
+ dispatch?.(tr);
return true;
});
- bind('Cmd-f', (state: EditorState, dispatch: (tx: Transaction) => void) => {
+ bind('Cmd-f', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
const content = state.tr.selection.empty ? undefined : state.tr.selection.content().content.textBetween(0, state.tr.selection.content().size + 1);
const newNode = schema.nodes.footnote.create({}, content ? state.schema.text(content) : undefined);
const { tr } = state;
tr.replaceSelectionWith(newNode); // replace insertion with a footnote.
- dispatch(
+ dispatch?.(
tr.setSelection(
new NodeSelection( // select the footnote node to open its display
tr.doc.resolve(
@@ -259,25 +278,25 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
return true;
});
- bind('Ctrl-a', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1))));
+ bind('Ctrl-a', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => {
+ dispatch?.(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1))));
return true;
});
// backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward);
- const backspace = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => {
+ const backspace = (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined, view?: EditorView) => {
if (onKey()) return true;
if (!canEdit(state)) return true;
if (
!deleteSelection(state, (tx: Transaction) => {
- dispatch(updateBullets(tx, schema));
+ dispatch?.(updateBullets(tx, schema));
})
) {
if (
!joinBackward(state, (tx: Transaction) => {
- dispatch(updateBullets(tx, schema));
- if (view.state.selection.$anchor.node(-1)?.type === schema.nodes.list_item) {
+ dispatch?.(updateBullets(tx, schema));
+ if (view?.state.selection.$anchor.node(-1)?.type === schema.nodes.list_item) {
// gets rid of an extra paragraph when joining two list items together.
joinBackward(view.state, (tx2: Transaction) => view.dispatch(tx2));
}
@@ -285,7 +304,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
) {
if (
!selectNodeBackward(state, (tx: Transaction) => {
- dispatch(updateBullets(tx, schema));
+ dispatch?.(updateBullets(tx, schema));
})
) {
return false;
@@ -299,7 +318,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
// newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock
// command to break line
- const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView, once = true) => {
+ const enter = (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined, view?: EditorView, once = true) => {
if (onKey()) return true;
if (!canEdit(state)) return true;
@@ -311,31 +330,31 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
!state.selection.$from.node().content.size &&
trange
) {
- dispatch(state.tr.lift(trange, depth) as any);
+ dispatch?.(state.tr.lift(trange, depth));
return true;
}
const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
- if (!newlineInCode(state, dispatch as any)) {
- const olNode = view.state.selection.$anchor.node(-2);
- const liNode = view.state.selection.$anchor.node(-1);
+ if (!newlineInCode(state, dispatch)) {
+ const olNode = view?.state.selection.$anchor.node(-2);
+ const liNode = view?.state.selection.$anchor.node(-1);
// prettier-ignore
if (liNode?.type === schema.nodes.list_item && !liNode.textContent &&
- olNode?.type === schema.nodes.ordered_list && once && view.state.selection.$from.depth === 3)
+ olNode?.type === schema.nodes.ordered_list && once && view?.state.selection.$from.depth === 3)
{
// handles case of hitting enter at then end of a top-level empty list item - the result is to create a paragraph
- for (let i = 0; i < 10 && view.state.selection.$from.depth > 1 && liftListItem(schema.nodes.list_item)(view.state, view.dispatch); i++);
+ for (let i = 0; i < 10 && view?.state.selection.$from.depth > 1 && liftListItem(schema.nodes.list_item)(view.state, view.dispatch); i++);
} else if (
- !splitListItem(schema.nodes.list_item)(state as any, (tx2: Transaction) => {
+ !splitListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
const tx3 = updateBullets(tx2, schema);
marks && tx3.ensureMarks([...marks]);
marks && tx3.setStoredMarks([...marks]);
- dispatch(tx3);
+ dispatch?.(tx3);
// removes an extra paragraph created when selecting text across two list items or splitting an empty list item
- !once && view.dispatch(view.state.tr.deleteRange(view.state.selection.from - 5, view.state.selection.from - 2));
+ !once && view?.dispatch(view?.state.tr.deleteRange(view.state.selection.from - 5, view.state.selection.from - 2));
})
) {
- if (once && view.state.selection.$from.node(-2)?.type === schema.nodes.ordered_list && view.state.selection.$from.node(-1)?.type === schema.nodes.list_item && view.state.selection.$from.node(-1)?.textContent === '') {
+ if (once && view?.state.selection.$from.node(-2)?.type === schema.nodes.ordered_list && view?.state.selection.$from.node(-1)?.type === schema.nodes.list_item && view.state.selection.$from.node(-1)?.textContent === '') {
// handles case of hitting enter on an empty list item which needs to create a second empty paragraph, then split it by calling enter() again
view.dispatch(view.state.tr.insert(view.state.selection.from, schema.nodes.paragraph.create({})));
enter(view.state, view.dispatch, view, false);
@@ -346,12 +365,12 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
const tonode = tx3.selection.$to.node();
if (tx3.selection.to && tx3.doc.nodeAt(tx3.selection.to - 1)) {
const tx4 = tx3.setNodeMarkup(tx3.selection.to - 1, tonode.type, fromattrs, tonode.marks).setStoredMarks(marks || []);
- dispatch(tx4);
+ dispatch?.(tx4);
}
- if (view.state.selection.$anchor.depth > 0 &&
- view.state.selection.$anchor.node(view.state.selection.$anchor.depth-1).type === schema.nodes.list_item &&
- view.state.selection.$anchor.nodeAfter?.type === schema.nodes.text && once) {
+ if ((view?.state.selection.$anchor.depth ??0) > 0 &&
+ view?.state.selection.$anchor.node(view.state.selection.$anchor.depth-1).type === schema.nodes.list_item &&
+ view?.state.selection.$anchor.nodeAfter?.type === schema.nodes.text && once) {
// if text is selected across list items, then we need to forcibly insert a new line since the splitBlock code joins the two list items.
enter(view.state, dispatch, view, false);
}
@@ -368,14 +387,14 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa
// Command to create a blank space
bind('Space', () => {
- const editDoc = props.TemplateDataDocument ?? props.Document[DocData];
+ const editDoc = tbox?._props.TemplateDataDocument ?? tbox?.Document[DocData];
if (editDoc && ![AclAdmin, AclAugment, AclEdit].includes(GetEffectiveAcl(editDoc))) return true;
return false;
});
- bind('Alt-ArrowUp', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && joinUp(state, dispatch as any));
- bind('Alt-ArrowDown', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && joinDown(state, dispatch as any));
- bind('Mod-BracketLeft', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && lift(state, dispatch as any));
+ bind('Alt-ArrowUp', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && joinUp(state, dispatch));
+ bind('Alt-ArrowDown', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && joinDown(state, dispatch));
+ bind('Mod-BracketLeft', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && lift(state, dispatch));
const cmd = chainCommands(exitCode, (state, dispatch) => {
if (dispatch) {