Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new syntaxes in CKEDITOR.tools.color #4599

Merged
merged 16 commits into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 55 additions & 26 deletions core/tools/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,19 @@
* @returns {Array/null}
*/
extractColorChannelsFromHex: function( colorCode ) {
// We also like to support hex-like values (so hexes without hash at the beginning).
if ( colorCode.indexOf( '#' ) === -1 ) {
colorCode = '#' + colorCode;
}

if ( colorCode.match( CKEDITOR.tools.color.hex3CharsRegExp ) ) {
colorCode = this._.hex3ToHex6( colorCode );
}

if ( colorCode.match( CKEDITOR.tools.color.hex4CharsRegExp ) ) {
colorCode = this._.hex4ToHex8( colorCode );
}

if ( !colorCode.match( CKEDITOR.tools.color.hex6CharsRegExp ) && !colorCode.match( CKEDITOR.tools.color.hex8CharsRegExp ) ) {
return null;
}
Expand Down Expand Up @@ -367,19 +376,11 @@
extractColorChannelsFromRgba: function( colorCode ) {
var channels = this._.extractColorChannelsByPattern( colorCode, CKEDITOR.tools.color.rgbRegExp );

if ( !channels ) {
if ( !channels || channels.length < 3 || channels.length > 4 ) {
sculpt0r marked this conversation as resolved.
Show resolved Hide resolved
return null;
}

var isColorDeclaredWithAlpha = colorCode.indexOf( 'rgba' ) === 0;

if ( isColorDeclaredWithAlpha && channels.length !== 4 ) {
return null;
}

if ( !isColorDeclaredWithAlpha && channels.length !== 3 ) {
return null;
}
var isColorDeclaredWithAlpha = channels.length === 4;

var red = tryToConvertToValidIntegerValue( channels[ 0 ], CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE ),
green = tryToConvertToValidIntegerValue( channels[ 1 ], CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE ),
Expand All @@ -403,19 +404,11 @@
extractColorChannelsFromHsla: function( colorCode ) {
var channels = this._.extractColorChannelsByPattern( colorCode, CKEDITOR.tools.color.hslRegExp );

if ( !channels ) {
if ( !channels || channels.length < 3 || channels.length > 4 ) {
return null;
}

var isColorDeclaredWithAlpha = colorCode.indexOf( 'hsla' ) === 0;

if ( isColorDeclaredWithAlpha && channels.length !== 4 ) {
return null;
}

if ( !isColorDeclaredWithAlpha && channels.length !== 3 ) {
return null;
}
var isColorDeclaredWithAlpha = channels.length === 4;

var hue = tryToConvertToValidIntegerValue( channels[ 0 ], CKEDITOR.tools.color.MAX_HUE_CHANNEL_VALUE ),
saturation = tryToConvertToValidFloatValue( channels[ 1 ], CKEDITOR.tools.color.MAX_SATURATION_LIGHTNESS_CHANNEL_VALUE ),
Expand Down Expand Up @@ -446,6 +439,19 @@
return '#' + parts[ 1 ] + parts[ 1 ] + parts[ 2 ] + parts[ 2 ] + parts[ 3 ] + parts[ 3 ];
},

/**
* Converts 4-characters hexadecimal color format to 8-characters one.
*
* @private
* @param {String} hex4ColorCode 4-characters hexadecimal color, e.g. `#F0F0`.
* @returns {String} 8-characters hexadecimal color e.g. `#FF00FF00`.
*/
hex4ToHex8: function( hex4ColorCode ) {
var hex6 = this._.hex3ToHex6( hex4ColorCode.substr( 0, 4 ) );

return hex6 + CKEDITOR.tools.repeat( hex4ColorCode[ 4 ], 2 );
},

/**
* Extracts color channels values based on provided regular expression.
*
Expand All @@ -461,11 +467,25 @@
return null;
}

var values = match[ 2 ].split( ',' );
var separator = match[ 1 ].indexOf( ',' ) === -1 ? /\s/ : ',',
values = match[ 1 ].split( separator );

values = CKEDITOR.tools.array.map( values, function( value ) {
return CKEDITOR.tools.trim( value );
} );
values = CKEDITOR.tools.array.reduce( values, function( trimmedValues, value ) {
var trimmedValue = CKEDITOR.tools.trim( value );

if ( trimmedValue.length === 0 ) {
return trimmedValues;
}

return trimmedValues.concat( [ trimmedValue ] );
}, [] );

// There was alpha channel in the no-comma syntax ( / <number>%?).
if ( match[ 2 ] ) {
var alpha = CKEDITOR.tools.trim( match[ 2 ].replace( '/', '' ) );

values.push( alpha );
}

return values;
},
Expand Down Expand Up @@ -612,6 +632,15 @@
*/
hex3CharsRegExp: /#([0-9a-f]{3}$)/gim,

/**
* Regular expression to match hash (`#`) followed by four characters long hexadecimal color value.
*
* @private
* @static
* @property {RegExp}
*/
hex4CharsRegExp: /#([0-9a-f]{4}$)/gim,

/**
* Regular expression to match hash (`#`) followed by six characters long hexadecimal color value.
*
Expand Down Expand Up @@ -640,7 +669,7 @@
* @static
* @property {RegExp}
*/
rgbRegExp: /(rgb[a]?)\(([.,\d\s%]*)\)/i,
rgbRegExp: /rgba?\(([.,\d\s%]*)(\s*\/\s*[\d.%]+)?\s*\)/i,

/**
* Regular expression to extract numbers from HSL and HSLA color value.
Expand All @@ -652,7 +681,7 @@
* @static
* @property {RegExp}
*/
hslRegExp: /(hsl[a]?)\(([.,\d\s%]*)\)/i,
hslRegExp: /hsla?\(([.,\d\s%]*)(\s*\/\s*[\d.%]+)?\s*\)/i,

/**
* Color list based on [W3 named colors list](https://www.w3.org/TR/css-color-4/#named-colors).
Expand Down
79 changes: 74 additions & 5 deletions tests/core/tools/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// 3-HEX -> hexadecimal color with only 3 characters value: #FFF
// 6-HEX -> hexadecimal color with exactly 6 characters value: #FFFFFF
// 8-HEX -> hexadecimal color with exactly 8 characters value: #FFFFFF00. Last two characters are for alpha
// n-HEX-like -> n-HEX format without the hash at the beginning: FFF, FFF0, FFFFFF, FFFFFF00

( function() {
'use strict';
Expand Down Expand Up @@ -36,8 +37,6 @@

'test color from RGBA with outranged alpha percent value returns default value': colorTools.testColorConversion( 'rgba( 120, 120, 120, 101% )', 'default', 'getHex', 'default' ),

'test color from invalid HSL with four values returns default value': colorTools.testColorConversion( 'hsl( 40, 40%, 100%, 1 )', 'default', 'getHex', 'default' ),

'test color from outranged percent HSL value returns default value': colorTools.testColorConversion( 'hsl( 361, 101%, 101% )', 'default', 'getHex', 'default' ),

'test color from outranged normalized HSL value returns default value': colorTools.testColorConversion( 'hsl( 361, 1.1, 1.1 )', 'default', 'getHex', 'default' ),
Expand All @@ -64,8 +63,6 @@

'test color from valid string color name returns 6-HEX': colorTools.testColorConversion( 'red', '#FF0000', 'getHex' ),

'test color from invalid RGB with four values returns default value': colorTools.testColorConversion( 'rgb( 40, 40, 150, 1 )', 'default', 'getHex', 'default' ),

'test color from valid RGB string returns 6-HEX': colorTools.testColorConversion( 'rgb( 40, 40, 150 )', '#282896', 'getHex' ),

'test color from valid RGB string returns 6-HEX (max value)': colorTools.testColorConversion( 'rgb( 255, 40, 150 )', '#FF2896', 'getHex' ),
Expand Down Expand Up @@ -104,7 +101,79 @@

'test color from valid HSL string returns 8-HEX': colorTools.testColorConversion( 'hsl( 195, 1, 0.5 )', '#00BFFFFF', 'getHexWithAlpha' ),

'test color from valid RGB with percent returns valid RGB': colorTools.testColorConversion( 'rgb(20.5%,0,255)', 'rgb(52,0,255)', 'getRgb' )
'test color from valid RGB with percent returns valid RGB': colorTools.testColorConversion( 'rgb(20.5%,0,255)', 'rgb(52,0,255)', 'getRgb' ),

// (#4583)
'test color from 4-HEX returns valid 6-HEX': colorTools.testColorConversion( '#F0F0', '#FFFFFF', 'getHex' ),

// (#4583)
'test color from 4-HEX returns valid 8-HEX': colorTools.testColorConversion( '#F0F0', '#FF00FF00', 'getHexWithAlpha' ),

// (#4583)
'test color from 4-HEX returns valid RGBA': colorTools.testColorConversion( '#F0F0', 'rgba(255,0,255,0)', 'getRgba' ),

// (#4583)
'test color from 4-HEX returns valid HSLA': colorTools.testColorConversion( '#F0F0','hsla(-60,100%,50%,0)', 'getHsla' ),

// (#4583)
'test RGB values are treated like RGBA values': colorTools.testColorConversion( 'rgb( 255, 0, 255, 0)', 'rgba(255,0,255,0)', 'getRgba' ),

// (#4583)
'test HSL values are treated like HSLA values': colorTools.testColorConversion( 'hsl( 195, 100%, 50%, 0 )', 'hsla(195,100%,50%,0)', 'getHsla' ),

// (#4583)
'test RGB value with no-comma syntax': colorTools.testColorConversion( 'rgb( 255 0 255 )', 'rgb(255,0,255)', 'getRgb' ),

// (#4583)
'test RGB value with alpha (number) and no-comma syntax': colorTools.testColorConversion( 'rgb( 255 0 255 / 0.1 )', 'rgba(255,0,255,0.1)', 'getRgba' ),

// (#4583)
'test RGB value with alpha (percentage) and no-comma syntax': colorTools.testColorConversion( 'rgb( 255 0 255 / 10% )', 'rgba(255,0,255,0.1)', 'getRgba' ),

// (#4583)
'test RGBA value with no-comma syntax': colorTools.testColorConversion( 'rgba( 255 0 255 )', 'rgb(255,0,255)', 'getRgb' ),

// (#4583)
'test RGBA value with alpha (number) and no-comma syntax': colorTools.testColorConversion( 'rgba( 255 0 255 / 0.1 )', 'rgba(255,0,255,0.1)', 'getRgba' ),

// (#4583)
'test RGBA value with alpha (percentage) and no-comma syntax': colorTools.testColorConversion( 'rgba( 255 0 255 / 10% )', 'rgba(255,0,255,0.1)', 'getRgba' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSL value with no-comma syntax': colorTools.testColorConversion( 'hsl( 200 50% 10% )', 'hsl(199,0%,10%)', 'getHsl' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSL value with alpha (number) and no-comma syntax': colorTools.testColorConversion( 'hsl( 200 50% 10% / 0.1 )', 'hsla(199,0%,10%,0.1)', 'getHsla' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSL value with alpha (percentage) and no-comma syntax': colorTools.testColorConversion( 'hsl( 200 50% 10% / 10% )', 'hsla(199,0%,10%,0.1)', 'getHsla' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSLA value with no-comma syntax': colorTools.testColorConversion( 'hsla( 200 50% 10% )', 'hsl(199,0%,10%)', 'getHsl' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSLA value with alpha (number) and no-comma syntax': colorTools.testColorConversion( 'hsla( 200 50% 10% / 0.1 )', 'hsla(199,0%,10%,0.1)', 'getHsla' ),

// (#4583)
// The expected value is incorrect due to #4597.
'test HSLA value with alpha (percentage) and no-comma syntax': colorTools.testColorConversion( 'hsla( 200 50% 10% / 10% )', 'hsla(199,0%,10%,0.1)', 'getHsla' ),

// (#4583)
'test 6-HEX-like value is treated as 6-HEX value': colorTools.testColorConversion( 'FF0000', '#FF0000', 'getHex' ),

// (#4583)
'test 3-HEX-like value is treated as 3-HEX value': colorTools.testColorConversion( 'F00', '#FF0000', 'getHex' ),

// (#4583)
'test 8-HEX-like value is treated as 8-HEX value': colorTools.testColorConversion( 'FF0000FF', '#FF0000FF', 'getHexWithAlpha' ),

// (#4583)
'test 4-HEX-like value is treated as 8-HEX value': colorTools.testColorConversion( 'F00F', '#FF0000FF', 'getHexWithAlpha' )
} );

} )();