]> git.immae.eu Git - perso/Immae/Projets/packagist/piedsjaloux-ckeditor-component.git/blobdiff - sources/core/tools.js
Add oembed
[perso/Immae/Projets/packagist/piedsjaloux-ckeditor-component.git] / sources / core / tools.js
index ae5b4d0ff3a9c18144ab88dfbd73f000b7775657..a4b736d647700bb6b59f3701a0f19b398f14dc9c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md or http://ckeditor.com/license
  */
 
                        } );
                },
 
+               /**
+                * Normalizes hexadecimal notation so that the color string is always 6 characters long and lowercase.
+                *
+                * @param {String} styleText The style data (or just a string containing hex colors) to be converted.
+                * @returns {String} The style data with hex colors normalized.
+                */
+               normalizeHex: function( styleText ) {
+                       return styleText.replace( /#(([0-9a-f]{3}){1,2})($|;|\s+)/gi, function( match, hexColor, hexColorPart, separator ) {
+                               var normalizedHexColor = hexColor.toLowerCase();
+                               if ( normalizedHexColor.length == 3 ) {
+                                       var parts = normalizedHexColor.split( '' );
+                                       normalizedHexColor = [ parts[ 0 ], parts[ 0 ], parts[ 1 ], parts[ 1 ], parts[ 2 ], parts[ 2 ] ].join( '' );
+                               }
+                               return '#' + normalizedHexColor + separator;
+                       } );
+               },
+
                /**
                 * Turns inline style text properties into one hash.
                 *
                                // Injects the style in a temporary span object, so the browser parses it,
                                // retrieving its final format.
                                var temp = new CKEDITOR.dom.element( 'span' );
-                               temp.setAttribute( 'style', styleText );
-                               styleText = CKEDITOR.tools.convertRgbToHex( temp.getAttribute( 'style' ) || '' );
+                               styleText = temp.setAttribute( 'style', styleText ).getAttribute( 'style' ) || '';
+                       }
+
+                       // Normalize colors.
+                       if ( styleText ) {
+                               styleText = CKEDITOR.tools.normalizeHex( CKEDITOR.tools.convertRgbToHex( styleText ) );
                        }
 
-                       // IE will leave a single semicolon when failed to parse the style text. (#3891)
+                       // IE will leave a single semicolon when failed to parse the style text. (http://dev.ckeditor.com/ticket/3891)
                        if ( !styleText || styleText == ';' )
                                return retval;
 
                        styleText.replace( /"/g, '"' ).replace( /\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g, function( match, name, value ) {
                                if ( normalize ) {
                                        name = name.toLowerCase();
-                                       // Normalize font-family property, ignore quotes and being case insensitive. (#7322)
-                                       // http://www.w3.org/TR/css3-fonts/#font-family-the-font-family-property
+                                       // Drop extra whitespacing from font-family.
                                        if ( name == 'font-family' )
-                                               value = value.toLowerCase().replace( /["']/g, '' ).replace( /\s*,\s*/g, ',' );
+                                               value = value.replace( /\s*,\s*/g, ',' );
                                        value = CKEDITOR.tools.trim( value );
                                }
 
                        return false;
                },
 
+               /**
+                * Converts a keystroke to its string representation. Returns an object with two fields:
+                *
+                * * `display` – A string that should be used for visible labels.
+                * For Mac devices it uses `⌥` for `ALT`, `⇧` for `SHIFT` and `⌘` for `COMMAND`.
+                * * `aria` – A string that should be used for ARIA descriptions.
+                * It does not use special characters such as `⌥`, `⇧` or `⌘`.
+                *
+                *              var lang = editor.lang.common.keyboard;
+                *              var shortcut = CKEDITOR.tools.keystrokeToString( lang, CKEDITOR.CTRL + 88 );
+                *              console.log( shortcut.display ); // 'CTRL + X', on Mac '⌘ + X'.
+                *              console.log( shortcut.aria ); // 'CTRL + X', on Mac 'COMMAND + X'.
+                *
+                * @since 4.6.0
+                * @param {Object} lang A language object with the key name translation.
+                * @param {Number} keystroke The keystroke to convert.
+                * @returns {{display: String, aria: String}}
+                */
+               keystrokeToString: function( lang, keystroke ) {
+                       var special = keystroke & 0xFF0000,
+                               key = keystroke & 0x00FFFF,
+                               isMac = CKEDITOR.env.mac,
+                               CTRL = 17,
+                               CMD = 224,
+                               ALT = 18,
+                               SHIFT = 16,
+                               display = [],
+                               aria = [];
+
+
+                       if ( special & CKEDITOR.CTRL ) {
+                               display.push( isMac ? '⌘' : lang[ CTRL ] );
+                               aria.push( isMac ? lang[ CMD ] : lang[ CTRL ] );
+                       }
+
+                       if ( special & CKEDITOR.ALT ) {
+                               display.push( isMac ? '⌥' : lang[ ALT ] );
+                               aria.push( lang[ ALT ] );
+                       }
+
+                       if ( special & CKEDITOR.SHIFT ) {
+                               display.push( isMac ? '⇧' : lang[ SHIFT ] );
+                               aria.push( lang[ SHIFT ] );
+                       }
+
+                       if ( key ) {
+                               if ( lang[ key ] ) {
+                                       display.push( lang[ key ] );
+                                       aria.push( lang[ key ] );
+                               } else {
+                                       display.push( String.fromCharCode( key ) );
+                                       aria.push( String.fromCharCode( key ) );
+                               }
+                       }
+
+                       return {
+                               display: display.join( '+' ),
+                               aria: aria.join( '+' )
+                       };
+               },
+
                /**
                 * The data URI of a transparent image. May be used e.g. in HTML as an image source or in CSS in `url()`.
                 *
                        }
 
                        return token;
+               },
+
+               /**
+                * Returns an escaped CSS selector. `CSS.escape()` is used if defined, leading digit is escaped otherwise.
+                *
+                * @since 4.5.10
+                * @param {String} selector A CSS selector to escape.
+                * @returns {String} An escaped selector.
+                */
+               escapeCss: function( selector ) {
+                       // Invalid input.
+                       if ( !selector ) {
+                               return '';
+                       }
+
+                       // CSS.escape() can be used.
+                       if ( window.CSS && CSS.escape ) {
+                               return CSS.escape( selector );
+                       }
+
+                       // Simple leading digit escape.
+                       if ( !isNaN( parseInt( selector.charAt( 0 ), 10 ) ) ) {
+                               return '\\3' + selector.charAt( 0 ) + ' ' + selector.substring( 1, selector.length );
+                       }
+
+                       return selector;
+               },
+
+               /**
+                * Detects which mouse button generated a given DOM event.
+                *
+                * @since 4.7.3
+                * @param {CKEDITOR.dom.event} evt DOM event.
+                * @returns {Number|Boolean} Returns a number indicating the mouse button or `false`
+                * if the mouse button cannot be determined.
+                */
+               getMouseButton: function( evt ) {
+                       var evtData = evt.data,
+                               domEvent = evtData && evtData.$;
+
+                       if ( !( evtData && domEvent ) ) {
+                               // Added in case when there's no data available. That's the case in some unit test in built version which
+                               // mock event but doesn't put data object.
+                               return false;
+                       }
+
+                       if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
+                               if ( domEvent.button === 4 ) {
+                                       return CKEDITOR.MOUSE_BUTTON_MIDDLE;
+                               } else if ( domEvent.button === 1 ) {
+                                       return CKEDITOR.MOUSE_BUTTON_LEFT;
+                               } else {
+                                       return CKEDITOR.MOUSE_BUTTON_RIGHT;
+                               }
+                       }
+
+                       return domEvent.button;
+               },
+
+               /**
+                * A set of functions for operations on styles.
+                *
+                * @property {CKEDITOR.tools.style}
+                */
+               style: {
+                       /**
+                        * Methods to parse miscellaneous CSS properties.
+                        *
+                        * @property {CKEDITOR.tools.style.parse}
+                        * @member CKEDITOR.tools.style
+                        */
+                       parse: {
+                               // Color list based on https://www.w3.org/TR/css-color-4/#named-colors.
+                               _colors: {
+                                       aliceblue: '#F0F8FF',
+                                       antiquewhite: '#FAEBD7',
+                                       aqua: '#00FFFF',
+                                       aquamarine: '#7FFFD4',
+                                       azure: '#F0FFFF',
+                                       beige: '#F5F5DC',
+                                       bisque: '#FFE4C4',
+                                       black: '#000000',
+                                       blanchedalmond: '#FFEBCD',
+                                       blue: '#0000FF',
+                                       blueviolet: '#8A2BE2',
+                                       brown: '#A52A2A',
+                                       burlywood: '#DEB887',
+                                       cadetblue: '#5F9EA0',
+                                       chartreuse: '#7FFF00',
+                                       chocolate: '#D2691E',
+                                       coral: '#FF7F50',
+                                       cornflowerblue: '#6495ED',
+                                       cornsilk: '#FFF8DC',
+                                       crimson: '#DC143C',
+                                       cyan: '#00FFFF',
+                                       darkblue: '#00008B',
+                                       darkcyan: '#008B8B',
+                                       darkgoldenrod: '#B8860B',
+                                       darkgray: '#A9A9A9',
+                                       darkgreen: '#006400',
+                                       darkgrey: '#A9A9A9',
+                                       darkkhaki: '#BDB76B',
+                                       darkmagenta: '#8B008B',
+                                       darkolivegreen: '#556B2F',
+                                       darkorange: '#FF8C00',
+                                       darkorchid: '#9932CC',
+                                       darkred: '#8B0000',
+                                       darksalmon: '#E9967A',
+                                       darkseagreen: '#8FBC8F',
+                                       darkslateblue: '#483D8B',
+                                       darkslategray: '#2F4F4F',
+                                       darkslategrey: '#2F4F4F',
+                                       darkturquoise: '#00CED1',
+                                       darkviolet: '#9400D3',
+                                       deeppink: '#FF1493',
+                                       deepskyblue: '#00BFFF',
+                                       dimgray: '#696969',
+                                       dimgrey: '#696969',
+                                       dodgerblue: '#1E90FF',
+                                       firebrick: '#B22222',
+                                       floralwhite: '#FFFAF0',
+                                       forestgreen: '#228B22',
+                                       fuchsia: '#FF00FF',
+                                       gainsboro: '#DCDCDC',
+                                       ghostwhite: '#F8F8FF',
+                                       gold: '#FFD700',
+                                       goldenrod: '#DAA520',
+                                       gray: '#808080',
+                                       green: '#008000',
+                                       greenyellow: '#ADFF2F',
+                                       grey: '#808080',
+                                       honeydew: '#F0FFF0',
+                                       hotpink: '#FF69B4',
+                                       indianred: '#CD5C5C',
+                                       indigo: '#4B0082',
+                                       ivory: '#FFFFF0',
+                                       khaki: '#F0E68C',
+                                       lavender: '#E6E6FA',
+                                       lavenderblush: '#FFF0F5',
+                                       lawngreen: '#7CFC00',
+                                       lemonchiffon: '#FFFACD',
+                                       lightblue: '#ADD8E6',
+                                       lightcoral: '#F08080',
+                                       lightcyan: '#E0FFFF',
+                                       lightgoldenrodyellow: '#FAFAD2',
+                                       lightgray: '#D3D3D3',
+                                       lightgreen: '#90EE90',
+                                       lightgrey: '#D3D3D3',
+                                       lightpink: '#FFB6C1',
+                                       lightsalmon: '#FFA07A',
+                                       lightseagreen: '#20B2AA',
+                                       lightskyblue: '#87CEFA',
+                                       lightslategray: '#778899',
+                                       lightslategrey: '#778899',
+                                       lightsteelblue: '#B0C4DE',
+                                       lightyellow: '#FFFFE0',
+                                       lime: '#00FF00',
+                                       limegreen: '#32CD32',
+                                       linen: '#FAF0E6',
+                                       magenta: '#FF00FF',
+                                       maroon: '#800000',
+                                       mediumaquamarine: '#66CDAA',
+                                       mediumblue: '#0000CD',
+                                       mediumorchid: '#BA55D3',
+                                       mediumpurple: '#9370DB',
+                                       mediumseagreen: '#3CB371',
+                                       mediumslateblue: '#7B68EE',
+                                       mediumspringgreen: '#00FA9A',
+                                       mediumturquoise: '#48D1CC',
+                                       mediumvioletred: '#C71585',
+                                       midnightblue: '#191970',
+                                       mintcream: '#F5FFFA',
+                                       mistyrose: '#FFE4E1',
+                                       moccasin: '#FFE4B5',
+                                       navajowhite: '#FFDEAD',
+                                       navy: '#000080',
+                                       oldlace: '#FDF5E6',
+                                       olive: '#808000',
+                                       olivedrab: '#6B8E23',
+                                       orange: '#FFA500',
+                                       orangered: '#FF4500',
+                                       orchid: '#DA70D6',
+                                       palegoldenrod: '#EEE8AA',
+                                       palegreen: '#98FB98',
+                                       paleturquoise: '#AFEEEE',
+                                       palevioletred: '#DB7093',
+                                       papayawhip: '#FFEFD5',
+                                       peachpuff: '#FFDAB9',
+                                       peru: '#CD853F',
+                                       pink: '#FFC0CB',
+                                       plum: '#DDA0DD',
+                                       powderblue: '#B0E0E6',
+                                       purple: '#800080',
+                                       rebeccapurple: '#663399',
+                                       red: '#FF0000',
+                                       rosybrown: '#BC8F8F',
+                                       royalblue: '#4169E1',
+                                       saddlebrown: '#8B4513',
+                                       salmon: '#FA8072',
+                                       sandybrown: '#F4A460',
+                                       seagreen: '#2E8B57',
+                                       seashell: '#FFF5EE',
+                                       sienna: '#A0522D',
+                                       silver: '#C0C0C0',
+                                       skyblue: '#87CEEB',
+                                       slateblue: '#6A5ACD',
+                                       slategray: '#708090',
+                                       slategrey: '#708090',
+                                       snow: '#FFFAFA',
+                                       springgreen: '#00FF7F',
+                                       steelblue: '#4682B4',
+                                       tan: '#D2B48C',
+                                       teal: '#008080',
+                                       thistle: '#D8BFD8',
+                                       tomato: '#FF6347',
+                                       turquoise: '#40E0D0',
+                                       violet: '#EE82EE',
+                                       wheat: '#F5DEB3',
+                                       white: '#FFFFFF',
+                                       whitesmoke: '#F5F5F5',
+                                       yellow: '#FFFF00',
+                                       yellowgreen: '#9ACD32'
+                               },
+
+                               _borderStyle: [
+                                       'none',
+                                       'hidden',
+                                       'dotted',
+                                       'dashed',
+                                       'solid',
+                                       'double',
+                                       'groove',
+                                       'ridge',
+                                       'inset',
+                                       'outset'
+                               ],
+
+                               _widthRegExp: /^(thin|medium|thick|[\+-]?\d+(\.\d+)?[a-z%]+|[\+-]?0+(\.0+)?|\.\d+[a-z%]+)$/,
+
+                               _rgbaRegExp: /rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi,
+
+                               _hslaRegExp: /hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi,
+
+                               /**
+                                * Parses the `value` used as a `background` property shorthand and returns information as an object.
+                                *
+                                * **Note:** Currently only the `color` property is extracted. Any other parts will go into the `unprocessed` property.
+                                *
+                                *              var background = CKEDITOR.tools.style.parse.background( '#0C0 url(foo.png)' );
+                                *              console.log( background );
+                                *              // Logs: { color: '#0C0', unprocessed: 'url(foo.png)' }
+                                *
+                                * @param {String} value The value of the `background` property.
+                                * @returns {Object} An object with information extracted from the background.
+                                * @returns {String} return.color The **first** color value found. The color format remains the same as in input.
+                                * @returns {String} return.unprocessed The remaining part of the `value` that has not been processed.
+                                * @member CKEDITOR.tools.style.parse
+                                */
+                               background: function( value ) {
+                                       var ret = {},
+                                               colors = this._findColor( value );
+
+                                       if ( colors.length ) {
+                                               ret.color = colors[ 0 ];
+
+                                               CKEDITOR.tools.array.forEach( colors, function( colorToken ) {
+                                                       value = value.replace( colorToken, '' );
+                                               } );
+                                       }
+
+                                       value = CKEDITOR.tools.trim( value );
+
+                                       if ( value ) {
+                                               // If anything was left unprocessed include it as unprocessed part.
+                                               ret.unprocessed = value;
+                                       }
+
+                                       return ret;
+                               },
+
+                               /**
+                                * Parses the `margin` CSS property shorthand format.
+                                *
+                                *              console.log( CKEDITOR.tools.parse.margin( '3px 0 2' ) );
+                                *              // Logs: { top: "3px", right: "0", bottom: "2", left: "0" }
+                                *
+                                * @param {String} value The `margin` property value.
+                                * @returns {Object}
+                                * @returns {Number} return.top Top margin.
+                                * @returns {Number} return.right Right margin.
+                                * @returns {Number} return.bottom Bottom margin.
+                                * @returns {Number} return.left Left margin.
+                                * @member CKEDITOR.tools.style.parse
+                                */
+                               margin: function( value ) {
+                                       var ret = {};
+
+                                       var widths = value.match( /(?:\-?[\.\d]+(?:%|\w*)|auto|inherit|initial|unset)/g ) || [ '0px' ];
+
+                                       switch ( widths.length ) {
+                                               case 1:
+                                                       mapStyles( [ 0, 0, 0, 0 ] );
+                                                       break;
+                                               case 2:
+                                                       mapStyles( [ 0, 1, 0, 1 ] );
+                                                       break;
+                                               case 3:
+                                                       mapStyles( [ 0, 1, 2, 1 ] );
+                                                       break;
+                                               case 4:
+                                                       mapStyles( [ 0, 1, 2, 3 ] );
+                                                       break;
+                                       }
+
+                                       function mapStyles( map ) {
+                                               ret.top = widths[ map[ 0 ] ];
+                                               ret.right = widths[ map[ 1 ] ];
+                                               ret.bottom = widths[ map[ 2 ] ];
+                                               ret.left = widths[ map[ 3 ] ];
+                                       }
+
+                                       return ret;
+                               },
+
+                               /**
+                                * Parses the `border` CSS property shorthand format.
+                                * This CSS property does not support inheritance (https://www.w3.org/TR/css3-background/#the-border-shorthands).
+                                *
+                                *              console.log( CKEDITOR.tools.style.parse.border( '3px solid #ffeedd' ) );
+                                *              // Logs: { width: "3px", style: "solid", color: "#ffeedd" }
+                                *
+                                * @param {String} value The `border` property value.
+                                * @returns {Object}
+                                * @returns {String} return.width The border-width attribute.
+                                * @returns {String} return.style The border-style attribute.
+                                * @returns {String} return.color The border-color attribute.
+                                * @member CKEDITOR.tools.style.parse
+                                */
+                               border: function( value ) {
+                                       var ret = {},
+                                               input = value.split( /\s+/ );
+
+                                       CKEDITOR.tools.array.forEach( input, function( val ) {
+                                               if ( !ret.color ) {
+                                                       var parseColor = CKEDITOR.tools.style.parse._findColor( val );
+                                                       if ( parseColor.length ) {
+                                                               ret.color = parseColor[ 0 ];
+                                                               return;
+                                                       }
+                                               }
+
+                                               if ( !ret.style ) {
+                                                       if ( CKEDITOR.tools.indexOf( CKEDITOR.tools.style.parse._borderStyle, val ) !== -1 ) {
+                                                               ret.style = val;
+                                                               return;
+                                                       }
+                                               }
+
+                                               if ( !ret.width ) {
+                                                       if ( CKEDITOR.tools.style.parse._widthRegExp.test( val ) ) {
+                                                               ret.width = val;
+                                                               return;
+                                                       }
+                                               }
+
+                                       } );
+                                       return ret;
+                               },
+
+                               /**
+                                * Searches the `value` for any CSS color occurrences and returns it.
+                                *
+                                * @private
+                                * @param {String} value
+                                * @returns {String[]} An array of matched results.
+                                * @member CKEDITOR.tools.style.parse
+                                */
+                               _findColor: function( value ) {
+                                       var ret = [],
+                                               arrayTools = CKEDITOR.tools.array;
+
+
+                                       // Check for rgb(a).
+                                       ret = ret.concat( value.match( this._rgbaRegExp ) || [] );
+
+                                       // Check for hsl(a).
+                                       ret = ret.concat( value.match( this._hslaRegExp ) || [] );
+
+                                       ret = ret.concat( arrayTools.filter( value.split( /\s+/ ), function( colorEntry ) {
+                                               // Check for hex format.
+                                               if ( colorEntry.match( /^\#[a-f0-9]{3}(?:[a-f0-9]{3})?$/gi ) ) {
+                                                       return true;
+                                               }
+
+                                               // Check for preset names.
+                                               return colorEntry.toLowerCase() in CKEDITOR.tools.style.parse._colors;
+                                       } ) );
+
+                                       return ret;
+                               }
+                       }
+               },
+
+               /**
+                * A set of array helpers.
+                *
+                * @property {CKEDITOR.tools.array}
+                * @member CKEDITOR.tools
+                */
+               array: {
+                       /**
+                        * Returns a copy of `array` filtered using the `fn` function. Any elements that the `fn` will return `false` for
+                        * will get removed from the returned array.
+                        *
+                        *              var filtered = this.array.filter( [ 0, 1, 2, 3 ], function( value ) {
+                        *                      // Leave only values equal or greater than 2.
+                        *                      return value >= 2;
+                        *              } );
+                        *              console.log( filtered );
+                        *              // Logs: [ 2, 3 ]
+                        *
+                        * @param {Array} array
+                        * @param {Function} fn A function that gets called with each `array` item. Any item that `fn`
+                        * returned a `false`-alike value for will be filtered out of the `array`.
+                        * @param {Mixed} fn.value The currently iterated array value.
+                        * @param {Number} fn.index The index of the currently iterated value in an array.
+                        * @param {Array} fn.array The original array passed as the `array` variable.
+                        * @param {Mixed} [thisArg=undefined] A context object for `fn`.
+                        * @returns {Array} The filtered array.
+                        * @member CKEDITOR.tools.array
+                        */
+                       filter: function( array, fn, thisArg ) {
+                               var ret = [];
+
+                               this.forEach( array, function( val, i ) {
+                                       if ( fn.call( thisArg, val, i, array ) ) {
+                                               ret.push( val );
+                                       }
+                               } );
+
+                               return ret;
+                       },
+
+                       /**
+                        * Iterates over every element in the `array`.
+                        *
+                        * @param {Array} array An array to be iterated over.
+                        * @param {Function} fn The function called for every `array` element.
+                        * @param {Mixed} fn.value The currently iterated array value.
+                        * @param {Number} fn.index The index of the currently iterated value in an array.
+                        * @param {Array} fn.array The original array passed as an `array` variable.
+                        * @param {Mixed} [thisArg=undefined] The context object for `fn`.
+                        * @member CKEDITOR.tools.array
+                        */
+                       forEach: function( array, fn, thisArg ) {
+                               var len = array.length,
+                                       i;
+
+                               for ( i = 0; i < len; i++ ) {
+                                       fn.call( thisArg, array[ i ], i, array );
+                               }
+                       },
+
+                       /**
+                        * Applies a function to each element of an array and returns the array of results in the same order.
+                        * Note the order of the parameters.
+                        *
+                        * @param {Array} array An array of elements that `fn` is applied on.
+                        * @param {Function} fn A function with the signature `a -> b`.
+                        * @param {Mixed} [thisArg=undefined] The context object for `fn`.
+                        * @returns {Array} An array of mapped elements.
+                        * @member CKEDITOR.tools.array
+                        * @since 4.6.2
+                        */
+                       map: function( array, fn, thisArg ) {
+                               var result = [];
+                               for ( var i = 0; i < array.length; i++ ) {
+                                       result.push( fn.call( thisArg, array[ i ], i, array ) );
+                               }
+                               return result;
+                       },
+
+                       /**
+                        * Applies a function against each value in an array storing the result in an accumulator passed to the next iteration.
+                        * Note the order of the parameters.
+                        *
+                        * @param {Array} array An array of elements that `fn` is applied on.
+                        * @param {Function} fn A function with the signature `(accumulator, a, index, array) -> b`.
+                        * @param {Mixed} initial Initial value of the accumulator.
+                        * @param {Mixed} [thisArg=undefined] The context object for `fn`.
+                        * @returns {Mixed} The final value of the accumulator.
+                        * @member CKEDITOR.tools.array
+                        * @since 4.6.2
+                       */
+                       reduce: function( array, fn, initial, thisArg ) {
+                               var acc = initial;
+                               for ( var i = 0; i < array.length; i++ ) {
+                                       acc = fn.call( thisArg, acc, array[ i ], i, array );
+                               }
+                               return acc;
+                       }
+               },
+
+               /**
+                * A set of object helpers.
+                *
+                * @property {CKEDITOR.tools.object}
+                * @member CKEDITOR.tools
+                */
+               object: {
+                       /**
+                        * Returns the first key from `obj` which has a given `value`.
+                        *
+                        * @param {Object} obj An object whose `key` is looked for.
+                        * @param {Mixed} value An object's `value` to be looked for.
+                        * @returns {String/null} Matched `key` or `null` if not found.
+                        * @member CKEDITOR.tools.object
+                        */
+
+                       findKey: function( obj, value ) {
+                               if ( typeof obj !== 'object' ) {
+                                       return null;
+                               }
+
+                               var key;
+
+                               for ( key in obj ) {
+                                       if ( obj[ key ] === value ) {
+                                               return key;
+                                       }
+                               }
+
+                               return null;
+                       }
                }
        };
 
 
                return result;
        }
+
+       /**
+        * @member CKEDITOR.tools.array
+        * @method indexOf
+        * @inheritdoc CKEDITOR.tools#indexOf
+        */
+       CKEDITOR.tools.array.indexOf = CKEDITOR.tools.indexOf;
+
+       /**
+        * @member CKEDITOR.tools.array
+        * @method isArray
+        * @inheritdoc CKEDITOR.tools#isArray
+        */
+       CKEDITOR.tools.array.isArray = CKEDITOR.tools.isArray;
+
+       /**
+        * Left mouse button.
+        *
+        * @since 4.7.3
+        * @readonly
+        * @property {Number} [=0]
+        * @member CKEDITOR
+        */
+       CKEDITOR.MOUSE_BUTTON_LEFT = 0;
+
+       /**
+        * Middle mouse button.
+        *
+        * @since 4.7.3
+        * @readonly
+        * @property {Number} [=1]
+        * @member CKEDITOR
+        */
+       CKEDITOR.MOUSE_BUTTON_MIDDLE = 1;
+
+       /**
+        * Right mouse button.
+        *
+        * @since 4.7.3
+        * @readonly
+        * @property {Number} [=2]
+        * @member CKEDITOR
+        */
+       CKEDITOR.MOUSE_BUTTON_RIGHT = 2;
+
+       /**
+        * The namespace containing functions to work on CSS properties.
+        *
+        * @since 4.6.1
+        * @class CKEDITOR.tools.style
+        */
+
+       /**
+        * The namespace with helper functions to parse some common CSS properties.
+        *
+        * @since 4.6.1
+        * @class CKEDITOR.tools.style.parse
+        */
+
+       /**
+        * The namespace with helper functions and polyfills for arrays.
+        *
+        * @since 4.6.1
+        * @class CKEDITOR.tools.array
+        */
+
+       /**
+        * The namespace with helper functions and polyfills for objects.
+        *
+        * @since 4.7.1
+        * @class CKEDITOR.tools.object
+        */
 } )();
 
 // PACKAGER_RENAME( CKEDITOR.tools )