docs: function(editor) {
      if (editor.blockless) return;
  
      var config = editor.config,
        lang = editor.lang.format;
  
      // Gets the list of tags from the settings.
      var tags = config.format_tags.split(';');
  
      // Create style objects for all defined styles.
      var styles = {},
        stylesCount = 0,
        allowedContent = [];
      for (var i = 0; i < tags.length; i++) {
        var tag = tags[i];
        // @EDIT: formatting tag name here, try to handle custom-elements
        var formatted_tag = tag.replace('-', '_');
        var style = new CKEDITOR.style(config['format_' + formatted_tag]);
        if (!editor.filter.customConfig || editor.filter.check(style)) {
          stylesCount++;
          styles[formatted_tag] = style;
          styles[formatted_tag]._.enterMode = editor.config.enterMode;
          allowedContent.push(style);
        }
      }
  
      // Hide entire combo when all formats are rejected.
      if (stylesCount === 0) return;
  
      editor.ui.addRichCombo('Format', {
        label: lang.label,
        title: lang.panelTitle,
        toolbar: 'styles,20',
        allowedContent: allowedContent,
  
        panel: {
          css: [CKEDITOR.skin.getPath('editor')].concat(config.contentsCss),
          multiSelect: false,
          attributes: { 'aria-label': lang.panelTitle },
        },
  
        init: function() {
          this.startGroup(lang.panelTitle);
  
          for (var tag in styles) {
            var label = lang['tag_' + tag];
  
            // Add the tag entry to the panel list.
            this.add(tag, styles[tag].buildPreview(label), label);
          }
        },
  
        onClick: function(value) {
          editor.focus();
          editor.fire('saveSnapshot');
  
          var style = styles[value],
            elementPath = editor.elementPath();
  
          // Always apply style, do not allow to toggle it by clicking on corresponding list item (#584).
          if (!style.checkActive(elementPath, editor)) {
            editor.applyStyle(style);
          }
  
          // Save the undo snapshot after all changes are affected. (https://dev.ckeditor.com/ticket/4899)
          setTimeout(function() {
            editor.fire('saveSnapshot');
          }, 0);
        },
  
        onRender: function() {
          editor.on(
            'selectionChange',
            function(ev) {
              var currentTag = this.getValue(),
                elementPath = ev.data.path;
  
              this.refresh();
  
              for (var tag in styles) {
                if (styles[tag].checkActive(elementPath, editor)) {
                  if (tag != currentTag)
                    this.setValue(tag, editor.lang.format['tag_' + tag]);
                  return;
                }
              }
  
              // If no styles match, just empty it.
              this.setValue('');
            },
            this,
          );
        },
  
        onOpen: function() {
          this.showAll();
          for (var name in styles) {
            var style = styles[name];
  
            // Check if that style is enabled in activeFilter.
            if (!editor.activeFilter.check(style)) this.hideItem(name);
          }
        },
  
        refresh: function() {
          var elementPath = editor.elementPath();
  
          if (!elementPath) return;
  
          // Check if element path contains 'p' element.
          if (!elementPath.isContextFor('p')) {
            this.setState(CKEDITOR.TRISTATE_DISABLED);
            return;
          }
  
          // Check if there is any available style.
          for (var name in styles) {
            if (editor.activeFilter.check(styles[name])) return;
          }
          this.setState(CKEDITOR.TRISTATE_DISABLED);
        },
      });
    }