diff --git a/packages/core/src/Editor.ts b/packages/core/src/Editor.ts index 002ef7b6..bbd3e8b5 100644 --- a/packages/core/src/Editor.ts +++ b/packages/core/src/Editor.ts @@ -12,6 +12,7 @@ import createDocument from './helpers/createDocument' import getHTMLFromFragment from './helpers/getHTMLFromFragment' import getText from './helpers/getText' import isNodeEmpty from './helpers/isNodeEmpty' +import resolveFocusPosition from './helpers/resolveFocusPosition' import getTextSeralizersFromSchema from './helpers/getTextSeralizersFromSchema' import createStyleTag from './utilities/createStyleTag' import isFunction from './utilities/isFunction' @@ -260,11 +261,14 @@ export class Editor extends EventEmitter { * Creates a ProseMirror view. */ private createView(): void { + const doc = createDocument(this.options.content, this.schema, this.options.parseOptions) + const selection = resolveFocusPosition(doc, this.options.autofocus) this.view = new EditorView(this.options.element, { ...this.options.editorProps, dispatchTransaction: this.dispatchTransaction.bind(this), state: EditorState.create({ - doc: createDocument(this.options.content, this.schema, this.options.parseOptions), + doc, + selection, }), }) diff --git a/packages/core/src/commands/focus.ts b/packages/core/src/commands/focus.ts index 1ae0c21e..650e84e3 100644 --- a/packages/core/src/commands/focus.ts +++ b/packages/core/src/commands/focus.ts @@ -1,42 +1,7 @@ -import { EditorState, Selection, TextSelection } from 'prosemirror-state' import { RawCommands, FocusPosition } from '../types' -import minMax from '../utilities/minMax' import isTextSelection from '../helpers/isTextSelection' import isiOS from '../utilities/isiOS' - -function resolveSelection(state: EditorState, position: FocusPosition = null) { - if (!position) { - return null - } - - if (position === 'start' || position === true) { - return { - from: 0, - to: 0, - } - } - - const { size } = state.doc.content - - if (position === 'end') { - return { - from: size, - to: size, - } - } - - if (position === 'all') { - return { - from: 0, - to: size, - } - } - - return { - from: position, - to: position, - } -} +import resolveFocusPosition from '../helpers/resolveFocusPosition' declare module '@tiptap/core' { interface Commands { @@ -95,13 +60,7 @@ export const focus: RawCommands['focus'] = (position = null, options) => ({ return true } - const { from, to } = resolveSelection(editor.state, position) || editor.state.selection - const { doc, storedMarks } = tr - const minPos = Selection.atStart(doc).from - const maxPos = Selection.atEnd(doc).to - const resolvedFrom = minMax(from, minPos, maxPos) - const resolvedEnd = minMax(to, minPos, maxPos) - const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd) + const selection = resolveFocusPosition(editor.state.doc, position) || editor.state.selection const isSameSelection = editor.state.selection.eq(selection) if (dispatch) { @@ -111,8 +70,8 @@ export const focus: RawCommands['focus'] = (position = null, options) => ({ // `tr.setSelection` resets the stored marks // so we’ll restore them if the selection is the same as before - if (isSameSelection && storedMarks) { - tr.setStoredMarks(storedMarks) + if (isSameSelection && tr.storedMarks) { + tr.setStoredMarks(tr.storedMarks) } delayedFocus() diff --git a/packages/core/src/helpers/resolveFocusPosition.ts b/packages/core/src/helpers/resolveFocusPosition.ts new file mode 100644 index 00000000..bf3e0559 --- /dev/null +++ b/packages/core/src/helpers/resolveFocusPosition.ts @@ -0,0 +1,22 @@ +import { Node as ProseMirrorNode } from 'prosemirror-model' +import { Selection, TextSelection } from 'prosemirror-state' +import { FocusPosition } from '../types' +import minMax from '../utilities/minMax' + +export default function resolveFocusPosition( + doc: ProseMirrorNode, + position: FocusPosition = null +): Selection | null { + + if (!position) return null + if (position === 'start' || position === true) return Selection.atStart(doc) + if (position === 'end') return Selection.atEnd(doc) + if (position === 'all') return TextSelection.create(doc, 0, doc.content.size) + + // Check if `position` is in bounds of the doc if `position` is a number. + const minPos = Selection.atStart(doc).from + const maxPos = Selection.atEnd(doc).to + const resolvedFrom = minMax(position, minPos, maxPos) + const resolvedEnd = minMax(position, minPos, maxPos) + return TextSelection.create(doc, resolvedFrom, resolvedEnd) +} \ No newline at end of file