docs: function () {
          const editor = this.editor
          const $textElem = editor.$textElem
  
          function insertEmptyP ($selectionElem) {
              const $p = $('<p><br></p>')
              $p.insertBefore($selectionElem)
              editor.selection.createRangeByElem($p, true)
              editor.selection.restoreSelection()
              $selectionElem.remove()
          }
  
          // 将回车之后生成的非 <p> 的顶级标签，改为 <p>
          function pHandle(e) {
              const $selectionElem = editor.selection.getSelectionContainerElem()
              const $parentElem = $selectionElem.parent()
  
              if ($parentElem.html() === '<code><br></code>') {
                  // 回车之前光标所在一个 <p><code>.....</code></p> ，忽然回车生成一个空的 <p><code><br></code></p>
                  // 而且继续回车跳不出去，因此只能特殊处理
                  insertEmptyP($selectionElem)
                  return
              }
  
              if (!$parentElem.equal($textElem)) {
                  // 不是顶级标签
                  return
              }
  
              const nodeName = $selectionElem.getNodeName()
              if (nodeName === 'P') {
                  // 当前的标签是 P ，不用做处理
                  return
              }
  
              if ($selectionElem.text()) {
                  // 有内容，不做处理
                  return
              }
  
              // 插入 <p> ，并将选取定位到 <p>，删除当前标签
              insertEmptyP($selectionElem)
          }
  
          $textElem.on('keyup', e => {
              if (e.keyCode !== 13) {
                  // 不是回车键
                  return
              }
              // 将回车之后生成的非 <p> 的顶级标签，改为 <p>
              pHandle(e)
          })
  
          // <pre><code></code></pre> 回车时 特殊处理
          function codeHandle(e) {
              const $selectionElem = editor.selection.getSelectionContainerElem()
              if (!$selectionElem) {
                  return
              }
              const $parentElem = $selectionElem.parent()
              const selectionNodeName = $selectionElem.getNodeName()
              const parentNodeName = $parentElem.getNodeName()
  
              if (selectionNodeName !== 'CODE' || parentNodeName !== 'PRE') {
                  // 不符合要求 忽略
                  return
              }
  
              if (!editor.cmd.queryCommandSupported('insertHTML')) {
                  // 必须原生支持 insertHTML 命令
                  return
              }
  
              // 处理：光标定位到代码末尾，联系点击两次回车，即跳出代码块
              if (editor._willBreakCode === true) {
                  // 此时可以跳出代码块
                  // 插入 <p> ，并将选取定位到 <p>
                  const $p = $('<p><br></p>')
                  $p.insertAfter($parentElem)
                  editor.selection.createRangeByElem($p, true)
                  editor.selection.restoreSelection()
  
                  // 修改状态
                  editor._willBreakCode = false
  
                  e.preventDefault()
                  return
              }
  
              const _startOffset = editor.selection.getRange().startOffset
  
              // 处理：回车时，不能插入 <br> 而是插入 \n ，因为是在 pre 标签里面
              editor.cmd.do('insertHTML', '\n')
              editor.selection.saveRange()
              if (editor.selection.getRange().startOffset === _startOffset) {
                  // 没起作用，再来一遍
                  editor.cmd.do('insertHTML', '\n')
              }
  
              const codeLength = $selectionElem.html().length
              if (editor.selection.getRange().startOffset + 1 === codeLength) {
                  // 说明光标在代码最后的位置，执行了回车操作
                  // 记录下来，以便下次回车时候跳出 code
                  editor._willBreakCode = true
              }
  
              // 阻止默认行为
              e.preventDefault()
          }
  
          $textElem.on('keydown', e => {
              if (e.keyCode !== 13) {
                  // 不是回车键
                  // 取消即将跳转代码块的记录
                  editor._willBreakCode = false
                  return
              }
              // <pre><code></code></pre> 回车时 特殊处理
              codeHandle(e)
          })
      }