Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge 279f297 into ecaf056
Browse files Browse the repository at this point in the history
  • Loading branch information
jodator committed Feb 11, 2020
2 parents ecaf056 + 279f297 commit d4d271c
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 14 deletions.
73 changes: 70 additions & 3 deletions src/view/styles/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,71 @@
* @module engine/view/styles/utils
*/

const colorRegExp = /^([#0-9A-Fa-f]{3,9}$|0$|rgba?\(|hsla?\(|[a-zA-Z]+$)/;
const HEX_COLOR_REGEXP = /^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
const RGB_COLOR_REGEXP = /^rgb\([ ]?([0-9]{1,3}[ %]?,[ ]?){2,3}[0-9]{1,3}[ %]?\)$/i;
const RGBA_COLOR_REGEXP = /^rgba\([ ]?([0-9]{1,3}[ %]?,[ ]?){3}(1|[0-9]+%|[0]?\.[0-9]+)\)$/i;
const HSL_COLOR_REGEXP = /^hsl\([ ]?([0-9]{1,3}[ %]?[,]?[ ]*){3}(1|[0-9]+%|[0]?\.[0-9]+)?\)$/i;
const HSLA_COLOR_REGEXP = /^hsla\([ ]?([0-9]{1,3}[ %]?,[ ]?){2,3}(1|[0-9]+%|[0]?\.[0-9]+)\)$/i;

const COLOR_NAMES = new Set( [
// CSS Level 1
'black', 'silver', 'gray', 'white', 'maroon', 'red', 'purple', 'fuchsia',
'green', 'lime', 'olive', 'yellow', 'navy', 'blue', 'teal', 'aqua',
// CSS Level 2 (Revision 1)
'orange',
// CSS Color Module Level 3
'aliceblue', 'antiquewhite', 'aquamarine', 'azure', 'beige', 'bisque', 'blanchedalmond', 'blueviolet', 'brown',
'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan',
'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta',
'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey',
'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod',
'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush',
'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray',
'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray',
'lightslategrey', 'lightsteelblue', 'lightyellow', 'limegreen', 'linen', 'magenta', 'mediumaquamarine',
'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen',
'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite',
'oldlace', 'olivedrab', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred',
'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon',
'sandybrown', 'seagreen', 'seashell', 'sienna', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow',
'springgreen', 'steelblue', 'tan', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'whitesmoke', 'yellowgreen',
// CSS Color Module Level 4
'rebeccapurple',
// Keywords
'currentcolor', 'transparent'
] );

/**
* Checks if string contains [color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) CSS value.
*
* isColor( '#f00' ); // true
* isColor( '#AA00BB33' ); // true
* isColor( 'rgb(0, 0, 250)' ); // true
* isColor( 'hsla(240, 100%, 50%, .7)' ); // true
* isColor( 'deepskyblue' ); // true
*
* **Note**: It does not support CSS Level 4 whitespace syntax, system colors and radius values for HSL colors.
*
* @param {String} string
* @returns {Boolean}
*/
export function isColor( string ) {
return colorRegExp.test( string );
// As far as I was able to test checking some pre-conditions is faster than joining each test with ||.
if ( string.startsWith( '#' ) ) {
return HEX_COLOR_REGEXP.test( string );
}

if ( string.startsWith( 'rgb' ) ) {
return RGB_COLOR_REGEXP.test( string ) || RGBA_COLOR_REGEXP.test( string );
}

if ( string.startsWith( 'hsl' ) ) {
return HSL_COLOR_REGEXP.test( string ) || HSLA_COLOR_REGEXP.test( string );
}

// Array check > RegExp test.
return COLOR_NAMES.has( string.toLowerCase() );
}

const lineStyleValues = [ 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset' ];
Expand All @@ -31,7 +86,7 @@ export function isLineStyle( string ) {
return lineStyleValues.includes( string );
}

const lengthRegExp = /^([+-]?[0-9]*[.]?[0-9]+([a-z]+|%)|0)$/;
const lengthRegExp = /^([+-]?[0-9]*[.]?[0-9]+(px|cm|mm|in|pc|pt|ch|em|ex|rem|vh|vw|vmin|vmax)|0)$/;

/**
* Checks if string contains [length](https://developer.mozilla.org/en-US/docs/Web/CSS/length) CSS value.
Expand All @@ -43,6 +98,18 @@ export function isLength( string ) {
return lengthRegExp.test( string );
}

const PERCENTAGE_VALUE_REGEXP = /^[+-]?[0-9]*[.]?[0-9]+%$/;

/**
* Checks if string contains [percentage](https://developer.mozilla.org/en-US/docs/Web/CSS/percentage) CSS value.
*
* @param {String} string
* @returns {Boolean}
*/
export function isPercentage( string ) {
return PERCENTAGE_VALUE_REGEXP.test( string );
}

const repeatValues = [ 'repeat-x', 'repeat-y', 'repeat', 'space', 'round', 'no-repeat' ];

/**
Expand Down
122 changes: 111 additions & 11 deletions tests/view/styles/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,111 @@
*/

import {
getShorthandValues,
getBoxSidesShorthandValue,
getBoxSidesValues,
getShorthandValues,
isColor,
isLength,
isLineStyle
isLineStyle, isPercentage
} from '../../../src/view/styles/utils';

describe( 'Styles utils', () => {
describe( 'isColor()', () => {
it( 'returns true for #RGB color', () => {
testValues( [ '#f00', '#ba2' ], isColor );
testValues( [ '#f00', '#ba2', '#F00', '#BA2', '#AbC' ], isColor );
} );

it( 'returns true for #RRGGBB color', () => {
testValues( [ '#ff0000', '#bbaa22' ], isColor );
testValues( [ '#ff0000', '#bbaa22', '#FF0000', '#BBAA22', '#AabBCC' ], isColor );
} );

it( 'returns true for #RGBA color', () => {
testValues( [ '#f000', '#ba24' ], isColor );
testValues( [ '#f000', '#ba24', '#F000', '#BA24', '#aBcD' ], isColor );
} );

it( 'returns true for #RRGGBBAA color', () => {
testValues( [ '#ff000000', '#bbaa2244' ], isColor );
testValues( [ '#ff000000', '#bbaa2244', '#FF000000', '#BBAA2244', '#AabBCCdd' ], isColor );
} );

it( 'returns false for invalid # color', () => {
testValues( [ '#ttt', '#1', '#12', '#12345' ], value => !isColor( value ) );
} );

it( 'returns true for rgb() color', () => {
testValues( [ 'rgb(255, 255, 255)', 'rgb(23%,0,100%)' ], isColor );
testValues( [
'rgb(255,0,153)',
'rgb(255, 0, 153)',
'rgb(100%,0%,60%)',
'rgb(100%, 0%, 60%)'
// Unsupported:
// 'rgb(11, 22, 33, 0.1)', // rgba() is equal to rgb()
// 'rgb(255, 0, 153.0)', // Floats are valid
// 'rgb(255 0 153)', // CSS Level 4 notation
], isColor );
} );

it( 'returns false for invalid rgb() color', () => {
testValues( [
'rgb()',
'rgb(1)',
'rgb(1,2)',
'rgb(11,',
'rgb(11, 22,',
'rgb(11, 22, 33',
'rgb((11, 22, 33',
'rgb((11, 22, 33)',
'rgb(11, 22, 33))',
'rgb(11, 22, 33, 0.1)',
'rgb(11, 22, 33, .153)'
// Unsupported:
// 'rgb(100%, 0, 60%)', // Mixed numbers and percentages. TODO: might be skipped - adds complexity.,
], value => !isColor( value ) );
} );

it( 'returns true for rgba() color', () => {
testValues( [ 'rgba(1,2,3,0.7)', 'rgba(12%,0,0,1)' ], isColor );
} );

it( 'returns true for hsl() color', () => {
testValues( [ 'hsl(0, 100%, 50%)', 'hsl(340,80%,40%)' ], isColor );
testValues( [
'hsl(270,60%,70%)',
'hsl(270, 60%, 70%)',
'hsl(270, 60%, 50%, .15)',
'hsl(270, 60%, 50%, 0.15)',
'hsl(270, 60%, 50%, 15%)'
// Unsupported:
// 'hsl(270deg, 60%, 70%)', // Valid deg unit
// 'hsl(4.71239rad, 60%, 70%)', // Valid rad unit
// 'hsl(.75turn, 60%, 70%)', // Valid turn unit
// 'hsl(270 60% 70%)', // CSS Level 4 notation
// 'hsl(270 60% 50% / .15)', // CSS Level 4 notation
// 'hsl(270 60% 50% / 15%)' // CSS Level 4 notation
], isColor );
} );

it( 'returns true for hsla() color', () => {
testValues( [ 'hsla(240, 100%, 50%, 1)', 'hsla(240, 100%, 50%, .05)' ], isColor );
} );

it( 'returns true for currentColor color', () => {
testValues( [ 'currentColor' ], isColor );
it( 'returns true for color keywords', () => {
testValues( [ 'currentColor', 'transparent' ], isColor );
} );

it( 'returns true for color keyword', () => {
testValues( [
// CSS Level 1
'red', 'green', 'blue', // ...
// CSS Level 2
'orange',
// CSS Level 3
'cyan', 'azure', 'wheat',
// CSS Level 4
'rebeccapurple'
], isColor );
} );

it( 'returns false for unknown color keyword', () => {
testValues( [ 'redx', 'greenx', 'bluex' ], value => !isColor( value ) );
} );
} );

Expand All @@ -63,10 +124,49 @@ describe( 'Styles utils', () => {
describe( 'isLength()', () => {
it( 'returns true for various units', () => {
testValues(
[ '1px', '2rem', '34.5px', '.2em', '0', '1346vmax' ],
[
'1px',
'1cm',
'1mm',
'1in',
'1pc',
'1pt',
'1ch',
'1em',
'1ex',
'1rem',
'1vh',
'1vw',
'1vmin',
'1vmax'
],
isLength
);
} );

it( 'returns true for various values notation', () => {
testValues(
[
'0',
'1px',
'1000px',
'1.1px',
'345.457px',
'.457px'
],
isLength
);
} );
} );

describe( 'isPercentage()', () => {
it( 'returns true valid values', () => {
testValues( [ '1%', '100%', '1123.1312%', '0.9876%' ], isPercentage );
} );

it( 'returns false for not a percentage values', () => {
testValues( [ '0', '1px', '1000px', '1.1px', '345.457px', '.457px' ], value => !isPercentage( value ) );
} );
} );

describe( 'getBoxSidesShorthandValue()', () => {
Expand Down

0 comments on commit d4d271c

Please sign in to comment.