You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
11 KiB
526 lines
11 KiB
var functionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)'; |
|
var functionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)'; |
|
var variableRegexStr = 'var\\(\\-\\-[^\\)]+\\)'; |
|
var functionAnyRegexStr = '(' + variableRegexStr + '|' + functionNoVendorRegexStr + '|' + functionVendorRegexStr + ')'; |
|
|
|
var animationTimingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/; |
|
var calcRegex = new RegExp('^(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)$', 'i'); |
|
var decimalRegex = /[0-9]/; |
|
var functionAnyRegex = new RegExp('^' + functionAnyRegexStr + '$', 'i'); |
|
var hslColorRegex = /^hsl\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+%\s{0,31}\)|hsla\(\s{0,31}[\-\.]?\d+\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+%\s{0,31},\s{0,31}\.?\d+\s{0,31}\)$/; |
|
var identifierRegex = /^(\-[a-z0-9_][a-z0-9\-_]*|[a-z][a-z0-9\-_]*)$/i; |
|
var longHexColorRegex = /^#[0-9a-f]{6}$/i; |
|
var namedEntityRegex = /^[a-z]+$/i; |
|
var prefixRegex = /^-([a-z0-9]|-)*$/i; |
|
var rgbColorRegex = /^rgb\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31}\)|rgba\(\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\d]{1,3}\s{0,31},\s{0,31}[\.\d]+\s{0,31}\)$/; |
|
var shortHexColorRegex = /^#[0-9a-f]{3}$/i; |
|
var validTimeUnits = ['ms', 's']; |
|
var urlRegex = /^url\([\s\S]+\)$/i; |
|
var variableRegex = new RegExp('^' + variableRegexStr + '$', 'i'); |
|
|
|
var DECIMAL_DOT = '.'; |
|
var MINUS_SIGN = '-'; |
|
var PLUS_SIGN = '+'; |
|
|
|
var Keywords = { |
|
'^': [ |
|
'inherit', |
|
'initial', |
|
'unset' |
|
], |
|
'*-style': [ |
|
'auto', |
|
'dashed', |
|
'dotted', |
|
'double', |
|
'groove', |
|
'hidden', |
|
'inset', |
|
'none', |
|
'outset', |
|
'ridge', |
|
'solid' |
|
], |
|
'animation-direction': [ |
|
'alternate', |
|
'alternate-reverse', |
|
'normal', |
|
'reverse' |
|
], |
|
'animation-fill-mode': [ |
|
'backwards', |
|
'both', |
|
'forwards', |
|
'none' |
|
], |
|
'animation-iteration-count': [ |
|
'infinite' |
|
], |
|
'animation-name': [ |
|
'none' |
|
], |
|
'animation-play-state': [ |
|
'paused', |
|
'running' |
|
], |
|
'animation-timing-function': [ |
|
'ease', |
|
'ease-in', |
|
'ease-in-out', |
|
'ease-out', |
|
'linear', |
|
'step-end', |
|
'step-start' |
|
], |
|
'background-attachment': [ |
|
'fixed', |
|
'inherit', |
|
'local', |
|
'scroll' |
|
], |
|
'background-clip': [ |
|
'border-box', |
|
'content-box', |
|
'inherit', |
|
'padding-box', |
|
'text' |
|
], |
|
'background-origin': [ |
|
'border-box', |
|
'content-box', |
|
'inherit', |
|
'padding-box' |
|
], |
|
'background-position': [ |
|
'bottom', |
|
'center', |
|
'left', |
|
'right', |
|
'top' |
|
], |
|
'background-repeat': [ |
|
'no-repeat', |
|
'inherit', |
|
'repeat', |
|
'repeat-x', |
|
'repeat-y', |
|
'round', |
|
'space' |
|
], |
|
'background-size': [ |
|
'auto', |
|
'cover', |
|
'contain' |
|
], |
|
'border-collapse': [ |
|
'collapse', |
|
'inherit', |
|
'separate' |
|
], |
|
'bottom': [ |
|
'auto' |
|
], |
|
'clear': [ |
|
'both', |
|
'left', |
|
'none', |
|
'right' |
|
], |
|
'color': [ |
|
'transparent' |
|
], |
|
'cursor': [ |
|
'all-scroll', |
|
'auto', |
|
'col-resize', |
|
'crosshair', |
|
'default', |
|
'e-resize', |
|
'help', |
|
'move', |
|
'n-resize', |
|
'ne-resize', |
|
'no-drop', |
|
'not-allowed', |
|
'nw-resize', |
|
'pointer', |
|
'progress', |
|
'row-resize', |
|
's-resize', |
|
'se-resize', |
|
'sw-resize', |
|
'text', |
|
'vertical-text', |
|
'w-resize', |
|
'wait' |
|
], |
|
'display': [ |
|
'block', |
|
'inline', |
|
'inline-block', |
|
'inline-table', |
|
'list-item', |
|
'none', |
|
'table', |
|
'table-caption', |
|
'table-cell', |
|
'table-column', |
|
'table-column-group', |
|
'table-footer-group', |
|
'table-header-group', |
|
'table-row', |
|
'table-row-group' |
|
], |
|
'float': [ |
|
'left', |
|
'none', |
|
'right' |
|
], |
|
'left': [ |
|
'auto' |
|
], |
|
'font': [ |
|
'caption', |
|
'icon', |
|
'menu', |
|
'message-box', |
|
'small-caption', |
|
'status-bar', |
|
'unset' |
|
], |
|
'font-size': [ |
|
'large', |
|
'larger', |
|
'medium', |
|
'small', |
|
'smaller', |
|
'x-large', |
|
'x-small', |
|
'xx-large', |
|
'xx-small' |
|
], |
|
'font-stretch': [ |
|
'condensed', |
|
'expanded', |
|
'extra-condensed', |
|
'extra-expanded', |
|
'normal', |
|
'semi-condensed', |
|
'semi-expanded', |
|
'ultra-condensed', |
|
'ultra-expanded' |
|
], |
|
'font-style': [ |
|
'italic', |
|
'normal', |
|
'oblique' |
|
], |
|
'font-variant': [ |
|
'normal', |
|
'small-caps' |
|
], |
|
'font-weight': [ |
|
'100', |
|
'200', |
|
'300', |
|
'400', |
|
'500', |
|
'600', |
|
'700', |
|
'800', |
|
'900', |
|
'bold', |
|
'bolder', |
|
'lighter', |
|
'normal' |
|
], |
|
'line-height': [ |
|
'normal' |
|
], |
|
'list-style-position': [ |
|
'inside', |
|
'outside' |
|
], |
|
'list-style-type': [ |
|
'armenian', |
|
'circle', |
|
'decimal', |
|
'decimal-leading-zero', |
|
'disc', |
|
'decimal|disc', // this is the default value of list-style-type, see comment in compactable.js |
|
'georgian', |
|
'lower-alpha', |
|
'lower-greek', |
|
'lower-latin', |
|
'lower-roman', |
|
'none', |
|
'square', |
|
'upper-alpha', |
|
'upper-latin', |
|
'upper-roman' |
|
], |
|
'overflow': [ |
|
'auto', |
|
'hidden', |
|
'scroll', |
|
'visible' |
|
], |
|
'position': [ |
|
'absolute', |
|
'fixed', |
|
'relative', |
|
'static' |
|
], |
|
'right': [ |
|
'auto' |
|
], |
|
'text-align': [ |
|
'center', |
|
'justify', |
|
'left', |
|
'left|right', // this is the default value of list-style-type, see comment in compactable.js |
|
'right' |
|
], |
|
'text-decoration': [ |
|
'line-through', |
|
'none', |
|
'overline', |
|
'underline' |
|
], |
|
'text-overflow': [ |
|
'clip', |
|
'ellipsis' |
|
], |
|
'top': [ |
|
'auto' |
|
], |
|
'vertical-align': [ |
|
'baseline', |
|
'bottom', |
|
'middle', |
|
'sub', |
|
'super', |
|
'text-bottom', |
|
'text-top', |
|
'top' |
|
], |
|
'visibility': [ |
|
'collapse', |
|
'hidden', |
|
'visible' |
|
], |
|
'white-space': [ |
|
'normal', |
|
'nowrap', |
|
'pre' |
|
], |
|
'width': [ |
|
'inherit', |
|
'initial', |
|
'medium', |
|
'thick', |
|
'thin' |
|
] |
|
}; |
|
|
|
var Units = [ |
|
'%', |
|
'ch', |
|
'cm', |
|
'em', |
|
'ex', |
|
'in', |
|
'mm', |
|
'pc', |
|
'pt', |
|
'px', |
|
'rem', |
|
'vh', |
|
'vm', |
|
'vmax', |
|
'vmin', |
|
'vw' |
|
]; |
|
|
|
function isAnimationTimingFunction() { |
|
var isTimingFunctionKeyword = isKeyword('animation-timing-function'); |
|
|
|
return function (value) { |
|
return isTimingFunctionKeyword(value) || animationTimingFunctionRegex.test(value); |
|
}; |
|
} |
|
|
|
function isColor(value) { |
|
return value != 'auto' && |
|
( |
|
isKeyword('color')(value) || |
|
isHexColor(value) || |
|
isColorFunction(value) || |
|
isNamedEntity(value) |
|
); |
|
} |
|
|
|
function isColorFunction(value) { |
|
return isRgbColor(value) || isHslColor(value); |
|
} |
|
|
|
function isDynamicUnit(value) { |
|
return calcRegex.test(value); |
|
} |
|
|
|
function isFunction(value) { |
|
return functionAnyRegex.test(value); |
|
} |
|
|
|
function isHexColor(value) { |
|
return shortHexColorRegex.test(value) || longHexColorRegex.test(value); |
|
} |
|
|
|
function isHslColor(value) { |
|
return hslColorRegex.test(value); |
|
} |
|
|
|
function isIdentifier(value) { |
|
return identifierRegex.test(value); |
|
} |
|
|
|
function isImage(value) { |
|
return value == 'none' || value == 'inherit' || isUrl(value); |
|
} |
|
|
|
function isKeyword(propertyName) { |
|
return function(value) { |
|
return Keywords[propertyName].indexOf(value) > -1; |
|
}; |
|
} |
|
|
|
function isNamedEntity(value) { |
|
return namedEntityRegex.test(value); |
|
} |
|
|
|
function isNumber(value) { |
|
return scanForNumber(value) == value.length; |
|
} |
|
|
|
function isRgbColor(value) { |
|
return rgbColorRegex.test(value); |
|
} |
|
|
|
function isPrefixed(value) { |
|
return prefixRegex.test(value); |
|
} |
|
|
|
function isPositiveNumber(value) { |
|
return isNumber(value) && |
|
parseFloat(value) >= 0; |
|
} |
|
|
|
function isVariable(value) { |
|
return variableRegex.test(value); |
|
} |
|
|
|
function isTime(value) { |
|
var numberUpTo = scanForNumber(value); |
|
|
|
return numberUpTo == value.length && parseInt(value) === 0 || |
|
numberUpTo > -1 && validTimeUnits.indexOf(value.slice(numberUpTo + 1)) > -1; |
|
} |
|
|
|
function isUnit(validUnits, value) { |
|
var numberUpTo = scanForNumber(value); |
|
|
|
return numberUpTo == value.length && parseInt(value) === 0 || |
|
numberUpTo > -1 && validUnits.indexOf(value.slice(numberUpTo + 1)) > -1 || |
|
value == 'auto' || |
|
value == 'inherit'; |
|
} |
|
|
|
function isUrl(value) { |
|
return urlRegex.test(value); |
|
} |
|
|
|
function isZIndex(value) { |
|
return value == 'auto' || |
|
isNumber(value) || |
|
isKeyword('^')(value); |
|
} |
|
|
|
function scanForNumber(value) { |
|
var hasDot = false; |
|
var hasSign = false; |
|
var character; |
|
var i, l; |
|
|
|
for (i = 0, l = value.length; i < l; i++) { |
|
character = value[i]; |
|
|
|
if (i === 0 && (character == PLUS_SIGN || character == MINUS_SIGN)) { |
|
hasSign = true; |
|
} else if (i > 0 && hasSign && (character == PLUS_SIGN || character == MINUS_SIGN)) { |
|
return i - 1; |
|
} else if (character == DECIMAL_DOT && !hasDot) { |
|
hasDot = true; |
|
} else if (character == DECIMAL_DOT && hasDot) { |
|
return i - 1; |
|
} else if (decimalRegex.test(character)) { |
|
continue; |
|
} else { |
|
return i - 1; |
|
} |
|
} |
|
|
|
return i; |
|
} |
|
|
|
function validator(compatibility) { |
|
var validUnits = Units.slice(0).filter(function (value) { |
|
return !(value in compatibility.units) || compatibility.units[value] === true; |
|
}); |
|
|
|
return { |
|
colorOpacity: compatibility.colors.opacity, |
|
isAnimationDirectionKeyword: isKeyword('animation-direction'), |
|
isAnimationFillModeKeyword: isKeyword('animation-fill-mode'), |
|
isAnimationIterationCountKeyword: isKeyword('animation-iteration-count'), |
|
isAnimationNameKeyword: isKeyword('animation-name'), |
|
isAnimationPlayStateKeyword: isKeyword('animation-play-state'), |
|
isAnimationTimingFunction: isAnimationTimingFunction(), |
|
isBackgroundAttachmentKeyword: isKeyword('background-attachment'), |
|
isBackgroundClipKeyword: isKeyword('background-clip'), |
|
isBackgroundOriginKeyword: isKeyword('background-origin'), |
|
isBackgroundPositionKeyword: isKeyword('background-position'), |
|
isBackgroundRepeatKeyword: isKeyword('background-repeat'), |
|
isBackgroundSizeKeyword: isKeyword('background-size'), |
|
isColor: isColor, |
|
isColorFunction: isColorFunction, |
|
isDynamicUnit: isDynamicUnit, |
|
isFontKeyword: isKeyword('font'), |
|
isFontSizeKeyword: isKeyword('font-size'), |
|
isFontStretchKeyword: isKeyword('font-stretch'), |
|
isFontStyleKeyword: isKeyword('font-style'), |
|
isFontVariantKeyword: isKeyword('font-variant'), |
|
isFontWeightKeyword: isKeyword('font-weight'), |
|
isFunction: isFunction, |
|
isGlobal: isKeyword('^'), |
|
isHslColor: isHslColor, |
|
isIdentifier: isIdentifier, |
|
isImage: isImage, |
|
isKeyword: isKeyword, |
|
isLineHeightKeyword: isKeyword('line-height'), |
|
isListStylePositionKeyword: isKeyword('list-style-position'), |
|
isListStyleTypeKeyword: isKeyword('list-style-type'), |
|
isNumber: isNumber, |
|
isPrefixed: isPrefixed, |
|
isPositiveNumber: isPositiveNumber, |
|
isRgbColor: isRgbColor, |
|
isStyleKeyword: isKeyword('*-style'), |
|
isTime: isTime, |
|
isUnit: isUnit.bind(null, validUnits), |
|
isUrl: isUrl, |
|
isVariable: isVariable, |
|
isWidth: isKeyword('width'), |
|
isZIndex: isZIndex |
|
}; |
|
} |
|
|
|
module.exports = validator;
|
|
|