google-caja
Version:
Node wrapper for the Google Caja HTML/CSS sanitizer
1,551 lines (1,494 loc) • 149 kB
JavaScript
var window = {};
/* Copyright Google Inc.
* Licensed under the Apache Licence Version 2.0
* Autogenerated at Sat May 04 18:26:48 CDT 2013
* \@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 ] + ' *$', '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' ], [ 'Courier New', '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[ 2 ],
'cssAlternates': [ 'boxShadow' ],
'cssPropBits': 7,
'cssLitGroup': [ L[ 0 ], L[ 35 ], L[ 48 ], L[ 54 ] ]
},
'-moz-opacity': {
'cssPropBits': 1,
'cssLitGroup': [ L[ 47 ] ]
},
'-moz-outline': {
'cssExtra': c[ 1 ],
'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[ 1 ],
'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[ 2 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 1 ],
'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[ 2 ],
'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[ 1 ],
'cssPropBits': 130,
'cssLitGroup': [ L[ 0 ], L[ 47 ] ]
},
'content': {
'cssPropBits': 8,
'cssLitGroup': [ L[ 54 ], L[ 55 ] ]
},
'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[ 1 ],
'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[ 1 ],
'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': 8,
'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[ 2 ],
'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 ("?
var FUNCTION = '(?!url[(])' + IDENT + '[(]';
// 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) 2010 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
* Implements RFC 3986 for parsing/formatting URIs.
*
* @author mikesamuel@gmail.com
* \@provides URI
* \@overrides window
*/
var URI = (function () {
/**
* creates a uri from the string form. The parser is relaxed, so special
* characters that aren't escaped but don't cause ambiguities will not cause
* parse failures.
*
* @return {URI|null}
*/
function parse(uriStr) {
var m = ('' + uriStr).match(URI_RE_);
if (!m) { return null; }
return new URI(
nullIfAbsent(m[1]),
nullIfAbsent(m[2]),
nullIfAbsent(m[3]),
nullIfAbsent(m[4]),
nullIfAbsent(m[5]),
nullIfAbsent(m[6]),
nullIfAbsent(m[7]));
}
/**
* creates a uri from the given parts.
*
* @param scheme {string} an unencoded scheme such as "http" or null
* @param credentials {string} unencoded user credentials or null
* @param domain {string} an unencoded domain name or null
* @param port {number} a port number in [1, 32768].
* -1 indicates no port, as does null.
* @param path {string} an unencoded path
* @param query {Array.<string>|string|null} a list of unencoded cgi
* parameters where even values are keys and odds the corresponding values
* or an unencoded query.
* @param fragment {string} an unencoded fragment without the "#" or null.
* @return {URI}
*/
function create(scheme, credentials, domain, port, path, query, fragment) {
var uri = new URI(
encodeIfExists2(scheme, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_),
encodeIfExists2(
credentials, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_),
encodeIfExists(domain),
port > 0 ? port.toString() : null,
encodeIfExists2(path, URI_DISALLOWED_IN_PATH_),
null,
encodeIfExists(fragment));
if (query) {
if ('string' === typeof query) {
uri.setRawQuery(query.replace(/[^?&=0-9A-Za-z_\-~.%]/g, encodeOne));
} else {
uri.setAllParameters(query);
}
}
return uri;
}
function encodeIfExists(unescapedPart) {
if ('string' == typeof unescapedPart) {
return encodeURIComponent(unescapedPart);
}
return null;
};
/**
* if unescapedPart is non null, then escapes any characters in it that aren't
* valid characters in a url and also escapes any special characters that
* appear in extra.
*
* @param unescapedPart {string}
* @param extra {RegExp} a character set of characters in [\01-\177].
* @return {string|null} null iff unescapedPart == null.
*/
function encodeIfExists2(unescapedPart, extra) {
if ('string' == typeof unescapedPart) {
return encodeURI(unescapedPart).replace(extra, encodeOne);
}
return null;
};
/** converts a character in [\01-\177] to its url encoded equivalent. */
function encodeOne(ch) {
var n = ch.charCodeAt(0);
return '%' + '0123456789ABCDEF'.charAt((n >> 4) & 0xf) +
'0123456789ABCDEF'.charAt(n & 0xf);
}
/**
* {@updoc
* $ normPath('foo/./bar')
* # 'foo/bar'
* $ normPath('./foo')
* # 'foo'
* $ normPath('foo/.')
* # 'foo'
* $ normPath('foo//bar')
* # 'foo/bar'
* }
*/
function normPath(path) {
return path.replace(/(^|\/)\.(?:\/|$)/g, '$1').replace(/\/{2,}/g, '/');
}
var PARENT_DIRECTORY_HANDLER = new RegExp(
''
// A path break
+ '(/|^)'
// followed by a non .. path element
// (cannot be . because normPath is used prior to this RegExp)
+ '(?:[^./][^/]*|\\.{2,}(?:[^./][^/]*)|\\.{3,}[^/]*)'
// followed by .. followed by a path break.
+ '/\\.\\.(?:/|$)');
var PARENT_DIRECTORY_HANDLER_RE = new RegExp(PARENT_DIRECTORY_HANDLER);
var EXTRA_PARENT_PATHS_RE = /^(?:\.\.\/)*(?:\.\.$)?/;
/**
* Normalizes its input path and collapses all . and .. sequences except for
* .. sequences that would take it above the root of the current parent
* directory.
* {@updoc
* $ collapse_dots('foo/../bar')
* # 'bar'
* $ collapse_dots('foo/./bar')
* # 'foo/bar'
* $ collapse_dots('foo/../bar/./../../baz')
* # 'baz'
* $ collapse_dots('../foo')
* # '../foo'
* $ collapse_dots('../foo').replace(EXTRA_PARENT_PATHS_RE, '')
* # 'foo'
* }
*/
function collapse_dots(path) {
if (path === null) { return null; }
var p = normPath(path);
// Only /../ left to flatten
var r = PARENT_DIRECTORY_HANDLER_RE;
// We replace with $1 which matches a / before the .. because this
// guarantees that:
// (1) we have at most 1 / between the adjacent place,
// (2) always have a slash if there is a preceding path section, and
// (3) we never turn a relative path into an absolute path.
for (var q; (q = p.replace(r, '$1')) != p; p = q) {};
return p;
}
/**
* resolves a relative url string to a base uri.
* @return {URI}
*/
function resolve(baseUri, relativeUri) {
// there are several kinds of relative urls:
// 1. //foo - replaces everything from the domain on. foo is a domain name
// 2. foo - replaces the last part of the path, the whole query and fragment
// 3. /foo - replaces the the path, the query and fragment
// 4. ?foo - replace the query and fragment
// 5. #foo - replace the fragment only
var absoluteUri = baseUri.clone();
// we satisfy these conditions by looking for the first part of relativeUri
// that is not blank and applying defaults to the rest
var overridden = relativeUri.hasScheme();
if (overridden) {
absoluteUri.setRawScheme(relativeUri.getRawScheme());
} else {
overridden = relativeUri.hasCredentials();
}
if (overridden) {
absoluteUri.setRawCredentials(relativeUri.getRawCredentials());
} else {
overridden = relativeUri.hasDomain();
}
if (overridden) {
absoluteUri.setRawDomain(relativeUri.getRawDomain());
} else {
overridden = relativeUri.hasPort();
}
var rawPath = relativeUri.getRawPath();
var simplifiedPath = collapse_dots(rawPath);
if (overridden) {
absoluteUri.setPort(relativeUri.getPort());
simplifiedPath = simplifiedPath
&& simplifiedPath.replace(EXTRA_PARENT_PATHS_RE, '');
} else {
overridden = !!rawPath;
if (overridden) {
// resolve path properly
if (simplifiedPath.charCodeAt(0) !== 0x2f /* / */) { // path is relative
var absRawPath = collapse_dots(absoluteUri.getRawPath() || '')
.replace(EXTRA_PARENT_PATHS_RE, '');
var slash = absRawPath.lastIndexOf('/') + 1;
simplifiedPath = collapse_dots(
(slash ? absRawPath.substring(0, slash) : '')
+ collapse_dots(rawPath))
.replace(EXTRA_PARENT_PATHS_RE, '');
}
} else {
simplifiedPath = simplifiedPath
&& simplifiedPath.replace(EXTRA_PARENT_PATHS_RE, '');
if (simplifiedPath !== rawPath) {
absoluteUri.setRawPath(simplifiedPath);
}
}
}
if (overridden) {
absoluteUri.setRawPath(simplifiedPath);
} else {
overridden = relativeUri.hasQuery();
}
if (overridden) {
absoluteUri.setRawQuery(relativeUri.getRawQuery());
} else {
overridden = relativeUri.hasFragment();
}
if (overridden) {
absoluteUri.setRawFragment(relativeUri.getRawFragment());
}
return absoluteUri;
}
/**
* a mutable URI.
*
* This class contains setters and getters for the parts of the URI.
* The <tt>getXYZ</tt>/<tt>setXYZ</tt> methods return the decoded part -- so
* <code>uri.parse('/foo%20bar').getPath()</code> will return the decoded path,
* <tt>/foo bar</tt>.
*
* <p>The raw versions of fields are available too.
* <code>uri.parse('/foo%20bar').getRawPath()</code> will return the raw path,
* <tt>/foo%20bar</tt>. Use the raw setters with care, since
* <code>URI::toString</code> is not guaranteed to return a valid url if a
* raw setter was used.
*
* <p>All setters return <tt>this</tt> and so may be chained, a la
* <code>uri.parse('/foo').setFragment('part').toString()</code>.
*
* <p>You should not use this constructor directly -- please prefer the factory
* functions {@link uri.parse}, {@link uri.create}, {@link uri.resolve}
* instead.</p>
*
* <p>The parameters are all raw (assumed to be properly escaped) parts, and
* any (but not all) may be null. Undefined is not allowed.</p>
*
* @constructor
*/
function URI(
rawScheme,
rawCredentials, rawDomain, port,
rawPath, rawQuery, rawFragment) {
this.scheme_ = rawScheme;
this.credentials_ = rawCredentials;
this.domain_ = rawDomain;
this.port_ = port;
this.path_ = rawPath;
this.query_ = rawQuery;
this.fragment_ = rawFragment;
/**
* @type {Array|null}
*/
this.paramCache_ = null;
}
/** returns the string form of the url. */
URI.prototype.toString = function () {
var out = [];
if (null !== this.scheme_) { out.push(this.scheme_, ':'); }
if (null !== this.domain_) {
out.push('//');
if (null !== this.credentials_) { out.push(this.credentials_, '@'); }
out.push(this.domain_);
if (null !== this.port_) { out.push(':', this.port_.toString()); }
}
if (null !== this.path_) { out.push(this.path_); }
if (null !== this.query_) { out.push('?', this.query_); }
if (null !== this.fragment_) { out.push('#', this.fragment_); }
return out.join('');
};
URI.prototype.clone = function () {
return new URI(this.scheme_, this.credentials_, this.domain_, this.port_,
this.path_, this.query_, this.fragment_);
};
URI.prototype.getScheme = function () {
// HTML5 spec does not require the scheme to be lowercased but
// all common browsers except Safari lowercase the scheme.
return this.scheme_ && decodeURIComponent(this.scheme_).toLowerCase();
};
URI.prototype.getRawScheme = function () {
return this.scheme_;
};
URI.prototype.setScheme = function (newScheme) {
this.scheme_ = encodeIfExists2(
newScheme, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_);
return this;
};
URI.prototype.setRawScheme = function (newScheme) {
this.scheme_ = newScheme ? newScheme : null;
return this;
};
URI.prototype.hasScheme = function () {
return null !== this.scheme_;
};
URI.prototype.getCredentials = function () {
return this.credentials_ && decodeURIComponent(this.credentials_);
};
URI.prototype.getRawCredentials = function () {
return this.credentials_;
};
URI.prototype.setCredentials = function (newCredentials) {
this.credentials_ = encodeIfExists2(
newCredentials, URI_DISALLOWED_IN_SCHEME_OR_CREDENTIALS_);
return this;
};
URI.prototype.setRawCredentials = function (newCredentials) {
this.credentials_ = newCredentials ? newCredentials : null;
return this;
};
URI.prototype.hasCredentials = function () {
return null !== this.credentials_;
};
URI.prototype.getDomain = function () {
return this.domain_ && decodeURIComponent(this.domain_);
};
URI.prototype.getRawDomain = function () {
return this.domain_;
};
URI.prototype.setDomain = function (newDomain) {
return this.setRawDomain(newDomain && encodeURIComponent(newDomain));
};
URI.prototype.setRawDomain = function (newDomain) {
this.domain_ = newDomain ? newDomain : null;
// Maintain the invariant that paths must start with a slash when the URI
// is not path-relative.
return this.setRawPath(this.path_);
};
URI.prototype.hasDomain = function () {
return null !== this.domain_;
};
URI.prototype.getPort = function () {
return this.port_ && decodeURIComponent(this.port_);
};
URI.prototype.setPort = function (newPort) {
if (newPort) {
newPort = Number(newPort);
if (newPort !== (newPort & 0xffff)) {
throw new Error('Bad port number ' + newPort);
}
this.port_ = '' + newPort;
} else {
this.port_ = null;
}
return this;
};
URI.prototype.hasPort = function () {
return null !== this.port_;
};
URI.prototype.getPath = function () {
return this.path_ && decodeURIComponent(this.path_);
};
URI.prototype.getRawPath = function () {
return this.path_;
};
URI.prototype.setPath = function (newPath) {
return this.setRawPath(encodeIfExists2(newPath, URI_DISALLOWED_IN_PATH_));
};
URI.prototype.setRawPath = function (newPath) {
if (newPath) {
newPath = String(newPath);
this.path_ =
// Paths must start with '/' unless this is a path-relative URL.
(!this.domain_ || /^\//.test(newPath)) ? newPath : '/' + newPath;
} else {
this.path_ = null;
}
return this;
};
URI.prototype.hasPath = function () {
return null !== this.path_;
};
URI.prototype.getQuery = function () {
// From http://www.w3.org/Addressing/URL/4_URI_Recommentations.html
// Within the query string, the plus sign is reserved as shorthand notation
// for a space.
return this.query_ && decodeURIComponent(this.query_).replace(/\+/g, ' ');
};
URI.prototype.getRawQuery = function () {
return this.query_;
};
URI.prototype.setQuery = function (newQuery) {
this.paramCache_ = null;
this.query_ = encodeIfExists(newQuery);
return this;
};
URI.prototype.setRawQuery = function (newQuery) {
this.paramCache_ = null;
this.query_ = newQuery ? newQuery : null;
return this;
};
URI.prototype.hasQuery = function () {
return null !== this.query_;
};
/**
* sets the query given a list of strings of the form
* [ key0, value0, key1, value1, ... ].
*
* <p><code>uri.setAllParameters(['a', 'b', 'c', 'd']).getQuery()</code>
* will yield <code>'a=b&c=d'</code>.
*/
URI.prototype.setAllParameters = function (params) {
if (typeof params === 'object') {
if (!(params instanceof Array)
&& (params instanceof Object
|| Object.prototype.toString.call(params) !== '[object Array]')) {
var newParams = [];
var i = -1;
for (var k in params) {
var v = params[k];
if ('string' === typeof v) {
newParams[++i] = k;
newParams[++i] = v;
}
}
params = newParams;
}
}
this.paramCache_ = null;
var queryBuf = [];
var separator = '';
for (var j = 0; j < params.length;) {
var k = params[j++];
var v = params[j++];
queryBuf.push(separator, encodeURIComponent(k.toString()));
separator = '&';
if (v) {
queryBuf.push('=', encodeURIComponent(v.toString()));
}
}
this.query_ = queryBuf.join('');
return this;
};
URI.prototype.c