add: editor insert & replace api with selection
This commit is contained in:
parent
31d8e98594
commit
f36c2b3932
|
|
@ -1,6 +1,14 @@
|
|||
// The prosemirror imports are only for type hint
|
||||
import { Node, NodeType } from "prosemirror-model";
|
||||
import { Mark, MarkType, ResolvedPos, Attrs } from "prosemirror-model";
|
||||
import {
|
||||
Node,
|
||||
NodeType,
|
||||
Mark,
|
||||
MarkType,
|
||||
ResolvedPos,
|
||||
Attrs,
|
||||
DOMParser,
|
||||
Schema,
|
||||
} from "prosemirror-model";
|
||||
import { EditorState, TextSelection } from "prosemirror-state";
|
||||
import { EditorView } from "prosemirror-view";
|
||||
|
||||
|
|
@ -8,6 +16,38 @@ declare const _currentEditorInstance: {
|
|||
_editorCore: EditorCore;
|
||||
};
|
||||
|
||||
function fromHTML(schema: Schema, html: string, slice?: boolean) {
|
||||
let domNode = document.createElement("div");
|
||||
domNode.innerHTML = html;
|
||||
let fragment = document.createDocumentFragment();
|
||||
while (domNode.firstChild) {
|
||||
fragment.appendChild(domNode.firstChild);
|
||||
}
|
||||
if (slice) {
|
||||
return DOMParser.fromSchema(schema).parseSlice(fragment);
|
||||
} else {
|
||||
return DOMParser.fromSchema(schema).parse(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
function getSliceFromHTML(state: EditorState, html: string) {
|
||||
return fromHTML(state.schema, html, true);
|
||||
}
|
||||
|
||||
function getNodeFromHTML(state: EditorState, html: string) {
|
||||
return fromHTML(state.schema, html);
|
||||
}
|
||||
|
||||
function setSelection(anchor: number, head?: number | undefined) {
|
||||
return (state: EditorState, dispatch?: EditorView["dispatch"]) => {
|
||||
const { tr, selection } = state;
|
||||
const _TextSelection =
|
||||
selection.constructor as unknown as typeof TextSelection;
|
||||
tr.setSelection(_TextSelection.create(tr.doc, anchor, head));
|
||||
dispatch && dispatch(tr);
|
||||
};
|
||||
}
|
||||
|
||||
// Code from https://github.com/ueberdosis/tiptap/tree/main/packages/core/src/helpers
|
||||
|
||||
function objectIncludes(object1: any, object2: any) {
|
||||
|
|
@ -148,7 +188,8 @@ function replaceRangeNode(
|
|||
nodeType: NodeType,
|
||||
nodeAttrs: Attrs | string,
|
||||
markType?: MarkType,
|
||||
markAttrs?: Attrs | string
|
||||
markAttrs?: Attrs | string,
|
||||
select?: boolean
|
||||
) {
|
||||
return (state: EditorState, dispatch: EditorView["dispatch"]) => {
|
||||
const { tr } = state;
|
||||
|
|
@ -166,6 +207,9 @@ function replaceRangeNode(
|
|||
);
|
||||
console.log("Replace Node", from, to, node);
|
||||
tr.replaceWith(from, to, node);
|
||||
if (select) {
|
||||
setSelection(from + node.nodeSize, from)(state);
|
||||
}
|
||||
dispatch(tr);
|
||||
};
|
||||
}
|
||||
|
|
@ -333,6 +377,9 @@ export const BetterNotesEditorAPI = {
|
|||
updateImageDimensions,
|
||||
getHeadingLevelInRange,
|
||||
updateHeadingsInRange,
|
||||
getSliceFromHTML,
|
||||
getNodeFromHTML,
|
||||
setSelection,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export {
|
|||
getRangeAtCursor,
|
||||
getLineAtCursor,
|
||||
getPositionAtLine,
|
||||
getPositionAtCursor,
|
||||
getURLAtCursor,
|
||||
updateImageDimensionsAtCursor,
|
||||
updateURLAtCursor,
|
||||
|
|
@ -24,9 +25,11 @@ export {
|
|||
function insert(
|
||||
editor: Zotero.EditorInstance,
|
||||
content: string = "",
|
||||
position: number | "end" | "start" | "cursor" = "cursor"
|
||||
position: number | "end" | "start" | "cursor" = "cursor",
|
||||
select?: boolean
|
||||
) {
|
||||
const core = getEditorCore(editor);
|
||||
const EditorAPI = getEditorAPI(editor);
|
||||
if (position === "cursor") {
|
||||
position = getPositionAtCursor(editor);
|
||||
} else if (position === "end") {
|
||||
|
|
@ -36,6 +39,13 @@ function insert(
|
|||
}
|
||||
position = Math.max(0, Math.min(position, core.view.state.doc.content.size));
|
||||
(core as any).insertHTML(position, content);
|
||||
if (select) {
|
||||
const slice = EditorAPI.getSliceFromHTML(core.view.state, content);
|
||||
EditorAPI.setSelection(position + slice.content.size, position)(
|
||||
core.view.state,
|
||||
core.view.dispatch
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function del(editor: Zotero.EditorInstance, from: number, to: number) {
|
||||
|
|
@ -92,7 +102,8 @@ function replace(
|
|||
| "backgroundColor"
|
||||
| "link"
|
||||
| "code",
|
||||
markAttrs: Record<string, any>
|
||||
markAttrs: Record<string, any>,
|
||||
select?: boolean
|
||||
) {
|
||||
const core = getEditorCore(editor);
|
||||
const EditorAPI = getEditorAPI(editor);
|
||||
|
|
@ -104,7 +115,8 @@ function replace(
|
|||
schema.nodes[nodeTypeName],
|
||||
JSON.stringify(nodeAttrs),
|
||||
schema.marks[markTypeName],
|
||||
JSON.stringify(markAttrs)
|
||||
JSON.stringify(markAttrs),
|
||||
select
|
||||
)(core.view.state, core.view.dispatch);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue