define([
  'summernote/base/core/agent',
  'summernote/base/core/dom',
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/range'
], function (agent, dom, func, list, range) {
  var AirPopover = function (context) {
    var self = this;

    var $document = $(document);
    var $editable = context.layoutInfo.editable;
    var editable = $editable[0];

    var options = context.options;

    var innerMouseUp;

    this.events = {
      'summernote.keyup summernote.mouseup summernote.scroll': function () {
        innerMouseUp = true;
        self.update();
      },
      'summernote.change summernote.dialog.shown': function () {
        self.update();
      },
      'summernote.focusout': function (we, e) {
        // [workaround] Firefox doesn't support relatedTarget on focusout
        //  - Ignore hide action on focus out in FF.
        if (agent.isFF) {
          return;
        }

        if (!e.relatedTarget) {
          self.hide();
        }

        self.lastRange = range.createFromSelection();
      }
    };

    $editable.on('mousedown', function () {
      $document.on('mouseup', function () {
        if (!innerMouseUp) {
          self.update();
        }

        innerMouseUp = false;
        $document.off('mouseup');
      });
    });

    this.shouldInitialize = function () {
      return options.airMode &&
        options.popover &&
        options.popover.air &&
        typeof options.popover.air.hide === 'function' &&
        typeof options.popover.air.update === 'function';
    };

    this.initialize = function () {
      this.fontInstalledMap = {};
    };

    this.destroy = function () {
      delete this.fontInstalledMap;
    };

    this.isFontInstalled = function (name) {
      if (!self.fontInstalledMap.hasOwnProperty(name)) {
        self.fontInstalledMap[name] = agent.isFontInstalled(name) ||
          list.contains(options.fontNamesIgnoreCheck, name);
      }

      return self.fontInstalledMap[name];
    };

    this.getAvailablesFont = function () {
      return options.fontNames.filter(self.isFontInstalled);
    };

    this.getLastRange = function () {
      return self.lastRange;
    };

    this.insertNode = function (node, rng, forceInline) {
      if (!$editable.is(':focus')) {
        $editable.focus();
      }
      rng = rng || self.lastRange || range.create(editable);
      var info = dom.splitPoint(rng.getStartPoint(), forceInline || dom.isInline(node));

      if (info.rightNode) {
        info.rightNode.parentNode.insertBefore(node, info.rightNode);
      } else {
        info.container.appendChild(node);
      }

      self.lastRange = range.createFromNodeAfter(node);
      self.lastRange.select();
    };

    this.moveCursorToEnd = function () {
      if (editable.lastChild || editable.lastElementChild) {
        range.createFromNodeAfter(editable.lastChild || editable.lastElementChild).select();
      }
    };

    this.update = function (force) {
      var styleInfo = context.invoke('editor.currentStyle');
      if (styleInfo.range && (!styleInfo.range.isCollapsed() || force)) {
        var rect = list.last(styleInfo.range.getClientRects());
        var bnd;
        if (rect) {
          bnd = func.rect2bnd(rect);
          options.popover.air.update(styleInfo, bnd);
        } else if (force) {
          options.popover.air.update(styleInfo, null);
        }
      } else {
        this.hide();
      }
    };

    this.hide = function () {
      options.popover.air.hide();
    };
  };

  return AirPopover;
});

@@ -2929,32 +2929,791 @@
       %7D%0A    %7D;%0A%0A
+    this.pasteHTML = function (markup, rng) %7B%0A      if (!$editable.is(':focus')) %7B%0A        $editable.focus();%0A      %7D%0A      rng = rng %7C%7C self.lastRange %7C%7C range.create(editable);%0A      var info = dom.splitPoint(rng.getStartPoint(), false);%0A%0A      var contentsContainer = $('%3Cdiv%3E%3C/div%3E').html(markup)%5B0%5D;%0A      var childNodes = list.from(contentsContainer.childNodes);%0A%0A      var contents = childNodes.map(function (childNode) %7B%0A        if (info.rightNode) %7B%0A          info.rightNode.parentNode.insertBefore(childNode, info.rightNode);%0A        %7D else %7B%0A          info.container.appendChild(childNode);%0A        %7D%0A        return childNode;%0A      %7D);%0A%0A      self.lastRange = range.createFromNodeAfter(list.last(contents));%0A      self.lastRange.select();%0A    %7D;%0A%0A
     this.update 

Add pasteHTML