UNPKG

google-caja

Version:

Node wrapper for the Google Caja HTML/CSS sanitizer

1,551 lines (1,494 loc) 149 kB
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