OverviewFilesCommitsIssuesDocsReleasesPeers

holepunchto-deps / @holepunchto / keet-editor / src / extensions / helpers / exit-block.js

89 lines · javascript ref:
import { TextSelection } from 'prosemirror-state'

export function exitAfterBlock () {
  const { editor, name } = this

  const { state, view, schema } = editor
  const { nodes } = schema

  const { from, to } = state.selection
  const { $head, $anchor } = state.selection

  if (!$head.sameParent($anchor)) return

  let inBlock

  state.doc.nodesBetween(from - 1, to - 1, node => {
    if (node.type.name === name) {
      inBlock = true
    }
  })

  if (!inBlock) return

  const pos = $head.after()
  const { depth } = $head

  const cursorAtEnd = to === pos - 1

  if (!cursorAtEnd) return

  let tr = state.tr

  if (pos + depth >= state.tr.doc.content.size) {
    tr = tr.insert(pos + depth - 1, nodes.paragraph.createAndFill(''))
  }

  tr = tr.setSelection(TextSelection.create(tr.doc, pos + depth))

  const nextState = state.apply(tr)
  view.updateState(nextState)

  return true
}

export function exitBeforeBlock () {
  const { editor, name } = this

  const { state, view, schema } = editor
  const { nodes } = schema

  const { from, to } = state.selection
  const { $head, $anchor } = state.selection

  const { depth, parentOffset } = $head

  if (parentOffset !== 0) return

  if (!$head.sameParent($anchor)) return

  let inBlock

  state.doc.nodesBetween(from - 1, to - 1, node => {
    if (node.type.name === name) {
      inBlock = true
    }
  })

  if (!inBlock) return

  const pos = from

  const parentPos = pos - depth

  const parentResolvedPos = state.doc.resolve(parentPos)
  const parentNode = parentResolvedPos.nodeAfter

  if (parentNode?.type.name !== this.name) return

  let tr = state.tr

  tr = tr.insert(parentPos, nodes.paragraph.createAndFill(''))
  tr = tr.setSelection(TextSelection.create(tr.doc, parentPos))

  const nextState = state.apply(tr)
  view.updateState(nextState)

  return true
}