table extension
@param {Editor} editor - editor instance
@ignore
437460
function tableExtension(editor) {
  const {eventManager} = editor;

  editor.toMarkOptions = editor.toMarkOptions || {};
  editor.toMarkOptions.renderer = toMarkRenderer;
  _bindEvents(eventManager);

  if (editor.isViewer()) {
    return;
  }

  const wwComponentManager = editor.wwEditor.componentManager;
  const popupTableUtils = editor.getUI().getPopupTableUtils();

  _addCommands(editor);
  _changeWysiwygManagers(wwComponentManager);

  if (popupTableUtils) {
    mergedTableUI.updateContextMenu(popupTableUtils, eventManager, wwComponentManager.getManager('tableSelection'));
  }
}
1289153
function getOnKeyDownListener( editor ) {
		var keystrokes = { 37: 1, 39: 1, 8: 1, 46: 1 };

		return function( evt ) {
			var keystroke = evt.data.getKeystroke();

			// Handle only left/right/del/bspace keys.
			if ( !keystrokes[ keystroke ] )
				return;

			var sel = editor.getSelection(),
				ranges = sel.getRanges(),
				range = ranges[ 0 ];

			// Handle only single range and it has to be collapsed.
			if ( ranges.length != 1 || !range.collapsed )
				return;

			var next = range[ keystroke < 38 ? 'getPreviousEditableNode' : 'getNextEditableNode' ]();

			if ( next && next.type == CKEDITOR.NODE_ELEMENT && next.getAttribute( 'contenteditable' ) == 'false' ) {
				editor.getSelection().fake( next );
				evt.data.preventDefault();
				evt.cancel();
			}
		};
	}
1221477
function( editor ) {
		editor.addCommand( 'removeFormat', CKEDITOR.plugins.removeformat.commands.removeformat );
		editor.ui.addButton && editor.ui.addButton( 'RemoveFormat', {
			label: editor.lang.removeformat.toolbar,
			command: 'removeFormat',
			toolbar: 'cleanup,10'
		} );
	}
604182
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);
      },
    });
  }
474712
function(oExtension, $Cell, aDefaultLabels, aDefaultDescriptions, aLabels, aDescriptions, sText, fAdapt) {
			ExtensionHelper.storeDefaultsBeforeCellModifications(oExtension, $Cell, aDefaultLabels, aDefaultDescriptions);
			var oCountChangeInfo = ExtensionHelper.updateRowColCount(oExtension);
			oExtension.getTable().$("cellacc").text(sText || " "); //set the custom text to the prepared hidden element

			if (fAdapt) { //Allow to adapt the labels / descriptions based on the changed row / column count
				fAdapt(aLabels, aDescriptions, oCountChangeInfo.rowChange, oCountChangeInfo.colChange, oCountChangeInfo.initial);
			}

			var sLabel = "";
			if (oCountChangeInfo.initial) {
				var oTable = oExtension.getTable();
				sLabel = oTable.getAriaLabelledBy().join(" ") + " " + oTable.getId() + "-ariacount";
				if (oTable.getSelectionMode() !== SelectionMode.None) {
					sLabel = sLabel + " " + oTable.getId() + "-ariaselection";
				}
			}

			if (aLabels && aLabels.length) {
				sLabel = sLabel + " " + aLabels.join(" ");
			}

			$Cell.attr({
				"aria-labelledby": sLabel ? sLabel : null,
				"aria-describedby": aDescriptions && aDescriptions.length ? aDescriptions.join(" ") : null
			});
		}
124258
function( editor ) {
			var commandName = 'pastetext';

			editor.addCommand( commandName, pasteTextCmd );

			editor.ui.addButton && editor.ui.addButton( 'PasteText', {
				label: editor.lang.pastetext.button,
				command: commandName,
				toolbar: 'clipboard,40'
			} );

			if ( editor.config.forcePasteAsPlainText ) {
				editor.on( 'beforePaste', function( evt ) {
					// Do NOT overwrite if HTML format is explicitly requested.
					// This allows pastefromword dominates over pastetext.
					if ( evt.data.type != 'html' )
						evt.data.type = 'text';
				} );
			}

			editor.on( 'pasteState', function( evt ) {
				editor.getCommand( commandName ).setState( evt.data );
			} );
		}
440415
function buildAddonTable(addons, enabledAddons) {
  var tbody = document.querySelector('.addonPicker tbody');

  // Remove all old content.
  while (tbody.firstChild) {
    tbody.firstChild.remove();
  }

  // Add empty row.
  if (!addons.length) {
    var tr = document.createElement('tr');
    tr.className = 'emptyRow';
    var td = document.createElement('td');
    td.innerText = 'No addons added.';
    tr.appendChild(td);
    tbody.appendChild(tr);
  }

  // Build the table.
  for (var n = 0; n < addons.length; n++) {
    var extension = addons[n];
    addExtensionRow(extension);
  }
  function addExtensionRow(extension) {
    var isEnabled = enabledAddons.indexOf(extension.url) >= 0;;

    var td = document.createElement('td');
    var input = document.createElement('input');
    input.type = 'checkbox';
    input.checked = isEnabled;
    td.appendChild(input);
    var span = document.createElement('span');
    span.innerText = extension.manifest.name;
    span.title = extension.url;
    td.appendChild(span);

    var remove = document.createElement('td');
    remove.className = 'remove';
    var removeImg = document.createElement('img');
    removeImg.title = 'Remove extension';
    remove.appendChild(removeImg);

    var tr = document.createElement('tr');
    tr.appendChild(td);
    tr.appendChild(remove);

    tbody.appendChild(tr);

    function changed() {
      _gaq.push(['_trackEvent', 'popup', 'addon_toggled']);

      port.postMessage({
        command: 'toggle_extension',
        enabled: input.checked,
        url: extension.url
      });
    };
    input.onchange = function() {
      changed();
    };
    span.onclick = function() {
      input.checked = !input.checked;
      changed();
    };

    remove.onclick = function() {
      _gaq.push(['_trackEvent', 'popup', 'addon_removed']);

      if (isEnabled) {
        port.postMessage({
          command: 'toggle_addon',
          enabled: false,
          url: extension.url
        });
      }
      port.postMessage({
        command: 'remove_addon',
        url: extension.url
      });
    };
  };
}
1154367
function( editor ) {
			if ( editor.blockless )
				return;

			var left = new justifyCommand( editor, 'justifyleft', 'left' ),
				center = new justifyCommand( editor, 'justifycenter', 'center' ),
				right = new justifyCommand( editor, 'justifyright', 'right' ),
				justify = new justifyCommand( editor, 'justifyblock', 'justify' );

			editor.addCommand( 'justifyleft', left );
			editor.addCommand( 'justifycenter', center );
			editor.addCommand( 'justifyright', right );
			editor.addCommand( 'justifyblock', justify );

			if ( editor.ui.addButton ) {
				editor.ui.addButton( 'JustifyLeft', {
					label: editor.lang.justify.left,
					command: 'justifyleft',
					toolbar: 'align,10'
				} );
				editor.ui.addButton( 'JustifyCenter', {
					label: editor.lang.justify.center,
					command: 'justifycenter',
					toolbar: 'align,20'
				} );
				editor.ui.addButton( 'JustifyRight', {
					label: editor.lang.justify.right,
					command: 'justifyright',
					toolbar: 'align,30'
				} );
				editor.ui.addButton( 'JustifyBlock', {
					label: editor.lang.justify.block,
					command: 'justifyblock',
					toolbar: 'align,40'
				} );
			}

			editor.on( 'dirChanged', onDirChanged );
		}
713667
function switchBorderColor(editor, flag) {
        var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color;
        for (var i = 0, node; node = tableArr[i++];) {
            var td = domUtils.getElementsByTagName(node, "td");
            if (td[0]) {
                if (flag) {
                    color = (td[0].style.borderColor).replace(/\s/g, "");
                    if (/(#ffffff)|(rgb\(255,255,255\))/ig.test(color))
                        domUtils.addClass(node, "noBorderTable")
                } else {
                    domUtils.removeClasses(node, "noBorderTable")
                }
            }

        }
    }
816508
function blockComment(editor) {
        editor = editor || EditorManager.getFocusedEditor();
        if (!editor) {
            return;
        }

        var edits = [],
            lineCommentSels = [];
        _.each(editor.getSelections(), function (sel) {
            var mode = editor.getModeForRange(sel.start, sel.end),
                edit = {edit: [], selection: [sel]}; // default edit in case we don't have a mode for this selection
            if (mode) {
                var language = editor.document.getLanguage().getLanguageForMode(mode.name || mode);

                if (language.hasBlockCommentSyntax()) {
                    // getLineCommentPrefixes always return an array, and will be empty if no line comment syntax is defined
                    edit = _getBlockCommentPrefixSuffixEdit(editor, language.getBlockCommentPrefix(), language.getBlockCommentSuffix(),
                                                            language.getLineCommentPrefixes(), sel);
                    if (!edit) {
                        // This is only null if the block comment code found that the selection is within a line-commented line.
                        // Add this to the list of line-comment selections we need to handle. Since edit is null, we'll skip
                        // pushing anything onto the edit list for this selection.
                        lineCommentSels.push(sel);
                    }
                }
            }
            if (edit) {
                edits.push(edit);
            }
        });

        // Handle any line-comment edits. It's okay if these are out-of-order with the other edits, since
        // they shouldn't overlap, and `doMultipleEdits()` will take care of sorting the edits so the
        // selections can be tracked appropriately.
        edits.push.apply(edits, _getLineCommentEdits(editor, lineCommentSels, "block"));

        editor.setSelections(editor.document.doMultipleEdits(edits));
    }
635230
function fixDom( evt ) {
		var editor = evt.editor,
			path = evt.data.path,
			blockLimit = path.blockLimit,
			selection = evt.data.selection,
			range = selection.getRanges()[ 0 ],
			selectionUpdateNeeded;

		if ( CKEDITOR.env.gecko || ( CKEDITOR.env.ie && CKEDITOR.env.needsBrFiller ) ) {
			var blockNeedsFiller = needsBrFiller( selection, path );
			if ( blockNeedsFiller ) {
				blockNeedsFiller.appendBogus();
				// IE tends to place selection after appended bogus, so we need to
				// select the original range (placed before bogus).
				selectionUpdateNeeded = CKEDITOR.env.ie;
			}
		}

		// When we're in block enter mode, a new paragraph will be established
		// to encapsulate inline contents inside editable. (#3657)
		// Don't autoparagraph if browser (namely - IE) incorrectly anchored selection
		// inside non-editable content. This happens e.g. if non-editable block is the only
		// content of editable.
		if ( shouldAutoParagraph( editor, path.block, blockLimit ) && range.collapsed && !range.getCommonAncestor().isReadOnly() ) {
			var testRng = range.clone();
			testRng.enlarge( CKEDITOR.ENLARGE_BLOCK_CONTENTS );
			var walker = new CKEDITOR.dom.walker( testRng );
			walker.guard = function( node ) {
				return !isNotEmpty( node ) ||
					node.type == CKEDITOR.NODE_COMMENT ||
					node.isReadOnly();
			};

			// 1. Inline content discovered under cursor;
			// 2. Empty editable.
			if ( !walker.checkForward() || testRng.checkStartOfBlock() && testRng.checkEndOfBlock() ) {
				var fixedBlock = range.fixBlock( true, editor.activeEnterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p' );

				// For IE<11, we should remove any filler node which was introduced before.
				if ( !CKEDITOR.env.needsBrFiller ) {
					var first = fixedBlock.getFirst( isNotEmpty );
					if ( first && isNbsp( first ) )
						first.remove();
				}

				selectionUpdateNeeded = 1;

				// Cancel this selection change in favor of the next (correct). (#6811)
				evt.cancel();
			}
		}

		if ( selectionUpdateNeeded )
			range.select();
	}
681196
function onEnter(
    event: *,
    change: Change,
    editor: *,
    opts: Options
): void | Change {
    event.preventDefault();
    const { selection, document } = change.value;
    const pos = TablePosition.create(opts, document, selection.startKey);

    if (
        !selection.hasFocusAtStartOf(pos.cell) &&
        !selection.hasFocusAtEndOf(pos.cell)
    ) {
        return undefined;
    }

    if (event.shiftKey) {
        return change
            .splitBlock()
            .setBlocks({ type: opts.typeContent, data: {} });
    }

    return insertRow(opts, change);
}
1089053
function colorSyntaxExtension(editor) {
  const {colorSyntax = {}} = editor.options;
  const {preset, useCustomSyntax = false} = colorSyntax;

  editor.eventManager.listen('convertorAfterMarkdownToHtmlConverted', html => {
    let replacement;

    if (!useCustomSyntax) {
      replacement = html;
    } else {
      replacement
                = html.replace(colorSyntaxRx, (matched, p1, p2) => makeHTMLColorSyntaxAndTextRange(p2, p1).result);
    }

    return replacement;
  });

  editor.eventManager.listen('convertorAfterHtmlToMarkdownConverted', markdown => {
    const findRx = useCustomSyntax ? colorHtmlCompleteRx : colorHtmlRx;

    return markdown.replace(findRx, (founded, color, text) => {
      let replacement;

      if (color.match(decimalColorRx)) {
        color = changeDecColorsToHex(color);
      }

      if (!useCustomSyntax) {
        replacement = founded.replace(/ ?class="colour" ?/g, ' ').replace(decimalColorRx, color);
      } else {
        replacement = makeCustomColorSyntaxAndTextRange(text, color).result;
      }

      return replacement;
    });
  });

  if (!editor.isViewer() && editor.getUI().name === 'default') {
    editor.addCommand('markdown', {
      name: 'color',
      exec(mde, color) {
        const cm = mde.getEditor();
        const rangeFrom = cm.getCursor('from');
        const rangeTo = cm.getCursor('to');
        let replacedText;
        let replacedFrom;

        if (!color) {
          return;
        }

        if (!useCustomSyntax) {
          ({result: replacedText, from: replacedFrom}
                        = makeHTMLColorSyntaxAndTextRange(cm.getSelection(), color));
          cm.replaceSelection(replacedText);
        } else {
          ({result: replacedText, from: replacedFrom}
                        = makeCustomColorSyntaxAndTextRange(cm.getSelection(), color));
          cm.replaceSelection(replacedText);
        }

        cm.setSelection({
          line: rangeFrom.line,
          ch: rangeFrom.ch + replacedFrom
        }, {
          line: rangeTo.line,
          ch: rangeFrom.line === rangeTo.line ? rangeTo.ch + replacedFrom : rangeTo.ch
        });

        mde.focus();
      }
    });

    editor.addCommand('wysiwyg', {
      name: 'color',
      exec(wwe, color) {
        if (!color) {
          return;
        }

        const sq = wwe.getEditor();
        const tableSelectionManager = wwe.componentManager.getManager('tableSelection');
        if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) {
          tableSelectionManager.styleToSelectedCells(styleColor, color);

          const range = sq.getSelection();
          range.collapse(true);
          sq.setSelection(range);
        } else {
          styleColor(sq, color);
        }
      }
    });

    initUI(editor, preset);
  }
}
1121519
function fixCut() {
			if ( !CKEDITOR.env.ie || CKEDITOR.env.quirks )
				return;

			var sel = editor.getSelection(),
				control, range, dummy;

			if ( ( sel.getType() == CKEDITOR.SELECTION_ELEMENT ) && ( control = sel.getSelectedElement() ) ) {
				range = sel.getRanges()[ 0 ];
				dummy = editor.document.createText( '' );
				dummy.insertBefore( control );
				range.setStartBefore( dummy );
				range.setEndAfter( control );
				sel.selectRanges( [ range ] );

				// Clear up the fix if the paste wasn't succeeded.
				setTimeout( function() {
					// Element still online?
					if ( control.getParent() ) {
						dummy.remove();
						sel.selectElement( control );
					}
				}, 0 );
			}
		}
366022
function toggleEditorClass(editor, enabled) {
	const view = atom.views.getView(editor);
	if (view) {
		view.classList.toggle('has-emmet-abbreviation', enabled);
	}
}
1062559
function( editor ) {
		var cmd = new CKEDITOR.dialogCommand( 'colordialog' );
		cmd.editorFocus = false;

		editor.addCommand( 'colordialog', cmd );

		CKEDITOR.dialog.add( 'colordialog', this.path + 'dialogs/colordialog.js' );

		/**
		 * Open up color dialog and to receive the selected color.
		 *
		 * @param {Function} callback The callback when color dialog is closed
		 * @param {String} callback.color The color value received if selected on the dialog.
		 * @param [scope] The scope in which the callback will be bound.
		 * @member CKEDITOR.editor
		 */
		editor.getColorFromDialog = function( callback, scope ) {
			var onClose = function( evt ) {
				releaseHandlers( this );
				var color = evt.name == 'ok' ? this.getValueOf( 'picker', 'selectedColor' ) : null;
				callback.call( scope, color );
			};
			var releaseHandlers = function( dialog ) {
				dialog.removeListener( 'ok', onClose );
				dialog.removeListener( 'cancel', onClose );
			};
			var bindToDialog = function( dialog ) {
				dialog.on( 'ok', onClose );
				dialog.on( 'cancel', onClose );
			};

			editor.execCommand( 'colordialog' );

			if ( editor._.storedDialogs && editor._.storedDialogs.colordialog )
				bindToDialog( editor._.storedDialogs.colordialog );
			else {
				CKEDITOR.on( 'dialogDefinition', function( e ) {
					if ( e.data.name != 'colordialog' )
						return;

					var definition = e.data.definition;

					e.removeListener();
					definition.onLoad = CKEDITOR.tools.override( definition.onLoad,
						function( orginal ) {
							return function() {
								bindToDialog( this );
								definition.onLoad = orginal;
								if ( typeof orginal == 'function' )
									orginal.call( this );
							};
						} );
				} );
			}
		};


	}
1201406
function scrollSyncExtension(editor) {
  const className = 'tui-scrollsync';
  const i18n = editor.i18n;
  const TOOL_TIP = {
    active: i18n.get('Auto scroll enabled'),
    inactive: i18n.get('Auto scroll disabled')
  };

  if (editor.isViewer()) {
    return;
  }

  const cm = editor.getCodeMirror();
  const sectionManager = new SectionManager(cm, editor.preview);
  const scrollManager = new ScrollManager(sectionManager, cm, editor.preview.$el);

  let isScrollable = false;
  let isActive = true;
  let button;
  let $divider;

  // UI
  if (editor.getUI().name === 'default') {
    const toolbar = editor.getUI().getToolbar();

    toolbar.addItem('divider');
    toolbar.addItem({
      type: 'button',
      options: {
        className,
        command: 'scrollSyncToggle',
        tooltip: TOOL_TIP.active,
        $el: $(`<button class="active ${className}" type="button"></button>`)
      }
    });
    const items = toolbar.getItems();
    $divider = items[items.length - 2].$el;
    button = items[items.length - 1];

    changeButtonVisiblityStateIfNeed();
    // hide scroll follow button in wysiwyg
    editor.on('changeMode', changeButtonVisiblityStateIfNeed);
    editor.on('changePreviewStyle', changeButtonVisiblityStateIfNeed);

    // Commands
    editor.addCommand('markdown', {
      name: 'scrollSyncToggle',
      exec() {
        isActive = !isActive;
        button._onOut();
        if (isActive) {
          button.$el.addClass('active');
          button.setTooltip(TOOL_TIP.active);
        } else {
          button.$el.removeClass('active');
          button.setTooltip(TOOL_TIP.inactive);
        }
        button._onOver();
      }
    });
  }

  // Events
  cm.on('change', () => {
    isScrollable = false;
    sectionManager.makeSectionList();
  });

  /**
   * change button visiblity state
   */
  function changeButtonVisiblityStateIfNeed() {
    if (editor.mdPreviewStyle === 'vertical' && editor.currentMode === 'markdown') {
      button.$el.show();
      $divider.show();
    } else {
      button.$el.hide();
      $divider.hide();
    }
  }

  editor.on('previewRenderAfter', () => {
    sectionManager.sectionMatch();
    if (isActive) {
      scrollManager.syncPreviewScrollTopToMarkdown();
    }
    isScrollable = true;
  });

  editor.eventManager.listen('scroll', event => {
    if (!isActive) {
      return;
    }

    if (isScrollable && editor.preview.isVisible()) {
      if (event.source === 'markdown' && !scrollManager.isMarkdownScrollEventBlocked) {
        scrollManager.syncPreviewScrollTopToMarkdown();
      } else if (event.source === 'preview' && !scrollManager.isPreviewScrollEventBlocked) {
        scrollManager.syncMarkdownScrollTopToPreview();
      }
    } else {
      scrollManager.saveScrollInfo();
    }
  });
}