hunk.code_window:     const { document } = state
       const schema = editor.getSchema()
       const offsetKey = OffsetKey.findKey(element, offset)
       const { key } = offsetKey
       const node = document.getDescendant(key)
       const decorators = document.getDescendantDecorators(key, schema)
       const ranges = node.getRanges(decorators)
  
hunk.labels: keep keep add keep keep keep keep
hunk.after_edit:     if (!offsetKey) return null
  
hunk.file_path: src/components/content.js
hunk.type: add
file: 
  import normalizeNodeAndOffset from './normalize-node-and-offset'
  
  /**
   * Offset key parser regex.
   *
   * @type {RegExp}
   */
  
  const PARSER = /^(\w+)(?:-(\d+))?$/
  
  /**
   * Offset key attribute name.
   *
   * @type {String}
   */
  
  const ATTRIBUTE = 'data-offset-key'
  
  /**
   * Offset key attribute selector.
   *
   * @type {String}
   */
  
  const SELECTOR = `[${ATTRIBUTE}]`
  
  /**
   * Void node selection.
   *
   * @type {String}
   */
  
  const VOID_SELECTOR = '[data-slate-void]'
  
  /**
   * Find the start and end bounds from an `offsetKey` and `ranges`.
   *
   * @param {Number} index
   * @param {List<Range>} ranges
   * @return {Object}
   */
  
  function findBounds(index, ranges) {
    const range = ranges.get(index)
    const start = ranges
      .slice(0, index)
      .reduce((memo, r) => {
        return memo += r.text.length
      }, 0)
  
    return {
      start,
      end: start + range.text.length
    }
  }
  
  /**
   * From a DOM node, find the closest parent's offset key.
   *
   * @param {Element} rawNode
   * @param {Number} rawOffset
   * @return {Object}
   */
  
  function findKey(rawNode, rawOffset) {
    let { node, offset } = normalizeNodeAndOffset(rawNode, rawOffset)
    const { parentNode } = node
  
    // Find the closest parent with an offset key attribute.
    let closest = parentNode.closest(SELECTOR)
    let offsetKey
  
    // For void nodes, the element with the offset key will be a cousin, not an
    // ancestor, so find it by going down from the nearest void parent.
    if (!closest) {
      const closestVoid = parentNode.closest(VOID_SELECTOR)
      closest = closestVoid.querySelector(SELECTOR)
      offset = closest.textContent.length
    }
  
    // Get the string value of the offset key attribute.
    offsetKey = closest.getAttribute(ATTRIBUTE)
  
    // If we still didn't find an offset key, this is a bug.
    if (!offsetKey) {
      throw new Error(`Unable to find offset key for ${node} with offset "${offset}".`)
    }
  
    // Return the parsed the offset key.
    const parsed = parse(offsetKey)
    return {
      key: parsed.key,
      index: parsed.index,
      offset
    }
  }
  
  /**
   * Find the selection point from an `offsetKey` and `ranges`.
   *
   * @param {Object} offsetKey
   * @param {List<Range>} ranges
   * @return {Object}
   */
  
  function findPoint(offsetKey, ranges) {
    let { key, index, offset } = offsetKey
    const { start, end } = findBounds(index, ranges)
  
    // Don't let the offset be outside of the start and end bounds.
    offset = start + offset
    offset = Math.max(offset, start)
    offset = Math.min(offset, end)
  
    return {
      key,
      index,
      start,
      end,
      offset
    }
  }
  
  /**
   * Parse an offset key `string`.
   *
   * @param {String} string
   * @return {Object}
   */
  
  function parse(string) {
    const matches = PARSER.exec(string)
    if (!matches) throw new Error(`Invalid offset key string "${string}".`)
    const [ original, key, index ] = matches // eslint-disable-line no-unused-vars
    return {
      key,
      index: parseInt(index, 10)
    }
  }
  
  /**
   * Stringify an offset key `object`.
   *
   * @param {Object} object
   *   @property {String} key
   *   @property {Number} index
   * @return {String}
   */
  
  function stringify(object) {
    return `${object.key}-${object.index}`
  }
  
  /**
   * Export.
   *
   * @type {Object}
   */
  
  export default {
    findBounds,
    findKey,
    findPoint,
    parse,
    stringify
  }
  