@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
1,437 lines (1,397 loc) • 123 kB
JavaScript
(function() {
/* Copyright Google Inc.
* Licensed under the Apache Licence Version 2.0
* Autogenerated at Tue May 22 10:18:21 PDT 2012
* \@overrides window
* \@provides cssSchema, CSS_PROP_BIT_QUANTITY, CSS_PROP_BIT_HASH_VALUE, CSS_PROP_BIT_NEGATIVE_QUANTITY, CSS_PROP_BIT_QSTRING_CONTENT, CSS_PROP_BIT_QSTRING_URL, CSS_PROP_BIT_HISTORY_INSENSITIVE, CSS_PROP_BIT_Z_INDEX, CSS_PROP_BIT_ALLOWED_IN_LINK */
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_QUANTITY = 1;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_HASH_VALUE = 2;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_NEGATIVE_QUANTITY = 4;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_QSTRING_CONTENT = 8;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_QSTRING_URL = 16;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_HISTORY_INSENSITIVE = 32;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_Z_INDEX = 64;
/**
* @const
* @type {number}
*/
var CSS_PROP_BIT_ALLOWED_IN_LINK = 128;
var cssSchema = (function () {
var s = [
'rgb(?:\\(\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)\\s*,\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)\\s*,\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)|a\\(\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)\\s*,\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)\\s*,\\s*(?:\\d+|0|\\d+(?:\\.\\d+)?%)\\s*,\\s*(?:\\d+|0(?:\\.\\d+)?|\\.\\d+|1(?:\\.0+)?|0|\\d+(?:\\.\\d+)?%)) *\\)'
], c = [ /^ *$/i, RegExp('^ *(?:\\s*' + s[ 0 ] + '|(?:\\s*' + s[ 0 ] +
')?)+ *$', 'i'), RegExp('^ *\\s*' + s[ 0 ] + ' *$', 'i'),
RegExp('^ *\\s*' + s[ 0 ] + '\\s*' + s[ 0 ] + ' *$', 'i') ], L = [ [
'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige',
'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown',
'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral',
'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue',
'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkkhaki',
'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred',
'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray',
'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray',
'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia',
'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green',
'greenyellow', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory',
'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon',
'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow',
'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen',
'lightskyblue', 'lightslategray', 'lightsteelblue', 'lightyellow',
'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine',
'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen',
'mediumslateblue', 'mediumspringgreen', 'mediumturquoise',
'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose',
'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab',
'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen',
'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru',
'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown',
'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen',
'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray',
'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato',
'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow',
'yellowgreen' ], [ 'all-scroll', 'col-resize', 'crosshair', 'default',
'e-resize', 'hand', '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' ], [ '-moz-inline-box', '-moz-inline-stack',
'block', 'inline', 'inline-block', 'inline-table', 'list-item',
'run-in', 'table', 'table-caption', 'table-cell', 'table-column',
'table-column-group', 'table-footer-group', 'table-header-group',
'table-row', 'table-row-group' ], [ 'armenian', 'circle', 'decimal',
'decimal-leading-zero', 'disc', 'georgian', 'lower-alpha',
'lower-greek', 'lower-latin', 'lower-roman', 'square', 'upper-alpha',
'upper-latin', 'upper-roman' ], [ '100', '200', '300', '400', '500',
'600', '700', '800', '900', 'bold', 'bolder', 'lighter' ], [
'condensed', 'expanded', 'extra-condensed', 'extra-expanded',
'narrower', 'semi-condensed', 'semi-expanded', 'ultra-condensed',
'ultra-expanded', 'wider' ], [ 'behind', 'center-left', 'center-right',
'far-left', 'far-right', 'left-side', 'leftwards', 'right-side',
'rightwards' ], [ 'large', 'larger', 'small', 'smaller', 'x-large',
'x-small', 'xx-large', 'xx-small' ], [ '-moz-pre-wrap', '-o-pre-wrap',
'-pre-wrap', 'nowrap', 'pre', 'pre-line', 'pre-wrap' ], [ 'dashed',
'dotted', 'double', 'groove', 'outset', 'ridge', 'solid' ], [
'baseline', 'middle', 'sub', 'super', 'text-bottom', 'text-top' ], [
'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'
], [ 'fast', 'faster', 'slow', 'slower', 'x-fast', 'x-slow' ], [ 'above',
'below', 'higher', 'level', 'lower' ], [ 'border-box', 'contain',
'content-box', 'cover', 'padding-box' ], [ 'cursive', 'fantasy',
'monospace', 'sans-serif', 'serif' ], [ 'loud', 'silent', 'soft',
'x-loud', 'x-soft' ], [ 'no-repeat', 'repeat-x', 'repeat-y', 'round',
'space' ], [ 'blink', 'line-through', 'overline', 'underline' ], [
'high', 'low', 'x-high', 'x-low' ], [ 'absolute', 'relative', 'static'
], [ 'capitalize', 'lowercase', 'uppercase' ], [ 'child', 'female',
'male' ], [ 'bidi-override', 'embed' ], [ 'bottom', 'top' ], [ 'clip',
'ellipsis' ], [ 'continuous', 'digits' ], [ 'hide', 'show' ], [
'inside', 'outside' ], [ 'italic', 'oblique' ], [ 'left', 'right' ], [
'ltr', 'rtl' ], [ 'no-content', 'no-display' ], [ 'suppress',
'unrestricted' ], [ 'thick', 'thin' ], [ ',' ], [ '/' ], [ 'always' ],
[ 'auto' ], [ 'avoid' ], [ 'both' ], [ 'break-word' ], [ 'center' ], [
'code' ], [ 'collapse' ], [ 'fixed' ], [ 'hidden' ], [ 'inherit' ], [
'inset' ], [ 'invert' ], [ 'justify' ], [ 'local' ], [ 'medium' ], [
'mix' ], [ 'none' ], [ 'normal' ], [ 'once' ], [ 'repeat' ], [ 'scroll'
], [ 'separate' ], [ 'small-caps' ], [ 'spell-out' ], [ 'transparent' ],
[ 'visible' ] ];
return {
'-moz-border-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 36 ] ]
},
'-moz-border-radius-bottomleft': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-moz-border-radius-bottomright': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-moz-border-radius-topleft': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-moz-border-radius-topright': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-moz-box-shadow': {
'cssExtra': c[ 1 ],
'cssAlternates': [ 'boxShadow' ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 35 ], L[ 48 ], L[ 54 ] ]
},
'-moz-opacity': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 47 ] ]
},
'-moz-outline': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
49 ], L[ 52 ], L[ 54 ] ]
},
'-moz-outline-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 49 ] ]
},
'-moz-outline-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'-moz-outline-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'-o-text-overflow': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 25 ] ]
},
'-webkit-border-bottom-left-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-bottom-right-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 36 ] ]
},
'-webkit-border-radius-bottom-left': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-radius-bottom-right': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-radius-top-left': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-radius-top-right': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-top-left-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-border-top-right-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'-webkit-box-shadow': {
'cssExtra': c[ 1 ],
'cssAlternates': [ 'boxShadow' ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 35 ], L[ 48 ], L[ 54 ] ]
},
'azimuth': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 6 ], L[ 30 ], L[ 42 ], L[ 47 ] ]
},
'background': {
'cssExtra': RegExp('^ *(?:\\s*' + s[ 0 ] + '){0,2} *$', 'i'),
'cssPropBits': 23,
'cssLitGroup': [ L[ 0 ], L[ 14 ], L[ 17 ], L[ 24 ], L[ 30 ], L[ 35 ],
L[ 36 ], L[ 38 ], L[ 42 ], L[ 45 ], L[ 47 ], L[ 51 ], L[ 54 ], L[ 57
], L[ 58 ], L[ 62 ] ]
},
'background-attachment': {
'cssExtra': c[ 0 ],
'cssPropBits': 0,
'cssLitGroup': [ L[ 35 ], L[ 45 ], L[ 51 ], L[ 58 ] ]
},
'background-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 130,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'background-image': {
'cssExtra': c[ 0 ],
'cssPropBits': 16,
'cssLitGroup': [ L[ 35 ], L[ 54 ] ]
},
'background-position': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 24 ], L[ 30 ], L[ 35 ], L[ 42 ] ]
},
'background-repeat': {
'cssExtra': c[ 0 ],
'cssPropBits': 0,
'cssLitGroup': [ L[ 17 ], L[ 35 ], L[ 57 ] ]
},
'border': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
52 ], L[ 54 ], L[ 62 ] ]
},
'border-bottom': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
52 ], L[ 54 ], L[ 62 ] ]
},
'border-bottom-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'border-bottom-left-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'border-bottom-right-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'border-bottom-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'border-bottom-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'border-collapse': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 44 ], L[ 47 ], L[ 59 ] ]
},
'border-color': {
'cssExtra': RegExp('^ *(?:\\s*' + s[ 0 ] + '){1,4} *$', 'i'),
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'border-left': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
52 ], L[ 54 ], L[ 62 ] ]
},
'border-left-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'border-left-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'border-left-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'border-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 36 ] ]
},
'border-right': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
52 ], L[ 54 ], L[ 62 ] ]
},
'border-right-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'border-right-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'border-right-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'border-spacing': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'border-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'border-top': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
52 ], L[ 54 ], L[ 62 ] ]
},
'border-top-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 62 ] ]
},
'border-top-left-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'border-top-right-radius': {
'cssExtra': c[ 0 ],
'cssPropBits': 5
},
'border-top-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'border-top-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'border-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'bottom': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'box-shadow': {
'cssExtra': c[ 1 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 35 ], L[ 48 ], L[ 54 ] ]
},
'caption-side': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 24 ], L[ 47 ] ]
},
'clear': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 30 ], L[ 40 ], L[ 47 ], L[ 54 ] ]
},
'clip': {
'cssExtra':
/^ *\s*rect\(\s*(?:0|[+\-]?\d+(?:\.\d+)?(?:[cem]m|ex|in|p[ctx])|auto)\s*,\s*(?:0|[+\-]?\d+(?:\.\d+)?(?:[cem]m|ex|in|p[ctx])|auto)\s*,\s*(?:0|[+\-]?\d+(?:\.\d+)?(?:[cem]m|ex|in|p[ctx])|auto)\s*,\s*(?:0|[+\-]?\d+(?:\.\d+)?(?:[cem]m|ex|in|p[ctx])|auto) *\) *$/i,
'cssPropBits': 0,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'color': {
'cssExtra': c[ 2 ],
'cssPropBits': 130,
'cssLitGroup': [ L[ 0 ], L[ 47 ] ]
},
'content': { 'cssPropBits': 0 },
'counter-increment': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'counter-reset': {
'cssExtra': c[ 0 ],
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'cue': {
'cssPropBits': 16,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'cue-after': {
'cssPropBits': 16,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'cue-before': {
'cssPropBits': 16,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'cursor': {
'cssExtra': c[ 0 ],
'cssPropBits': 144,
'cssLitGroup': [ L[ 1 ], L[ 35 ], L[ 38 ], L[ 47 ] ]
},
'direction': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 31 ], L[ 47 ] ]
},
'display': {
'cssPropBits': 32,
'cssLitGroup': [ L[ 2 ], L[ 47 ], L[ 54 ] ]
},
'elevation': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 13 ], L[ 47 ] ]
},
'empty-cells': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 27 ], L[ 47 ] ]
},
'filter': {
'cssExtra':
/^ *(?:\s*alpha\(\s*opacity\s*=\s*(?:0|\d+(?:\.\d+)?%|[+\-]?\d+(?:\.\d+)?) *\))+ *$/i,
'cssPropBits': 32
},
'float': {
'cssAlternates': [ 'cssFloat', 'styleFloat' ],
'cssPropBits': 32,
'cssLitGroup': [ L[ 30 ], L[ 47 ], L[ 54 ] ]
},
'font': {
'cssExtra': c[ 0 ],
'cssPropBits': 9,
'cssLitGroup': [ L[ 4 ], L[ 7 ], L[ 11 ], L[ 15 ], L[ 29 ], L[ 35 ], L[
36 ], L[ 47 ], L[ 52 ], L[ 55 ], L[ 60 ] ]
},
'font-family': {
'cssExtra': c[ 0 ],
'cssPropBits': 8,
'cssLitGroup': [ L[ 15 ], L[ 35 ], L[ 47 ] ]
},
'font-size': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 7 ], L[ 47 ], L[ 52 ] ]
},
'font-stretch': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 5 ], L[ 55 ] ]
},
'font-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 29 ], L[ 47 ], L[ 55 ] ]
},
'font-variant': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 47 ], L[ 55 ], L[ 60 ] ]
},
'font-weight': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 4 ], L[ 47 ], L[ 55 ] ]
},
'height': {
'cssPropBits': 37,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'left': {
'cssPropBits': 37,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'letter-spacing': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ], L[ 55 ] ]
},
'line-height': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 47 ], L[ 55 ] ]
},
'list-style': {
'cssPropBits': 16,
'cssLitGroup': [ L[ 3 ], L[ 28 ], L[ 47 ], L[ 54 ] ]
},
'list-style-image': {
'cssPropBits': 16,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'list-style-position': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 28 ], L[ 47 ] ]
},
'list-style-type': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 3 ], L[ 47 ], L[ 54 ] ]
},
'margin': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'margin-bottom': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'margin-left': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'margin-right': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'margin-top': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'max-height': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 38 ], L[ 47 ], L[ 54 ] ]
},
'max-width': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 38 ], L[ 47 ], L[ 54 ] ]
},
'min-height': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'min-width': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'opacity': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 47 ] ]
},
'outline': {
'cssExtra': c[ 3 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 9 ], L[ 34 ], L[ 46 ], L[ 47 ], L[ 48 ], L[
49 ], L[ 52 ], L[ 54 ] ]
},
'outline-color': {
'cssExtra': c[ 2 ],
'cssPropBits': 2,
'cssLitGroup': [ L[ 0 ], L[ 47 ], L[ 49 ] ]
},
'outline-style': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 9 ], L[ 46 ], L[ 47 ], L[ 48 ], L[ 54 ] ]
},
'outline-width': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 34 ], L[ 47 ], L[ 52 ] ]
},
'overflow': {
'cssPropBits': 32,
'cssLitGroup': [ L[ 38 ], L[ 46 ], L[ 47 ], L[ 58 ], L[ 63 ] ]
},
'overflow-x': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 32 ], L[ 38 ], L[ 46 ], L[ 58 ], L[ 63 ] ]
},
'overflow-y': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 32 ], L[ 38 ], L[ 46 ], L[ 58 ], L[ 63 ] ]
},
'padding': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 47 ] ]
},
'padding-bottom': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 47 ] ]
},
'padding-left': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 47 ] ]
},
'padding-right': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 47 ] ]
},
'padding-top': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 47 ] ]
},
'page-break-after': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 30 ], L[ 37 ], L[ 38 ], L[ 39 ], L[ 47 ] ]
},
'page-break-before': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 30 ], L[ 37 ], L[ 38 ], L[ 39 ], L[ 47 ] ]
},
'page-break-inside': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 38 ], L[ 39 ], L[ 47 ] ]
},
'pause': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'pause-after': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'pause-before': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'pitch': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 19 ], L[ 47 ], L[ 52 ] ]
},
'pitch-range': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'play-during': {
'cssExtra': c[ 0 ],
'cssPropBits': 16,
'cssLitGroup': [ L[ 38 ], L[ 47 ], L[ 53 ], L[ 54 ], L[ 57 ] ]
},
'position': {
'cssPropBits': 32,
'cssLitGroup': [ L[ 20 ], L[ 47 ] ]
},
'quotes': {
'cssExtra': c[ 0 ],
'cssPropBits': 0,
'cssLitGroup': [ L[ 47 ], L[ 54 ] ]
},
'richness': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'right': {
'cssPropBits': 37,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'speak': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 47 ], L[ 54 ], L[ 55 ], L[ 61 ] ]
},
'speak-header': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 37 ], L[ 47 ], L[ 56 ] ]
},
'speak-numeral': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 26 ], L[ 47 ] ]
},
'speak-punctuation': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 43 ], L[ 47 ], L[ 54 ] ]
},
'speech-rate': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 12 ], L[ 47 ], L[ 52 ] ]
},
'stress': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'table-layout': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 38 ], L[ 45 ], L[ 47 ] ]
},
'text-align': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 30 ], L[ 42 ], L[ 47 ], L[ 50 ] ]
},
'text-decoration': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 18 ], L[ 47 ], L[ 54 ] ]
},
'text-indent': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ] ]
},
'text-overflow': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 25 ] ]
},
'text-shadow': {
'cssExtra': c[ 1 ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 35 ], L[ 48 ], L[ 54 ] ]
},
'text-transform': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 21 ], L[ 47 ], L[ 54 ] ]
},
'text-wrap': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 33 ], L[ 54 ], L[ 55 ] ]
},
'top': {
'cssPropBits': 37,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'unicode-bidi': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 23 ], L[ 47 ], L[ 55 ] ]
},
'vertical-align': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 10 ], L[ 24 ], L[ 47 ] ]
},
'visibility': {
'cssPropBits': 32,
'cssLitGroup': [ L[ 44 ], L[ 46 ], L[ 47 ], L[ 63 ] ]
},
'voice-family': {
'cssExtra': c[ 0 ],
'cssPropBits': 8,
'cssLitGroup': [ L[ 22 ], L[ 35 ], L[ 47 ] ]
},
'volume': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 16 ], L[ 47 ], L[ 52 ] ]
},
'white-space': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 8 ], L[ 47 ], L[ 55 ] ]
},
'width': {
'cssPropBits': 33,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'word-spacing': {
'cssPropBits': 5,
'cssLitGroup': [ L[ 47 ], L[ 55 ] ]
},
'word-wrap': {
'cssPropBits': 0,
'cssLitGroup': [ L[ 41 ], L[ 55 ] ]
},
'z-index': {
'cssPropBits': 69,
'cssLitGroup': [ L[ 38 ], L[ 47 ] ]
},
'zoom': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 55 ] ]
}
};
})();
if (typeof window !== 'undefined') {
window['cssSchema'] = cssSchema;
}
// Copyright (C) 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* A lexical scannar for CSS3 as defined at http://www.w3.org/TR/css3-syntax .
*
* @author Mike Samuel <mikesamuel@gmail.com>
* \@provides lexCss, decodeCss
* \@overrides window
*/
var lexCss;
var decodeCss;
(function () {
/**
* Decodes an escape sequence as specified in CSS3 section 4.1.
* http://www.w3.org/TR/css3-syntax/#characters
* @private
*/
function decodeCssEscape(s) {
var i = parseInt(s.substring(1), 16);
// If parseInt didn't find a hex diigt, it returns NaN so return the
// escaped character.
// Otherwise, parseInt will stop at the first non-hex digit so there's no
// need to worry about trailing whitespace.
if (i > 0xffff) {
// A supplemental codepoint.
return i -= 0x10000,
String.fromCharCode(
0xd800 + (i >> 10),
0xdc00 + (i & 0x3FF));
} else if (i == i) {
return String.fromCharCode(i);
} else if (s[1] < ' ') {
// "a backslash followed by a newline is ignored".
return '';
} else {
return s[1];
}
}
/**
* Returns an equivalent CSS string literal given plain text: foo -> "foo".
* @private
*/
function escapeCssString(s, replacer) {
return '"' + s.replace(/[\u0000-\u001f\\\"<>]/g, replacer) + '"';
}
/**
* Maps chars to CSS escaped equivalents: "\n" -> "\\a ".
* @private
*/
function escapeCssStrChar(ch) {
return cssStrChars[ch]
|| (cssStrChars[ch] = '\\' + ch.charCodeAt(0).toString(16) + ' ');
}
/**
* Maps chars to URI escaped equivalents: "\n" -> "%0a".
* @private
*/
function escapeCssUrlChar(ch) {
return cssUrlChars[ch]
|| (cssUrlChars[ch] = (ch < '\x10' ? '%0' : '%')
+ ch.charCodeAt(0).toString(16));
}
/**
* Mapping of CSS special characters to escaped equivalents.
* @private
*/
var cssStrChars = {
'\\': '\\\\'
};
/**
* Mapping of CSS special characters to URL-escaped equivalents.
* @private
*/
var cssUrlChars = {
'\\': '%5c'
};
// The comments below are copied from the CSS3 module syntax at
// http://www.w3.org/TR/css3-syntax .
// These string constants minify out when this is run-through closure
// compiler.
// Rules that have been adapted have comments prefixed with "Diff:", and
// where rules have been combined to avoid back-tracking in the regex engine
// or to work around limitations, there is a comment prefixed with
// "NewRule:".
// In the below, we assume CRLF and CR have been normalize to CR.
// wc ::= #x9 | #xA | #xC | #xD | #x20
var WC = '[\\t\\n\\f ]';
// w ::= wc*
var W = WC + '*';
// nl ::= #xA | #xD #xA | #xD | #xC
var NL = '[\\n\\f]';
// nonascii ::= [#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
// NewRule: Supplemental codepoints are represented as surrogate pairs in JS.
var SURROGATE_PAIR = '[\\ud800-\\udbff][\\udc00-\\udfff]';
var NONASCII = '[\\u0080-\\ud7ff\\ue000-\\ufffd]|' + SURROGATE_PAIR;
// unicode ::= '\' [0-9a-fA-F]{1,6} wc?
// NewRule: No point in having ESCAPE do (\\x|\\y)
var UNICODE_TAIL = '[0-9a-fA-F]{1,6}' + WC + '?';
var UNICODE = '\\\\' + UNICODE_TAIL;
// escape ::= unicode
// | '\' [#x20-#x7E#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
// NewRule: Below we use escape tail to efficiently match an escape or a
// line continuation so we can decode string content.
var ESCAPE_TAIL = '(?:' + UNICODE_TAIL
+ '|[\\u0020-\\u007e\\u0080-\\ud7ff\\ue000\\ufffd]|'
+ SURROGATE_PAIR + ')';
var ESCAPE = '\\\\' + ESCAPE_TAIL;
// urlchar ::= [#x9#x21#x23-#x26#x28-#x7E] | nonascii | escape
var URLCHAR = '(?:[\\t\\x21\\x23-\\x26\\x28-\\x5b\\x5d-\\x7e]|'
+ NONASCII + '|' + ESCAPE + ')';
// stringchar ::= urlchar | #x20 | '\' nl
// We ignore mismatched surrogate pairs inside strings, so stringchar
// simplifies to a non-(quote|newline|backslash) or backslash any.
// Since we normalize CRLF to a single code-unit, there is no special
// handling needed for '\\' + CRLF.
var STRINGCHAR = '[^\'"\\n\\f\\\\]|\\\\[\\s\\S]';
// string ::= '"' (stringchar | "'")* '"' | "'" (stringchar | '"')* "'"
var STRING = '"(?:\'|' + STRINGCHAR + ')*"'
+ '|\'(?:\"|' + STRINGCHAR + ')*\'';
// num ::= [0-9]+ | [0-9]* '.' [0-9]+
// Diff: We attach signs to num tokens.
var NUM = '[-+]?(?:[0-9]+(?:[.][0-9]+)?|[.][0-9]+)';
// nmstart ::= [a-zA-Z] | '_' | nonascii | escape
var NMSTART = '(?:[a-zA-Z_]|' + NONASCII + '|' + ESCAPE + ')';
// nmchar ::= [a-zA-Z0-9] | '-' | '_' | nonascii | escape
var NMCHAR = '(?:[a-zA-Z0-9_-]|' + NONASCII + '|' + ESCAPE + ')';
// name ::= nmchar+
var NAME = NMCHAR + '+';
// ident ::= '-'? nmstart nmchar*
var IDENT = '-?' + NMSTART + NMCHAR + '*';
// ATKEYWORD ::= '@' ident
var ATKEYWORD = '@' + IDENT;
// HASH ::= '#' name
var HASH = '#' + NAME;
// NUMBER ::= num
var NUMBER = NUM;
// NewRule: union of IDENT, ATKEYWORD, HASH, but excluding #[0-9].
var WORD_TERM = '(?:@?-?' + NMSTART + '|#)' + NMCHAR + '*';
// PERCENTAGE ::= num '%'
var PERCENTAGE = NUM + '%';
// DIMENSION ::= num ident
var DIMENSION = NUM + IDENT;
var NUMERIC_VALUE = NUM + '(?:%|' + IDENT + ')?';
// URI ::= "url(" w (string | urlchar* ) w ")"
var URI = 'url[(]' + W + '(?:' + STRING + '|' + URLCHAR + '*)' + W + '[)]';
// UNICODE-RANGE ::= "U+" [0-9A-F?]{1,6} ('-' [0-9A-F]{1,6})?
var UNICODE_RANGE = 'U[+][0-9A-F?]{1,6}(?:-[0-9A-F]{1,6})?';
// CDO ::= "<\!--"
var CDO = '<\!--';
// CDC ::= "-->"
var CDC = '-->';
// S ::= wc+
var S = WC + '+';
// COMMENT ::= "/*" [^*]* '*'+ ([^/] [^*]* '*'+)* "/"
// Diff: recognizes // comments.
var COMMENT = '/(?:[*][^*]*[*]+(?:[^/][^*]*[*]+)*/|/[^\\n\\f]*)';
// FUNCTION ::= ident '('
// Diff: We exclude url explicitly.
// TODO: should we be tolerant of "fn ("?
// ##### BEGIN: MODIFIED BY SAP
// Avoid risk of 'catastrophic backtracking' when unicode escapes are used
// var FUNCTION = '(?!url[(])' + IDENT + '[(]';
var FUNCTION = '(?!url[(])(?=(' + IDENT + '))\\1[(]';
// ##### END: MODIFIED BY SAP
// INCLUDES ::= "~="
var INCLUDES = '~=';
// DASHMATCH ::= "|="
var DASHMATCH = '[|]=';
// PREFIXMATCH ::= "^="
var PREFIXMATCH = '[^]=';
// SUFFIXMATCH ::= "$="
var SUFFIXMATCH = '[$]=';
// SUBSTRINGMATCH ::= "*="
var SUBSTRINGMATCH = '[*]=';
// NewRule: one rule for all the comparison operators.
var CMP_OPS = '[~|^$*]=';
// CHAR ::= any character not matched by the above rules, except for " or '
// Diff: We exclude / and \ since they are handled above to prevent
// /* without a following */ from combining when comments are concatenated.
var CHAR = '[^"\'\\\\/]|/(?![/*])';
// BOM ::= #xFEFF
var BOM = '\\uFEFF';
var CSS_TOKEN = new RegExp([
BOM, UNICODE_RANGE, URI, FUNCTION, WORD_TERM, STRING, NUMERIC_VALUE,
CDO, CDC, S, COMMENT, CMP_OPS, CHAR].join("|"), 'gi');
/**
* Decodes CSS escape sequences in a CSS string body.
*/
decodeCss = function (css) {
return css.replace(
new RegExp('\\\\(?:' + ESCAPE_TAIL + '|' + NL + ')', 'g'),
decodeCssEscape);
};
/**
* Given CSS Text, returns an array of normalized tokens.
* @param {string} cssText
* @return {Array.<string>} tokens where all ignorable token sequences have
* been reduced to a single {@code " "} and all strings and
* {@code url(...)} tokens have been normalized to use double quotes as
* delimiters and to not otherwise contain double quotes.
*/
lexCss = function (cssText) {
cssText = '' + cssText;
var tokens = cssText.replace(/\r\n?/g, '\n') // Normalize CRLF & CR to LF.
.match(CSS_TOKEN) || [];
var j = 0;
var last = ' ';
for (var i = 0, n = tokens.length; i < n; ++i) {
// Normalize all escape sequences. We will have to re-escape some
// codepoints in string and url(...) bodies but we already know the
// boundaries.
// We might mistakenly treat a malformed identifier like \22\20\22 as a
// string, but that will not break any valid stylesheets since we requote
// and re-escape in string below.
var tok = decodeCss(tokens[i]);
var len = tok.length;
var cc = tok.charCodeAt(0);
tok =
// All strings should be double quoted, and the body should never
// contain a double quote.
(cc == '"'.charCodeAt(0) || cc == '\''.charCodeAt(0))
? escapeCssString(tok.substring(1, len - 1), escapeCssStrChar)
// A breaking ignorable token should is replaced with a single space.
: (cc == '/'.charCodeAt(0) && len > 1 // Comment.
|| tok == '\\' || tok == CDC || tok == CDO || tok == '\ufeff'
// Characters in W.
|| cc <= ' '.charCodeAt(0))
? ' '
// Make sure that all url(...)s are double quoted.
: /url\(/i.test(tok)
? 'url(' + escapeCssString(
tok.replace(
new RegExp('^url\\(' + W + '["\']?|["\']?' + W + '\\)$', 'gi'),
''),
escapeCssUrlChar)
+ ')'
// Escapes in identifier like tokens will have been normalized above.
: tok;
// Merge adjacent space tokens.
if (last != tok || tok != ' ') {
tokens[j++] = last = tok;
}
}
tokens.length = j;
return tokens;
};
})();
// Exports for closure compiler.
if (typeof window !== 'undefined') {
window['lexCss'] = lexCss;
window['decodeCss'] = decodeCss;
}
// Copyright (C) 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview
* JavaScript support for client-side CSS sanitization.
* The CSS property schema API is defined in CssPropertyPatterns.java which
* is used to generate css-defs.js.
*
* @author mikesamuel@gmail.com
* \@requires CSS_PROP_BIT_ALLOWED_IN_LINK
* \@requires CSS_PROP_BIT_HASH_VALUE
* \@requires CSS_PROP_BIT_NEGATIVE_QUANTITY
* \@requires CSS_PROP_BIT_QSTRING_CONTENT
* \@requires CSS_PROP_BIT_QSTRING_URL
* \@requires CSS_PROP_BIT_QUANTITY
* \@requires CSS_PROP_BIT_Z_INDEX
* \@requires cssSchema
* \@requires decodeCss
* \@requires html4
* \@overrides window
* \@requires parseCssStylesheet
* \@provides sanitizeCssProperty
* \@provides sanitizeCssSelectors
* \@provides sanitizeStylesheet
*/
/**
* Given a series of normalized CSS tokens, applies a property schema, as
* defined in CssPropertyPatterns.java, and sanitizes the tokens in place.
* @param property a property name.
* @param propertySchema a property of cssSchema as defined by
* CssPropertyPatterns.java
* @param tokens as parsed by lexCss. Modified in place.
* @param opt_naiveUriRewriter a URI rewriter; an object with a "rewrite"
* function that takes a URL and returns a safe URL.
*/
var sanitizeCssProperty = (function () {
var NOEFFECT_URL = 'url("about:blank")';
/**
* The set of characters that need to be normalized inside url("...").
* We normalize newlines because they are not allowed inside quoted strings,
* normalize quote characters, angle-brackets, and asterisks because they
* could be used to break out of the URL or introduce targets for CSS
* error recovery. We normalize parentheses since they delimit unquoted
* URLs and calls and could be a target for error recovery.
*/
var NORM_URL_REGEXP = /[\n\f\r\"\'()*<>]/g;
/** The replacements for NORM_URL_REGEXP. */
var NORM_URL_REPLACEMENTS = {
'\n': '%0a',
'\f': '%0c',
'\r': '%0d',
'"': '%22',
'\'': '%27',
'(': '%28',
')': '%29',
'*': '%2a',
'<': '%3c',
'>': '%3e'
};
function normalizeUrl(s) {
if ('string' === typeof s) {
return 'url("' + s.replace(NORM_URL_REGEXP, normalizeUrlChar) + '")';
} else {
return NOEFFECT_URL;
}
}
function normalizeUrlChar(ch) {
return NORM_URL_REPLACEMENTS[ch];
}
// From RFC3986
var URI_SCHEME_RE = new RegExp(
'^' +
'(?:' +
'([^:\/?# ]+)' + // scheme
':)?'
);
var ALLOWED_URI_SCHEMES = /^(?:https?|mailto)$/i;
function safeUri(uri, prop, naiveUriRewriter) {
if (!naiveUriRewriter) { return null; }
var parsed = ('' + uri).match(URI_SCHEME_RE);
if (parsed && (!parsed[1] || ALLOWED_URI_SCHEMES.test(parsed[1]))) {
return naiveUriRewriter(uri, prop);
} else {
return null;
}
}
function unionArrays(arrs) {
var map = {};
for (var i = arrs.length; --i >= 0;) {
var arr = arrs[i];
for (var j = arr.length; --j >= 0;) {
map[arr[j]] = ALLOWED_LITERAL;
}
}
return map;
}
/**
* Normalize tokens within a function call they can match against
* cssSchema[propName].cssExtra.
* @return the exclusive end in tokens of the function call.
*/
function normalizeFunctionCall(tokens, start) {
var parenDepth = 1, end = start + 1, n = tokens.length;
while (end < n && parenDepth) {
// TODO: Can URLs appear in functions?
var token = tokens[end++];
parenDepth += (token === '(' ? 1 : token === ')' ? -1 : 0);
}
return end;
}
// Used as map value to avoid hasOwnProperty checks.
var ALLOWED_LITERAL = {};
return function (property, propertySchema, tokens, opt_naiveUriRewriter) {
var propBits = propertySchema.cssPropBits;
// Used to determine whether to treat quoted strings as URLs or
// plain text content, and whether unrecognized keywords can be quoted
// to treate ['Arial', 'Black'] equivalently to ['"Arial Black"'].
var qstringBits = propBits & (
CSS_PROP_BIT_QSTRING_CONTENT | CSS_PROP_BIT_QSTRING_URL);
// TODO(mikesamuel): Figure out what to do with props like
// content that admit both URLs and strings.
// Used to join unquoted keywords into a single quoted string.
var lastQuoted = NaN;
var i = 0, k = 0;
for (;i < tokens.length; ++i) {
// Has the effect of normalizing hex digits, keywords,
// and function names.
var token = tokens[i].toLowerCase();
var cc = token.charCodeAt(0), cc1, cc2, isnum1, isnum2, end;
var litGroup, litMap;
token = (
// Strip out spaces. Normally cssparser.js dumps these, but we
// strip them out in case the content doesn't come via cssparser.js.
(cc === ' '.charCodeAt(0)) ? ''
: (cc === '"'.charCodeAt(0)) ? ( // Quoted string.
(qstringBits === CSS_PROP_BIT_QSTRING_URL && opt_naiveUriRewriter)
// Sanitize and convert to url("...") syntax.
// Treat url content as case-sensitive.
? (normalizeUrl(safeUri(
decodeCss(tokens[i].substring(1, token.length - 1)),
property,
opt_naiveUriRewriter)))
// Drop if plain text content strings not allowed.
: (qstringBits === CSS_PROP_BIT_QSTRING_CONTENT) ? token : '')
// Preserve hash color literals if allowed.
: (cc === '#'.charCodeAt(0) && /^#(?:[0-9a-f]{3}){1,2}$/.test(token))
? (propBits & CSS_PROP_BIT_HASH_VALUE ? token : '')
: ('0'.charCodeAt(0) <= cc && cc <= '9'.charCodeAt(0))
// A number starting with a digit.
? ((propBits & CSS_PROP_BIT_QUANTITY)
? ((propBits & CSS_PROP_BIT_Z_INDEX)
? (token.match(/^\d{1,7}$/) ? token : '')
: token)
: '')
// Normalize quantities so they don't start with a '.' or '+' sign and
// make sure they all have an integer component so can't be confused
// with a dotted identifier.
// This can't be done in the lexer since ".4" is a valid rule part.
: (cc1 = token.charCodeAt(1),
cc2 = token.charCodeAt(2),
isnum1 = '0'.charCodeAt(0) <= cc1 && cc1 <= '9'.charCodeAt(0),
isnum2 = '0'.charCodeAt(0) <= cc2 && cc2 <= '9'.charCodeAt(0),
// +.5 -> 0.5 if allowed.
(cc === '+'.charCodeAt(0)
&& (isnum1 || (cc1 === '.'.charCodeAt(0) && isnum2))))
? ((propBits & CSS_PROP_BIT_QUANTITY)
? ((propBits & CSS_PROP_BIT_Z_INDEX)
? (token.match(/^\+\d{1,7}$/) ? token : '')
: ((isnum1 ? '' : '0') + token.substring(1)))
: '')
// -.5 -> -0.5 if allowed otherwise -> 0 if quantities allowed.
: (cc === '-'.charCodeAt(0)
&& (isnum1 || (cc1 === '.'.charCodeAt(0) && isnum2)))
? ((propBits & CSS_PROP_BIT_NEGATIVE_QUANTITY)
? ((propBits & CSS_PROP_BIT_Z_INDEX)
? (token.match(/^\-\d{1,7}$/) ? token : '')
: ((isnum1 ? '-' : '-0') + token.substring(1)))
: ((propBits & CSS_PROP_BIT_QUANTITY) ? '0' : ''))
// .5 -> 0.5 if allowed.
: (cc === '.'.charCodeAt(0) && isnum1)
? ((propBits & CSS_PROP_BIT_QUANTITY) ? '0' + token : '')
// Handle url("...") by rewriting the body.
: ('url(' === token.substring(0, 4))
? ((opt_naiveUriRewriter && (qstringBits & CSS_PROP_BIT_QSTRING_URL))
? normalizeUrl(safeUri(
tokens[i].substring(5, token.length - 2),
property,
opt_naiveUriRewriter))
: '')
// Handle func(...) and literal tokens
// such as keywords and punctuation.
: (
// Step 1. Combine func(...) into something that can be compared
// against propertySchema.cssExtra.
(token.charAt(token.length-1) === '(')
&& (end = normalizeFunctionCall(tokens, i),
// When tokens is
// ['x', ' ', 'rgb(', '255', ',', '0', ',', '0', ')', ' ', 'y']
// and i is the index of 'rgb(' and end is the index of ')'
// splices tokens to where i now is the index of the whole call:
// ['x', ' ', 'rgb( 255 , 0 , 0 )', ' ', 'y']
tokens.splice(i, end - i,
token = tokens.slice(i, end).join(' '))),
litGroup = propertySchema.cssLitGroup,
litMap = (litGroup
? (propertySchema.cssLitMap
// Lazily compute the union from litGroup.
|| (propertySchema.cssLitMap = unionArrays(litGroup)))
: ALLOWED_LITERAL), // A convenient empty object.
(litMap[token] === ALLOWED_LITERAL
|| propertySchema.cssExtra && propertySchema.cssExtra.test(token)))
// Token is in the literal map or matches extra.
? token
: (/^\w+$/.test(token)
&& (qstringBits === CSS_PROP_BIT_QSTRING_CONTENT))
// Quote unrecognized keywords so font names like
// Arial Bold
// ->
// "Arial Bold"
? (lastQuoted+1 === k
// If the last token was also a keyword that was quoted, then
// combine this token into that.
? (tokens[lastQuoted] = tokens[lastQuoted]
.substring(0, tokens[lastQuoted].length-1) + ' ' + token + '"',
token = '')
: (lastQuoted = k, '"' + token + '"'))
// Disallowed.
: '');
if (token) {
tokens[k++] = token;
}
}
// For single URL properties, if the URL failed to pass the sanitizer,
// then just drop it.
if (k === 1 && tokens[0] === NOEFFECT_URL) { k = 0; }
tokens.length = k;
};
})();
/**
* Given a series of tokens, returns two lists of sanitized selectors.
* @param {Array.<string>} selectors In the form produces by csslexer.js.
* @param {string} suffix a suffix that is added to all IDs and which is
* used as a CLASS names so that the returned selectors will only match
* nodes under one with suffix as a class name.
* If suffix is {@code "sfx"}, the selector
* {@code ["a", "#foo", " ", "b", ".bar"]} will be namespaced to
* {@code [".sfx", " ", "a", "#foo-sfx", " ", "b", ".bar"]}.
* @return {Array.<Array.<string>>} an array of length 2 where the zeroeth
* element contains history-insensitive selectors and the first element
* contains history-sensitive selectors.
*/
function sanitizeCssSelectors(selectors, suffix) {
// Produce two distinct lists of selectors to sequester selectors that are
// history sensitive (:visited), so that we can disallow properties in the
// property groups for the history sensitive ones.
var historySensitiveSelectors = [];
var historyInsensitiveSelectors = [];
// Remove any spaces that are not operators.
var k = 0, i;
for (i = 0; i < selectors.length; ++i) {
if (!(selectors[i] == ' '
&& (selectors[i-1] == '>' || selectors[i+1] == '>'))) {
selectors[k++] = selectors[i];
}
}
selectors.length = k;
// Split around commas. If there is an error in one of the comma separated
// bits, we throw the whole away, but the failure of one selector does not
// affect others.
var n = selectors.length, start = 0;
for (i = 0; i < n; ++i) {
if (selectors[i] == ',') {
processSelector(start, i);
start = i+1;
}
}
processSelector(start, n);
function processSelector(start, end) {
var historySensitive = false;
// Space around commas is not an operator.
if (selectors[start] === ' ') { ++start; }
if (end-1 !== start && selectors[end] === ' ') { --end; }
// Split the selector into element selectors, content around
// space (ancestor operator) and '>' (descendant operator).
var out = [];
var lastOperator = start;
var elSelector = '';
for (var i = start; i < end; ++i) {
var tok = selectors[i];
var isChild = (tok === '>');
if (isChild || tok === ' ') {
// We've found the end of a single link in the selector chain.
// We disallow absolute positions relative to html.
elSelector = processElementSelector(lastOperator, i, false);
if (!elSelector || (isChild && /^html/i.test(elSelector))) {
return;
}
lastOperator = i+1;
out.push(elSelector, isChild ? ' > ' : ' ');
}
}
elSelector = processElementSelector(lastOperator, end, true);
if (!elSelector) { return; }
out.push(elSelector);
function processElementSelector(start, end, last) {
var debugStart = start, debugEnd = end;
// Split the element selector into three parts.
// DIV.foo#bar:hover
// ^ ^
// el classes pseudo
var element, classId, pseudoSelector, tok, elType;
element = '';
if (start < end) {
tok = selectors[start].toLowerCase();
if (tok === '*'
|| (tok === 'body' && start+1 !== end && !last)
|| ('number' === typeof (elType = html4.ELEMENTS[tok])
&& !(elType & html4.eflags.UNSAFE))) {
++start;
element = tok;
}
}
classId = '';
while (start < end) {
tok = selectors[start];
if (tok.charAt(0) === '#') {
if (/^#_|__$|[^#0-9A-Za-z:_\-]/.test(tok)) { return null; }
// Rewrite ID elements to include the suffix.
classId += tok + '-' + suffix;
} else if (tok === '.') {
if (++start < end
&& /^[0-9A-Za-z:_\-]+$/.test(tok = selectors[start])
&& !/^_|__$/.test(tok)) {
classId += '.' + tok;
} else {
return null;
}
} else {
break;
}
++start;
}