define([
  'jquery',
  'summernote/base/core/agent'
], function ($, agent) {
  var HelpDialog = function (context) {
    var self = this;
    var ui = $.summernote.ui;

    var $editor = context.layoutInfo.editor;
    var options = context.options;
    var lang = options.langInfo;

    this.createShortCutList = function () {
      var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];

      var $list = $('<div />');

      Object.keys(keyMap).forEach(function (keyString) {
        var $row = $('<div class="help-list-item"/>');

        var command = keyMap[keyString];
        var str = context.memo('help.' + command) ? context.memo('help.' + command) : command;
        var $keyString = $('<label />').css({
          'width': 180,
          'max-width': 200,
          'margin-right': 10
        }).html(keyString);
        var $description = $('<span />').html(str);

        $row.html($keyString).append($description);

        $list.append($row);
      });

      return $list.html();
    };

    this.initialize = function () {
      var $container = options.dialogsInBody ? $(document.body) : $editor;

      var body = [
        '<p class="text-center">',
        '<a href="//summernote.org/" target="_blank">Summernote @VERSION</a> · ',
        '<a href="//github.com/summernote/summernote" target="_blank">Project</a> · ',
        '<a href="//github.com/summernote/summernote/issues" target="_blank">Issues</a>',
        '</p>'
      ].join('');

      this.$dialog = ui.dialog({
        title: lang.options.help,
        body: this.createShortCutList(),
        footer: body,
        callback: function ($node) {
          $node.find('.modal-body').css({
            'max-height': 300,
            'overflow': 'scroll'
          });
        }
      }).render().appendTo($container);
    };

    this.destroy = function () {
      ui.hideDialog(this.$dialog);
      this.$dialog.remove();
    };

    /**
     * show help dialog
     *
     * @return {Promise}
     */
    this.showHelpDialog = function () {
      return $.Deferred(function (deferred) {
        ui.onDialogHidden(self.$dialog, function () {
          context.triggerEvent('dialog.shown');
          deferred.resolve();
        });
        ui.showDialog(self.$dialog);
      }).promise();
    };

    this.show = function () {
      context.invoke('editor.saveRange');
      this.showHelpDialog().then(function () {
        context.invoke('editor.restoreRange');
      });
    };
  };

  return HelpDialog;
});

@@ -387,47 +387,20 @@
 '%5D;%0A
-%0A
       
-var $list = $('%3Cdiv /%3E');%0A%0A     
+return
  Obj
@@ -420,15 +420,11 @@
 ap).
-forEach
+map
 (fun
@@ -437,17 +437,46 @@
 (key
-String) %7B
+) %7B%0A        var command = keyMap%5Bkey%5D;
 %0A   
@@ -498,16 +498,21 @@
  $('%3Cdiv
+%3E%3Cdiv
  class=%22
@@ -532,21 +532,26 @@
 m%22/%3E
+%3C/div%3E
 ');%0A
-%0A
         
 var 
@@ -550,172 +550,59 @@
     
-var command = keyMap%5BkeyString%5D;%0A        var str = context.memo('help.' + command) ? context.memo('help.' + command) : command;%0A        var $keyString = $('%3C
+$row.append($('%3Clabel%3E%3Ckbd%3E' + key + '%3C/kdb%3E%3C/
 label
- /
 %3E').
@@ -648,115 +648,51 @@
  'ma
-x-width': 200,%0A          'margin-right': 10%0A        %7D).html(keyString);%0A        var $description = 
+rgin-right': 10%0A        %7D)).append(
 $('%3Cspan
  /%3E'
@@ -687,17 +687,16 @@
 $('%3Cspan
- 
 /%3E').htm
@@ -701,76 +701,62 @@
 tml(
-str);%0A%0A        $row.html($keyString).append($description
+context.memo('help.' + command) %7C%7C command)
 );%0A
-%0A
         
 $lis
@@ -755,63 +755,44 @@
     
-$list.append($row);%0A      %7D);%0A%0A      return $list.html(
+return $row.html();%0A      %7D).join(''
 );%0A 

Use the `<kbd>` for keyboard shortcut in help dialog.