OverviewFilesCommitsIssuesDocsReleasesPeers

holepunchto-deps / @holepunchto / keet-editor-parser / src / document / to-document-trim.js

56 lines · javascript ref:
module.exports = { documentTrim }

const { NODE_TYPE } = require('../constants')

const { TEXT, HARD_BREAK } = NODE_TYPE

/**
 * Trims leading and trailing whitespace (including hardBreak-only blocks)
 * from the given Tiptap JSON document.
 *
 * - Removes paragraphs at the start and end if their only content is a `hardBreak`.
 * - Trims whitespace from the start of the first text node and end of the last text node.
 *
 * @param {Object} doc - A Tiptap JSON document object.
 * @returns {Object} The modified (mutated) document with leading/trailing spacing trimmed.
 *
 */
function documentTrim(doc) {
  if (!doc?.content?.length) return doc

  let firstTextNode = null
  let lastTextNode = null
  let firstNodeIndex = 0
  let lastNodeIndex = 0

  for (let i = 0; i < doc.content.length; i++) {
    const node = doc.content[i]

    if (!node.content) {
      continue
    }

    const textNodes = node.content || []

    if (!firstTextNode && textNodes?.[0]?.type !== HARD_BREAK) {
      firstTextNode = textNodes[0]
      firstNodeIndex = i
    }
    if (textNodes?.[textNodes.length - 1]?.type !== HARD_BREAK) {
      lastTextNode = textNodes[textNodes.length - 1]
      lastNodeIndex = i
    }
  }

  doc.content = doc.content.slice(firstNodeIndex, lastNodeIndex + 1)

  if (firstTextNode?.type === TEXT) {
    firstTextNode.text = firstTextNode.text.trimStart()
  }
  if (lastTextNode?.type === TEXT) {
    lastTextNode.text = lastTextNode.text.trimEnd()
  }

  return doc
}