text: define([
    'summernote/core/dom',
    'summernote/core/range'
  ], function (dom, range) {
  
    var Typing = function () {
  
      /**
       * @param {jQuery} $editable 
       * @param {WrappedRange} rng
       * @param {Number} tabsize
       */
      this.insertTab = function ($editable, rng, tabsize) {
        var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));
        rng = rng.deleteContents();
        rng.insertNode(tab, true);
  
        rng = range.create(tab, tabsize);
        rng.select();
      };
  
      /**
       * insert paragraph
       */
      this.insertParagraph = function () {
        var rng = range.create();
  
        // deleteContents on range.
        rng = rng.deleteContents();
  
        // Wrap range if it needs to be wrapped by paragraph
        rng = rng.wrapBodyInlineWithPara();
  
        // finding paragraph
        var splitRoot = dom.ancestor(rng.sc, dom.isPara);
  
        var nextPara;
        // on paragraph: split paragraph
        if (splitRoot) {
          nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
  
          var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
          emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
  
          $.each(emptyAnchors, function (idx, anchor) {
            dom.remove(anchor);
          });
        // no paragraph: insert empty paragraph
        } else {
          var next = rng.sc.childNodes[rng.so];
          nextPara = $(dom.emptyPara)[0];
          if (next) {
            rng.sc.insertBefore(nextPara, next);
          } else {
            rng.sc.appendChild(nextPara);
          }
        }
  
        range.create(nextPara, 0).normalize().select();
      };
  
    };
  
    return Typing;
  });
  