Created
August 23, 2013 22:24
-
-
Save lcaballero/6324608 to your computer and use it in GitHub Desktop.
CSS Parser in JavaScript. Fork of cssParser (see the lisence and comments).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* ***** BEGIN LICENSE BLOCK ***** | |
| * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| * | |
| * The contents of this file are subject to the Mozilla Public License Version | |
| * 1.1 (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.mozilla.org/MPL/ | |
| * | |
| * Software distributed under the License is distributed on an "AS IS" basis, | |
| * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| * for the specific language governing rights and limitations under the | |
| * License. | |
| * | |
| * The Original Code is mozilla.org code. | |
| * | |
| * The Initial Developer of the Original Code is | |
| * Netscape Communications Corporation. | |
| * Portions created by the Initial Developer are Copyright (C) 1998 | |
| * the Initial Developer. All Rights Reserved. | |
| * | |
| * Contributor(s): | |
| * emk <VYV03354@nifty.ne.jp> | |
| * Daniel Glazman <glazman@netscape.com> | |
| * L. David Baron <dbaron@dbaron.org> | |
| * Boris Zbarsky <bzbarsky@mit.edu> | |
| * Mats Palmgren <mats.palmgren@bredband.net> | |
| * Christian Biesinger <cbiesinger@web.de> | |
| * Jeff Walden <jwalden+code@mit.edu> | |
| * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>, Collabora Ltd. | |
| * Siraj Razick <siraj.razick@collabora.co.uk>, Collabora Ltd. | |
| * Daniel Glazman <daniel.glazman@disruptive-innovations.com> | |
| * | |
| * Alternatively, the contents of this file may be used under the terms of | |
| * either of the GNU General Public License Version 2 or later (the "GPL"), | |
| * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| * in which case the provisions of the GPL or the LGPL are applicable instead | |
| * of those above. If you wish to allow use of your version of this file only | |
| * under the terms of either the GPL or the LGPL, and not to allow others to | |
| * use your version of this file under the terms of the MPL, indicate your | |
| * decision by deleting the provisions above and replace them with the notice | |
| * and other provisions required by the GPL or the LGPL. If you do not delete | |
| * the provisions above, a recipient may use your version of this file under | |
| * the terms of any one of the MPL, the GPL or the LGPL. | |
| * | |
| * ***** END LICENSE BLOCK ***** */ | |
| var kCHARSET_RULE_MISSING_SEMICOLON = "Missing semicolon at the end of @charset rule"; | |
| var kCHARSET_RULE_CHARSET_IS_STRING = "The charset in the @charset rule should be a string"; | |
| var kCHARSET_RULE_MISSING_WS = "Missing mandatory whitespace after @charset"; | |
| var kIMPORT_RULE_MISSING_URL = "Missing URL in @import rule"; | |
| var kURL_EOF = "Unexpected end of stylesheet"; | |
| var kURL_WS_INSIDE = "Multiple tokens inside a url() notation"; | |
| var kVARIABLES_RULE_POSITION = "@variables rule invalid at this position in the stylesheet"; | |
| var kIMPORT_RULE_POSITION = "@import rule invalid at this position in the stylesheet"; | |
| var kNAMESPACE_RULE_POSITION = "@namespace rule invalid at this position in the stylesheet"; | |
| var kCHARSET_RULE_CHARSET_SOF = "@charset rule invalid at this position in the stylesheet"; | |
| var kUNKNOWN_AT_RULE = "Unknow @-rule"; | |
| /* FROM http://peter.sh/data/vendor-prefixed-css.php?js=1 */ | |
| var kCSS_VENDOR_VALUES = { | |
| "-moz-box": {"webkit": "-webkit-box", "presto": "", "trident": "", "generic": "box" }, | |
| "-moz-inline-box": {"webkit": "-webkit-inline-box", "presto": "", "trident": "", "generic": "inline-box" }, | |
| "-moz-initial": {"webkit": "", "presto": "", "trident": "", "generic": "initial" }, | |
| "flex": {"webkit": "-webkit-flex", "presto": "", "trident": "", "generic": "" }, | |
| "inline-flex": {"webkit": "-webkit-inline-flex", "presto": "", "trident": "", "generic": "" }, | |
| "linear-gradient": {"webkit20110101":FilterLinearGradient, | |
| "webkit": FilterLinearGradient, | |
| "presto": FilterLinearGradient, | |
| "trident": FilterLinearGradient, | |
| "gecko1.9.2": FilterLinearGradient }, | |
| "repeating-linear-gradient": {"webkit20110101":FilterLinearGradient, | |
| "webkit": FilterLinearGradient, | |
| "presto": FilterLinearGradient, | |
| "trident": FilterLinearGradient, | |
| "gecko1.9.2": FilterLinearGradient }, | |
| "radial-gradient": {"webkit20110101":FilterRadialGradient, | |
| "webkit": FilterRadialGradient, | |
| "presto": FilterRadialGradient, | |
| "trident": FilterRadialGradient, | |
| "gecko1.9.2": FilterRadialGradient }, | |
| "repeating-radial-gradient": {"webkit20110101":FilterRadialGradient, | |
| "webkit": FilterRadialGradient, | |
| "presto": FilterRadialGradient, | |
| "trident": FilterRadialGradient, | |
| "gecko1.9.2": FilterRadialGradient } | |
| }; | |
| var kCSS_PREFIXED_VALUE = [ | |
| {"gecko": "-moz-box", "webkit": "-moz-box", "presto": "", "trident": "", "generic": "box"} | |
| ]; | |
| var kCSS_VENDOR_PREFIXES = | |
| {"lastUpdate":1374677405,"properties":[ | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-accelerator","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"-wap-accesskey","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-align-content","presto":"","trident":"","status":""}, | |
| {"gecko":"align-items","webkit":"-webkit-align-items","presto":"","trident":"","status":""}, | |
| {"gecko":"align-self","webkit":"-webkit-align-self","presto":"","trident":"","status":""}, | |
| {"gecko":"animation","webkit":"-webkit-animation","presto":"","trident":"animation","status":"WD"}, | |
| {"gecko":"animation-delay","webkit":"-webkit-animation-delay","presto":"","trident":"animation-delay","status":"WD"}, | |
| {"gecko":"animation-direction","webkit":"-webkit-animation-direction","presto":"","trident":"animation-direction","status":"WD"}, | |
| {"gecko":"animation-duration","webkit":"-webkit-animation-duration","presto":"","trident":"animation-duration","status":"WD"}, | |
| {"gecko":"animation-fill-mode","webkit":"-webkit-animation-fill-mode","presto":"","trident":"animation-fill-mode","status":"ED"}, | |
| {"gecko":"animation-iteration-count","webkit":"-webkit-animation-iteration-count","presto":"","trident":"animation-iteration-count","status":"WD"}, | |
| {"gecko":"animation-name","webkit":"-webkit-animation-name","presto":"","trident":"animation-name","status":"WD"}, | |
| {"gecko":"animation-play-state","webkit":"-webkit-animation-play-state","presto":"","trident":"animation-play-state","status":"WD"}, | |
| {"gecko":"animation-timing-function","webkit":"-webkit-animation-timing-function","presto":"","trident":"animation-timing-function","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-app-region","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-appearance","webkit":"-webkit-appearance","presto":"","trident":"","status":"CR"}, | |
| {"gecko":"","webkit":"-webkit-aspect-ratio","presto":"","trident":"","status":""}, | |
| {"gecko":"backface-visibility","webkit":"-webkit-backface-visibility","presto":"","trident":"backface-visibility","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-background-blend-mode","presto":"","trident":"","status":""}, | |
| {"gecko":"background-clip","webkit":"-webkit-background-clip","presto":"background-clip","trident":"background-clip","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-background-composite","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-background-inline-policy","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"background-origin","webkit":"-webkit-background-origin","presto":"background-origin","trident":"background-origin","status":"WD"}, | |
| {"gecko":"","webkit":"background-position-x","presto":"","trident":"-ms-background-position-x","status":""}, | |
| {"gecko":"","webkit":"background-position-y","presto":"","trident":"-ms-background-position-y","status":""}, | |
| {"gecko":"background-size","webkit":"-webkit-background-size","presto":"background-size","trident":"background-size","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-behavior","status":""}, | |
| {"gecko":"-moz-binding","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-blend-mode","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-block-progression","status":""}, | |
| {"gecko":"","webkit":"-webkit-border-after","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-after-color","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-after-style","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-after-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-before","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-before-color","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-before-style","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-before-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-bottom-colors","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"border-bottom-left-radius","webkit":"-webkit-border-bottom-left-radius","presto":"border-bottom-left-radius","trident":"border-bottom-left-radius","status":"WD"}, | |
| {"gecko":"border-bottom-right-radius","webkit":"-webkit-border-bottom-right-radius","presto":"border-bottom-right-radius","trident":"border-bottom-right-radius","status":"WD"}, | |
| {"gecko":"-moz-border-end","webkit":"-webkit-border-end","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-end-color","webkit":"-webkit-border-end-color","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-end-style","webkit":"-webkit-border-end-style","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-end-width","webkit":"-webkit-border-end-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-border-fit","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-border-horizontal-spacing","presto":"","trident":"","status":""}, | |
| {"gecko":"border-image","webkit":"-webkit-border-image","presto":"-o-border-image","trident":"","status":"WD"}, | |
| {"gecko":"-moz-border-left-colors","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"border-radius","webkit":"-webkit-border-radius","presto":"border-radius","trident":"border-radius","status":"WD"}, | |
| {"gecko":"-moz-border-right-colors","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-border-start","webkit":"-webkit-border-start","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-start-color","webkit":"-webkit-border-start-color","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-start-style","webkit":"-webkit-border-start-style","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-start-width","webkit":"-webkit-border-start-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-border-top-colors","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"border-top-left-radius","webkit":"-webkit-border-top-left-radius","presto":"border-top-left-radius","trident":"border-top-left-radius","status":"WD"}, | |
| {"gecko":"border-top-right-radius","webkit":"-webkit-border-top-right-radius","presto":"border-top-right-radius","trident":"border-top-right-radius","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-border-vertical-spacing","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-box-align","webkit":"-webkit-box-align","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-box-decoration-break","presto":"box-decoration-break","trident":"","status":"WD"}, | |
| {"gecko":"-moz-box-direction","webkit":"-webkit-box-direction","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"-moz-box-flex","webkit":"-webkit-box-flex","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-box-flex-group","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-box-lines","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"-moz-box-ordinal-group","webkit":"-webkit-box-ordinal-group","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"-moz-box-orient","webkit":"-webkit-box-orient","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"-moz-box-pack","webkit":"-webkit-box-pack","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-box-reflect","presto":"","trident":"","status":""}, | |
| {"gecko":"box-shadow","webkit":"-webkit-box-shadow","presto":"box-shadow","trident":"box-shadow","status":"WD"}, | |
| {"gecko":"-moz-box-sizing","webkit":"-webkit-box-sizing","presto":"box-sizing","trident":"box-sizing","status":"CR"}, | |
| {"gecko":"caption-side","webkit":"-epub-caption-side","presto":"caption-side","trident":"caption-side","status":""}, | |
| {"gecko":"clip-path","webkit":"-webkit-clip-path","presto":"clip-path","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-color-correction","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-column-axis","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-column-break-after","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-column-break-before","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-column-break-inside","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-column-count","webkit":"-webkit-column-count","presto":"column-count","trident":"column-count","status":"CR"}, | |
| {"gecko":"-moz-column-fill","webkit":"","presto":"column-fill","trident":"column-fill","status":"CR"}, | |
| {"gecko":"-moz-column-gap","webkit":"-webkit-column-gap","presto":"column-gap","trident":"column-gap","status":"CR"}, | |
| {"gecko":"","webkit":"-webkit-column-progression","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-column-rule","webkit":"-webkit-column-rule","presto":"column-rule","trident":"column-rule","status":"CR"}, | |
| {"gecko":"-moz-column-rule-color","webkit":"-webkit-column-rule-color","presto":"column-rule-color","trident":"column-rule-color","status":"CR"}, | |
| {"gecko":"-moz-column-rule-style","webkit":"-webkit-column-rule-style","presto":"column-rule-style","trident":"column-rule-style","status":"CR"}, | |
| {"gecko":"-moz-column-rule-width","webkit":"-webkit-column-rule-width","presto":"column-rule-width","trident":"column-rule-width","status":"CR"}, | |
| {"gecko":"","webkit":"-webkit-column-span","presto":"column-span","trident":"column-span","status":"CR"}, | |
| {"gecko":"-moz-column-width","webkit":"-webkit-column-width","presto":"column-width","trident":"column-width","status":"CR"}, | |
| {"gecko":"-moz-columns","webkit":"-webkit-columns","presto":"columns","trident":"columns","status":"CR"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-chaining","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-limit","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-limit-max","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-limit-min","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-snap","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-snap-points","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zoom-snap-type","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-content-zooming","status":""}, | |
| {"gecko":"","webkit":"-webkit-cursor-visibility","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-dashboard-region","presto":"-apple-dashboard-region","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-o-device-pixel-ratio","trident":"","status":""}, | |
| {"gecko":"filter","webkit":"-webkit-filter","presto":"filter","trident":"-ms-filter","status":""}, | |
| {"gecko":"flex","webkit":"-webkit-flex","presto":"","trident":"-ms-flex","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-flex-align","status":""}, | |
| {"gecko":"flex-basis","webkit":"-webkit-flex-basis","presto":"","trident":"","status":""}, | |
| {"gecko":"flex-direction","webkit":"-webkit-flex-direction","presto":"","trident":"-ms-flex-direction","status":""}, | |
| {"gecko":"","webkit":"-webkit-flex-flow","presto":"","trident":"","status":""}, | |
| {"gecko":"flex-grow","webkit":"-webkit-flex-grow","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-flex-order","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-flex-pack","status":""}, | |
| {"gecko":"flex-shrink","webkit":"-webkit-flex-shrink","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-flex-wrap","presto":"","trident":"-ms-flex-wrap","status":""}, | |
| {"gecko":"-moz-float-edge","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-flow-from","presto":"","trident":"-ms-flow-from","status":""}, | |
| {"gecko":"","webkit":"-webkit-flow-into","presto":"","trident":"-ms-flow-into","status":""}, | |
| {"gecko":"","webkit":"","presto":"-o-focus-opacity","trident":"","status":""}, | |
| {"gecko":"-moz-font-feature-settings","webkit":"-webkit-font-feature-settings","presto":"","trident":"font-feature-settings","status":""}, | |
| {"gecko":"font-kerning","webkit":"-webkit-font-kerning","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-font-language-override","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-font-size-delta","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-font-smoothing","presto":"","trident":"","status":""}, | |
| {"gecko":"font-variant-ligatures","webkit":"-webkit-font-variant-ligatures","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-force-broken-image-icon","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-after","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-auto-columns","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-auto-flow","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-auto-rows","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-before","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-column","presto":"","trident":"-ms-grid-column","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-column-align","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-column-span","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-columns","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-grid-definition-columns","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-definition-rows","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-end","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-grid-row","presto":"","trident":"-ms-grid-row","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-row-align","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-row-span","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-rows","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-grid-start","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-high-contrast-adjust","status":""}, | |
| {"gecko":"","webkit":"-webkit-highlight","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-hyphenate-character","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-hyphenate-limit-after","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-hyphenate-limit-before","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-hyphenate-limit-chars","status":""}, | |
| {"gecko":"","webkit":"-webkit-hyphenate-limit-lines","presto":"","trident":"-ms-hyphenate-limit-lines","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-hyphenate-limit-zone","status":""}, | |
| {"gecko":"-moz-hyphens","webkit":"-epub-hyphens","presto":"","trident":"-ms-hyphens","status":"WD"}, | |
| {"gecko":"-moz-image-region","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"ime-mode","webkit":"","presto":"","trident":"-ms-ime-mode","status":""}, | |
| {"gecko":"","webkit":"","presto":"-wap-input-format","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-wap-input-required","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-interpolation-mode","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-interpret-as","trident":"","status":""}, | |
| {"gecko":"justify-content","webkit":"-webkit-justify-content","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-flow","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-char","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-line","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-mode","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-type","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-align","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-box-contain","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-break","presto":"","trident":"line-break","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-clamp","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-grid","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-line-snap","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-o-link","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-o-link-source","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-locale","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-logical-height","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-logical-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-margin-after","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-margin-after-collapse","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-margin-before","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-margin-before-collapse","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-margin-bottom-collapse","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-margin-collapse","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-margin-end","webkit":"-webkit-margin-end","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-margin-start","webkit":"-webkit-margin-start","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-margin-top-collapse","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-marquee","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-wap-marquee-dir","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-marquee-direction","presto":"","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-marquee-increment","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-wap-marquee-loop","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-marquee-repetition","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-marquee-speed","presto":"-wap-marquee-speed","trident":"","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-marquee-style","presto":"-wap-marquee-style","trident":"","status":"WD"}, | |
| {"gecko":"mask","webkit":"-webkit-mask","presto":"mask","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image-outset","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image-repeat","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image-slice","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image-source","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-box-image-width","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-clip","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-composite","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-image","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-origin","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-position","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-position-x","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-position-y","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-repeat","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-repeat-x","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-repeat-y","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-mask-size","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-max-logical-height","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-max-logical-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-min-logical-height","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-min-logical-width","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"","presto":"-o-mini-fold","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-nbsp-mode","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"-o-object-fit","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"","presto":"-o-object-position","trident":"","status":"ED"}, | |
| {"gecko":"opacity","webkit":"-webkit-opacity","presto":"opacity","trident":"opacity","status":"WD"}, | |
| {"gecko":"order","webkit":"-webkit-order","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-orient","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-outline-radius","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-outline-radius-bottomleft","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-outline-radius-bottomright","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-outline-radius-topleft","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-outline-radius-topright","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-overflow-scrolling","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-overflow-style","status":"CR"}, | |
| {"gecko":"overflow-x","webkit":"overflow-x","presto":"overflow-x","trident":"-ms-overflow-x","status":"WD"}, | |
| {"gecko":"overflow-y","webkit":"overflow-y","presto":"overflow-y","trident":"-ms-overflow-y","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-padding-after","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"","webkit":"-webkit-padding-before","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-padding-end","webkit":"-webkit-padding-end","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"-moz-padding-start","webkit":"-webkit-padding-start","presto":"","trident":"","status":"ED"}, | |
| {"gecko":"perspective","webkit":"-webkit-perspective","presto":"","trident":"perspective","status":"WD"}, | |
| {"gecko":"perspective-origin","webkit":"-webkit-perspective-origin","presto":"","trident":"perspective-origin","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-perspective-origin-x","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-perspective-origin-y","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-phonemes","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-print-color-adjust","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-progress-appearance","status":""}, | |
| {"gecko":"","webkit":"-webkit-region-break-after","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-region-break-before","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-region-break-inside","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-region-fragment","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-rtl-ordering","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-ruby-position","presto":"","trident":"ruby-position","status":"CR"}, | |
| {"gecko":"-moz-script-level","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-script-min-size","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-script-size-multiplier","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-chaining","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-limit","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-limit-x-max","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-limit-x-min","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-limit-y-max","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-limit-y-min","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-rails","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-snap-points-x","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-snap-points-y","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-snap-type","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-snap-x","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-snap-y","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-scroll-translation","status":""}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-arrow-color","trident":"-ms-scrollbar-arrow-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-base-color","trident":"-ms-scrollbar-base-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-darkshadow-color","trident":"-ms-scrollbar-darkshadow-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-face-color","trident":"-ms-scrollbar-face-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-highlight-color","trident":"-ms-scrollbar-highlight-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-shadow-color","trident":"-ms-scrollbar-shadow-color","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"scrollbar-track-color","trident":"-ms-scrollbar-track-color","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-shape-inside","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-shape-margin","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-shape-outside","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-shape-padding","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-stack-sizing","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-svg-shadow","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-tab-size","webkit":"tab-size","presto":"-o-tab-size","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-o-table-baseline","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-tap-highlight-color","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-text-align-last","webkit":"-webkit-text-align-last","presto":"","trident":"-ms-text-align-last","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-text-autospace","status":"WD"}, | |
| {"gecko":"-moz-text-blink","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-epub-text-combine","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-text-decoration-color","webkit":"-webkit-text-decoration-color","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-text-decoration-line","webkit":"-webkit-text-decoration-line","presto":"","trident":"","status":""}, | |
| {"gecko":"-moz-text-decoration-style","webkit":"-webkit-text-decoration-style","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-text-decorations-in-effect","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-epub-text-emphasis","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-epub-text-emphasis-color","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-text-emphasis-position","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-epub-text-emphasis-style","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-text-fill-color","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-text-justify","presto":"","trident":"-ms-text-justify","status":"WD"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-text-kashida-space","status":"P"}, | |
| {"gecko":"","webkit":"-epub-text-orientation","presto":"","trident":"","status":""}, | |
| {"gecko":"text-overflow","webkit":"text-overflow","presto":"text-overflow","trident":"-ms-text-overflow","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-text-security","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-text-size-adjust","webkit":"","presto":"","trident":"","status":""}, | |
| {"gecko":"","webkit":"-webkit-text-stroke","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-text-stroke-color","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-text-stroke-width","presto":"","trident":"","status":"P"}, | |
| {"gecko":"text-transform","webkit":"-epub-text-transform","presto":"text-transform","trident":"text-transform","status":""}, | |
| {"gecko":"","webkit":"-webkit-text-underline-position","presto":"","trident":"-ms-text-underline-position","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-touch-action","status":""}, | |
| {"gecko":"","webkit":"-webkit-touch-callout","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-transform","webkit":"-webkit-transform","presto":"-o-transform","trident":"transform","status":"WD"}, | |
| {"gecko":"transform-origin","webkit":"-webkit-transform-origin","presto":"-o-transform-origin","trident":"transform-origin","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-transform-origin-x","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-transform-origin-y","presto":"","trident":"","status":"P"}, | |
| {"gecko":"","webkit":"-webkit-transform-origin-z","presto":"","trident":"","status":"P"}, | |
| {"gecko":"transform-style","webkit":"-webkit-transform-style","presto":"","trident":"transform-style","status":"WD"}, | |
| {"gecko":"transition","webkit":"-webkit-transition","presto":"-o-transition","trident":"transition","status":"WD"}, | |
| {"gecko":"transition-delay","webkit":"-webkit-transition-delay","presto":"-o-transition-delay","trident":"transition-delay","status":"WD"}, | |
| {"gecko":"transition-duration","webkit":"-webkit-transition-duration","presto":"-o-transition-duration","trident":"transition-duration","status":"WD"}, | |
| {"gecko":"transition-property","webkit":"-webkit-transition-property","presto":"-o-transition-property","trident":"transition-property","status":"WD"}, | |
| {"gecko":"transition-timing-function","webkit":"-webkit-transition-timing-function","presto":"-o-transition-timing-function","trident":"transition-timing-function","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-user-drag","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-user-focus","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-user-input","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-user-modify","webkit":"-webkit-user-modify","presto":"","trident":"","status":"P"}, | |
| {"gecko":"-moz-user-select","webkit":"-webkit-user-select","presto":"","trident":"-ms-user-select","status":"P"}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-balance","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-duration","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-pitch","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-pitch-range","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-rate","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-stress","trident":"","status":""}, | |
| {"gecko":"","webkit":"","presto":"-xv-voice-volume","trident":"","status":""}, | |
| {"gecko":"-moz-window-shadow","webkit":"","presto":"","trident":"","status":"P"}, | |
| {"gecko":"word-break","webkit":"-epub-word-break","presto":"","trident":"-ms-word-break","status":"WD"}, | |
| {"gecko":"word-wrap","webkit":"word-wrap","presto":"word-wrap","trident":"-ms-word-wrap","status":"WD"}, | |
| {"gecko":"","webkit":"-webkit-wrap-flow","presto":"","trident":"-ms-wrap-flow","status":""}, | |
| {"gecko":"","webkit":"","presto":"","trident":"-ms-wrap-margin","status":""}, | |
| {"gecko":"","webkit":"-webkit-wrap-through","presto":"","trident":"-ms-wrap-through","status":""}, | |
| {"gecko":"writing-mode","webkit":"-epub-writing-mode","presto":"writing-mode","trident":"-ms-writing-mode","status":"ED"}, | |
| {"gecko":"","webkit":"zoom","presto":"","trident":"-ms-zoom","status":""}]}; | |
| var PrefixHelper = { | |
| mVENDOR_PREFIXES: null, | |
| kEXPORTS_FOR_GECKO: true, | |
| kEXPORTS_FOR_WEBKIT: true, | |
| kEXPORTS_FOR_PRESTO: true, | |
| kEXPORTS_FOR_TRIDENT: true, | |
| cleanPrefixes: function() | |
| { | |
| this.mVENDOR_PREFIXES = null; | |
| }, | |
| prefixesForProperty: function(aProperty) | |
| { | |
| if (!this.mVENDOR_PREFIXES) { | |
| this.mVENDOR_PREFIXES = {}; | |
| for (var i = 0; i < kCSS_VENDOR_PREFIXES.properties.length; i++) { | |
| var p = kCSS_VENDOR_PREFIXES.properties[i]; | |
| if (p.gecko && (p.webkit || p.presto || p.trident)) { | |
| var o = {}; | |
| if (this.kEXPORTS_FOR_GECKO) o[p.gecko] = true; | |
| if (this.kEXPORTS_FOR_WEBKIT && p.webkit) o[p.webkit] = true; | |
| if (this.kEXPORTS_FOR_PRESTO && p.presto) o[p.presto] = true; | |
| if (this.kEXPORTS_FOR_TRIDENT && p.trident) o[p.trident] = true; | |
| this.mVENDOR_PREFIXES[p.gecko] = []; | |
| for (var j in o) | |
| this.mVENDOR_PREFIXES[p.gecko].push(j) | |
| } | |
| } | |
| } | |
| if (aProperty in this.mVENDOR_PREFIXES) | |
| return this.mVENDOR_PREFIXES[aProperty].sort(); | |
| return null; | |
| } | |
| }; | |
| function ParseURL(buffer) { | |
| var result = { }; | |
| result.protocol = ""; | |
| result.user = ""; | |
| result.password = ""; | |
| result.host = ""; | |
| result.port = ""; | |
| result.path = ""; | |
| result.query = ""; | |
| var section = "PROTOCOL"; | |
| var start = 0; | |
| var wasSlash = false; | |
| while(start < buffer.length) { | |
| if(section == "PROTOCOL") { | |
| if(buffer.charAt(start) == ':') { | |
| section = "AFTER_PROTOCOL"; | |
| start++; | |
| } else if(buffer.charAt(start) == '/' && result.protocol.length() == 0) { | |
| section = PATH; | |
| } else { | |
| result.protocol += buffer.charAt(start++); | |
| } | |
| } else if(section == "AFTER_PROTOCOL") { | |
| if(buffer.charAt(start) == '/') { | |
| if(!wasSlash) { | |
| wasSlash = true; | |
| } else { | |
| wasSlash = false; | |
| section = "USER"; | |
| } | |
| start ++; | |
| } else { | |
| throw new ParseException("Protocol shell be separated with 2 slashes"); | |
| } | |
| } else if(section == "USER") { | |
| if(buffer.charAt(start) == '/') { | |
| result.host = result.user; | |
| result.user = ""; | |
| section = "PATH"; | |
| } else if(buffer.charAt(start) == '?') { | |
| result.host = result.user; | |
| result.user = ""; | |
| section = "QUERY"; | |
| start++; | |
| } else if(buffer.charAt(start) == ':') { | |
| section = "PASSWORD"; | |
| start++; | |
| } else if(buffer.charAt(start) == '@') { | |
| section = "HOST"; | |
| start++; | |
| } else { | |
| result.user += buffer.charAt(start++); | |
| } | |
| } else if(section == "PASSWORD") { | |
| if(buffer.charAt(start) == '/') { | |
| result.host = result.user; | |
| result.port = result.password; | |
| result.user = ""; | |
| result.password = ""; | |
| section = "PATH"; | |
| } else if(buffer.charAt(start) == '?') { | |
| result.host = result.user; | |
| result.port = result.password; | |
| result.user = ""; | |
| result.password = ""; | |
| section = "QUERY"; | |
| start ++; | |
| } else if(buffer.charAt(start) == '@') { | |
| section = "HOST"; | |
| start++; | |
| } else { | |
| result.password += buffer.charAt(start++); | |
| } | |
| } else if(section == "HOST") { | |
| if(buffer.charAt(start) == '/') { | |
| section = "PATH"; | |
| } else if(buffer.charAt(start) == ':') { | |
| section = "PORT"; | |
| start++; | |
| } else if(buffer.charAt(start) == '?') { | |
| section = "QUERY"; | |
| start++; | |
| } else { | |
| result.host += buffer.charAt(start++); | |
| } | |
| } else if(section == "PORT") { | |
| if(buffer.charAt(start) == '/') { | |
| section = "PATH"; | |
| } else if(buffer.charAt(start) == '?') { | |
| section = "QUERY"; | |
| start++; | |
| } else { | |
| result.port += buffer.charAt(start++); | |
| } | |
| } else if(section == "PATH") { | |
| if(buffer.charAt(start) == '?') { | |
| section = "QUERY"; | |
| start ++; | |
| } else { | |
| result.path += buffer.charAt(start++); | |
| } | |
| } else if(section == "QUERY") { | |
| result.query += buffer.charAt(start++); | |
| } | |
| } | |
| if(section == "PROTOCOL") { | |
| result.host = result.protocol; | |
| result.protocol = "http"; | |
| } else if(section == "AFTER_PROTOCOL") { | |
| throw new ParseException("Invalid url"); | |
| } else if(section == "USER") { | |
| result.host = result.user; | |
| result.user = ""; | |
| } else if(section == "PASSWORD") { | |
| result.host = result.user; | |
| result.port = result.password; | |
| result.user = ""; | |
| result.password = ""; | |
| } | |
| return result; | |
| } | |
| function ParseException(description) { | |
| this.description = description; | |
| } | |
| function CountLF(s) | |
| { | |
| var nCR = s.match( /\n/g ); | |
| return nCR ? nCR.length + 1 : 1; | |
| } | |
| function DisposablePartialParsing(aStringToParse, aMethodName) | |
| { | |
| var parser = new CSSParser(); | |
| parser._init(); | |
| parser.mPreserveWS = false; | |
| parser.mPreserveComments = false; | |
| parser.mPreservedTokens = []; | |
| parser.mScanner.init(aStringToParse); | |
| return parser[aMethodName](); | |
| } | |
| function FilterLinearGradient(aValue, aEngine) | |
| { | |
| var d = DisposablePartialParsing(aValue, "parseBackgroundImages"); | |
| if (!d) | |
| return null; | |
| var g = d[0]; | |
| if (!g.value) | |
| return null; | |
| var str = ""; | |
| var position = ("position" in g.value) ? g.value.position.toLowerCase() : ""; | |
| var angle = ("angle" in g.value) ? g.value.angle.toLowerCase() : ""; | |
| if ("webkit20110101" == aEngine) { | |
| var cancelled = false; | |
| str = "-webkit-gradient(linear, "; | |
| // normalize angle | |
| if (angle) { | |
| var match = angle.match(/^([0-9\-\.\\+]+)([a-z]*)/); | |
| var angle = parseFloat(match[1]); | |
| var unit = match[2]; | |
| switch (unit) { | |
| case "grad": angle = angle * 90 / 100; break; | |
| case "rad": angle = angle * 180 / Math.PI; break; | |
| default: break; | |
| } | |
| while (angle < 0) | |
| angle += 360; | |
| while (angle >= 360) | |
| angle -= 360; | |
| } | |
| // get startpoint w/o keywords | |
| var startpoint = []; | |
| var endpoint = []; | |
| if (position != "") { | |
| if (position == "center") | |
| position = "center center"; | |
| startpoint = position.split(" "); | |
| if (angle == "" && angle != 0) { | |
| // no angle, then we just turn the point 180 degrees around center | |
| switch (startpoint[0]) { | |
| case "left": endpoint.push("right"); break; | |
| case "center": endpoint.push("center"); break; | |
| case "right": endpoint.push("left"); break; | |
| default: { | |
| var match = startpoint[0].match(/^([0-9\-\.\\+]+)([a-z]*)/); | |
| var v = parseFloat(match[0]); | |
| var unit = match[1]; | |
| if (unit == "%") { | |
| endpoint.push((100-v) + "%"); | |
| } | |
| else | |
| cancelled = true; | |
| } | |
| break; | |
| } | |
| if (!cancelled) | |
| switch (startpoint[1]) { | |
| case "top": endpoint.push("bottom"); break; | |
| case "center": endpoint.push("center"); break; | |
| case "bottom": endpoint.push("top"); break; | |
| default: { | |
| var match = startpoint[1].match(/^([0-9\-\.\\+]+)([a-z]*)/); | |
| var v = parseFloat(match[0]); | |
| var unit = match[1]; | |
| if (unit == "%") { | |
| endpoint.push((100-v) + "%"); | |
| } | |
| else | |
| cancelled = true; | |
| } | |
| break; | |
| } | |
| } | |
| else { | |
| switch (angle) { | |
| case 0: endpoint.push("right"); endpoint.push(startpoint[1]); break; | |
| case 90: endpoint.push(startpoint[0]); endpoint.push("top"); break; | |
| case 180: endpoint.push("left"); endpoint.push(startpoint[1]); break; | |
| case 270: endpoint.push(startpoint[0]); endpoint.push("bottom"); break; | |
| default: cancelled = true; break; | |
| } | |
| } | |
| } | |
| else { | |
| // no position defined, we accept only vertical and horizontal | |
| if (angle == "") | |
| angle = 270; | |
| switch (angle) { | |
| case 0: startpoint= ["left", "center"]; endpoint = ["right", "center"]; break; | |
| case 90: startpoint= ["center", "bottom"]; endpoint = ["center", "top"]; break; | |
| case 180: startpoint= ["right", "center"]; endpoint = ["left", "center"]; break; | |
| case 270: startpoint= ["center", "top"]; endpoint = ["center", "bottom"]; break; | |
| default: cancelled = true; break; | |
| } | |
| } | |
| if (cancelled) | |
| return ""; | |
| str += startpoint.join(" ") + ", " + endpoint.join(" "); | |
| if (!g.value.stops[0].position) | |
| g.value.stops[0].position = "0%"; | |
| if (!g.value.stops[g.value.stops.length-1].position) | |
| g.value.stops[g.value.stops.length-1].position = "100%"; | |
| var current = 0; | |
| for (var i = 0; i < g.value.stops.length && !cancelled; i++) { | |
| var s = g.value.stops[i]; | |
| if (s.position) { | |
| if (s.position.indexOf("%") == -1) { | |
| cancelled = true; | |
| break; | |
| } | |
| } | |
| else { | |
| var j = i + 1; | |
| while (j < g.value.stops.length && !g.value.stops[j].position) | |
| j++; | |
| var inc = parseFloat(g.value.stops[j].position) - current; | |
| for (var k = i; k < j; k++) { | |
| g.value.stops[k].position = (current + inc * (k - i + 1) / (j - i + 1)) + "%"; | |
| } | |
| } | |
| current = parseFloat(s.position); | |
| str += ", color-stop(" + (parseFloat(current) / 100) + ", " + s.color + ")"; | |
| } | |
| if (cancelled) | |
| return ""; | |
| } | |
| else { | |
| str = (g.value.isRepeating ? "repeating-" : "") + "linear-gradient("; | |
| if (angle || position) | |
| str += (angle ? angle : position) + ", "; | |
| for (var i = 0; i < g.value.stops.length; i++) { | |
| var s = g.value.stops[i]; | |
| str += s.color | |
| + (s.position ? " " + s.position : "") | |
| + ((i != g.value.stops.length -1) ? ", " : ""); | |
| } | |
| } | |
| str += ")"; | |
| switch (aEngine) { | |
| case "webkit": str = "-webkit-" + str; break; | |
| case "gecko1.9.2": str = "-moz-" + str; break; | |
| case "presto": str = "-o-" + str; break; | |
| case "trident": str = "-ms-" + str; break; | |
| default: break; | |
| } | |
| return str; | |
| } | |
| function FilterRadialGradient(aValue, aEngine) | |
| { | |
| var d = DisposablePartialParsing(aValue, "parseBackgroundImages"); | |
| if (!d) | |
| return null; | |
| var g = d[0]; | |
| if (!g.value) | |
| return null; | |
| // oh come on, this is now so painful to deal with ; no way I'm going to implement this | |
| if ("webkit20110101" == aEngine) | |
| return null; | |
| var str = (g.value.isRepeating ? "repeating-" : "") + "radial-gradient("; | |
| var shape = ("shape" in g.value) ? g.value.shape : ""; | |
| var extent = ("extent" in g.value) ? g.value.extent : ""; | |
| var lengths = ""; | |
| switch (g.value.positions.length) { | |
| case 1: | |
| lengths = g.value.positions[0] + " " + g.value.positions[0]; | |
| break; | |
| case 2: | |
| lengths = g.value.positions[0] + " " + g.value.positions[1]; | |
| break; | |
| default: | |
| break; | |
| } | |
| var at = g.value.at; | |
| str += (at ? at + ", " : "") | |
| + ((shape || extent || at) | |
| ? (shape ? shape + " " : "") | |
| + (extent ? extent + " " : "") | |
| + (lengths ? lengths + " " : "") | |
| + ", " | |
| : ""); | |
| for (var i = 0; i < g.value.stops.length; i++) { | |
| var s = g.value.stops[i]; | |
| str += s.color | |
| + (s.position ? " " + s.position : "") | |
| + ((i != g.value.stops.length -1) ? ", " : ""); | |
| } | |
| str += ")"; | |
| switch (aEngine) { | |
| case "webkit": str = "-webkit-" + str; break; | |
| case "gecko1.9.2": str = "-moz-" + str; break; | |
| case "presto": str = "-o-" + str; break; | |
| case "trident": str = "-ms-" + str; break; | |
| default: break; | |
| } | |
| return str; | |
| } | |
| var CSS_ESCAPE = '\\'; | |
| var IS_HEX_DIGIT = 1; | |
| var START_IDENT = 2; | |
| var IS_IDENT = 4; | |
| var IS_WHITESPACE = 8; | |
| var W = IS_WHITESPACE; | |
| var I = IS_IDENT; | |
| var S = START_IDENT; | |
| var SI = IS_IDENT|START_IDENT; | |
| var XI = IS_IDENT |IS_HEX_DIGIT; | |
| var XSI = IS_IDENT|START_IDENT|IS_HEX_DIGIT; | |
| function CSSScanner(aString) | |
| { | |
| this.init(aString); | |
| } | |
| CSSScanner.prototype = { | |
| kLexTable: [ | |
| // TAB LF FF CR | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, W, W, 0, W, W, 0, 0, | |
| // | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| // SPC ! " # $ % & ' ( ) * + , - . / | |
| W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, I, 0, 0, | |
| // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? | |
| XI, XI, XI, XI, XI, XI, XI, XI, XI, XI, 0, 0, 0, 0, 0, 0, | |
| // @ A B C D E F G H I J K L M N O | |
| 0, XSI,XSI,XSI,XSI,XSI,XSI,SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // P Q R S T U V W X Y Z [ \ ] ^ _ | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, 0, S, 0, 0, SI, | |
| // ` a b c d e f g h i j k l m n o | |
| 0, XSI,XSI,XSI,XSI,XSI,XSI,SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // p q r s t u v w x y z { | } ~ | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, 0, 0, 0, 0, 0, | |
| // | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| // | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| // ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬  ® ¯ | |
| 0, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // À à Â Ã Ä Å Æ Ç È É Ê Ë Ì à Î à | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // à Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü à Þ ß | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // à á â ã ä å æ ç è é ê ë ì à î ï | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, | |
| // ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ | |
| SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI | |
| ], | |
| kHexValues: { | |
| "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, | |
| "a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15 | |
| }, | |
| mString : "", | |
| mPos : 0, | |
| mPreservedPos : [], | |
| init: function(aString) { | |
| this.mString = aString; | |
| this.mPos = 0; | |
| this.mPreservedPos = []; | |
| }, | |
| getCurrentPos: function() { | |
| return this.mPos; | |
| }, | |
| getAlreadyScanned: function() | |
| { | |
| return this.mString.substr(0, this.mPos); | |
| }, | |
| preserveState: function() { | |
| this.mPreservedPos.push(this.mPos); | |
| }, | |
| restoreState: function() { | |
| if (this.mPreservedPos.length) { | |
| this.mPos = this.mPreservedPos.pop(); | |
| } | |
| }, | |
| forgetState: function() { | |
| if (this.mPreservedPos.length) { | |
| this.mPreservedPos.pop(); | |
| } | |
| }, | |
| read: function() { | |
| if (this.mPos < this.mString.length) | |
| return this.mString.charAt(this.mPos++); | |
| return -1; | |
| }, | |
| peek: function() { | |
| if (this.mPos < this.mString.length) | |
| return this.mString.charAt(this.mPos); | |
| return -1; | |
| }, | |
| isHexDigit: function(c) { | |
| var code = c.charCodeAt(0); | |
| return (code < 256 && (this.kLexTable[code] & IS_HEX_DIGIT) != 0); | |
| }, | |
| isIdentStart: function(c) { | |
| var code = c.charCodeAt(0); | |
| return (code >= 256 || (this.kLexTable[code] & START_IDENT) != 0); | |
| }, | |
| startsWithIdent: function(aFirstChar, aSecondChar) { | |
| var code = aFirstChar.charCodeAt(0); | |
| return this.isIdentStart(aFirstChar) || | |
| (aFirstChar == "-" && this.isIdentStart(aSecondChar)); | |
| }, | |
| isIdent: function(c) { | |
| var code = c.charCodeAt(0); | |
| return (code >= 256 || (this.kLexTable[code] & IS_IDENT) != 0); | |
| }, | |
| pushback: function() { | |
| this.mPos--; | |
| }, | |
| nextHexValue: function() { | |
| var c = this.read(); | |
| if (c == -1 || !this.isHexDigit(c)) | |
| return new jscsspToken(jscsspToken.NULL_TYPE, null); | |
| var s = c; | |
| c = this.read(); | |
| while (c != -1 && this.isHexDigit(c)) { | |
| s += c; | |
| c = this.read(); | |
| } | |
| if (c != -1) | |
| this.pushback(); | |
| return new jscsspToken(jscsspToken.HEX_TYPE, s); | |
| }, | |
| gatherEscape: function() { | |
| var c = this.peek(); | |
| if (c == -1) | |
| return ""; | |
| if (this.isHexDigit(c)) { | |
| var code = 0; | |
| for (var i = 0; i < 6; i++) { | |
| c = this.read(); | |
| if (this.isHexDigit(c)) | |
| code = code * 16 + this.kHexValues[c.toLowerCase()]; | |
| else if (!this.isHexDigit(c) && !this.isWhiteSpace(c)) { | |
| this.pushback(); | |
| break; | |
| } | |
| else | |
| break; | |
| } | |
| if (i == 6) { | |
| c = this.peek(); | |
| if (this.isWhiteSpace(c)) | |
| this.read(); | |
| } | |
| return String.fromCharCode(code); | |
| } | |
| c = this.read(); | |
| if (c != "\n") | |
| return c; | |
| return ""; | |
| }, | |
| gatherIdent: function(c) { | |
| var s = ""; | |
| if (c == CSS_ESCAPE) | |
| s += this.gatherEscape(); | |
| else | |
| s += c; | |
| c = this.read(); | |
| while (c != -1 | |
| && (this.isIdent(c) || c == CSS_ESCAPE)) { | |
| if (c == CSS_ESCAPE) | |
| s += this.gatherEscape(); | |
| else | |
| s += c; | |
| c = this.read(); | |
| } | |
| if (c != -1) | |
| this.pushback(); | |
| return s; | |
| }, | |
| parseIdent: function(c) { | |
| var value = this.gatherIdent(c); | |
| var nextChar = this.peek(); | |
| if (nextChar == "(") { | |
| value += this.read(); | |
| return new jscsspToken(jscsspToken.FUNCTION_TYPE, value); | |
| } | |
| return new jscsspToken(jscsspToken.IDENT_TYPE, value); | |
| }, | |
| isDigit: function(c) { | |
| return (c >= '0') && (c <= '9'); | |
| }, | |
| parseComment: function(c) { | |
| var s = c; | |
| while ((c = this.read()) != -1) { | |
| s += c; | |
| if (c == "*") { | |
| c = this.read(); | |
| if (c == -1) | |
| break; | |
| if (c == "/") { | |
| s += c; | |
| break; | |
| } | |
| this.pushback(); | |
| } | |
| } | |
| return new jscsspToken(jscsspToken.COMMENT_TYPE, s); | |
| }, | |
| parseNumber: function(c) { | |
| var s = c; | |
| var foundDot = false; | |
| while ((c = this.read()) != -1) { | |
| if (c == ".") { | |
| if (foundDot) | |
| break; | |
| else { | |
| s += c; | |
| foundDot = true; | |
| } | |
| } else if (this.isDigit(c)) | |
| s += c; | |
| else | |
| break; | |
| } | |
| if (c != -1 && this.startsWithIdent(c, this.peek())) { // DIMENSION | |
| var unit = this.gatherIdent(c); | |
| s += unit; | |
| return new jscsspToken(jscsspToken.DIMENSION_TYPE, s, unit); | |
| } | |
| else if (c == "%") { | |
| s += "%"; | |
| return new jscsspToken(jscsspToken.PERCENTAGE_TYPE, s); | |
| } | |
| else if (c != -1) | |
| this.pushback(); | |
| return new jscsspToken(jscsspToken.NUMBER_TYPE, s); | |
| }, | |
| parseString: function(aStop) { | |
| var s = aStop; | |
| var previousChar = aStop; | |
| var c; | |
| while ((c = this.read()) != -1) { | |
| if (c == aStop && previousChar != CSS_ESCAPE) { | |
| s += c; | |
| break; | |
| } | |
| else if (c == CSS_ESCAPE) { | |
| c = this.peek(); | |
| if (c == -1) | |
| break; | |
| else if (c == "\n" || c == "\r" || c == "\f") { | |
| d = c; | |
| c = this.read(); | |
| // special for Opera that preserves \r\n... | |
| if (d == "\r") { | |
| c = this.peek(); | |
| if (c == "\n") | |
| c = this.read(); | |
| } | |
| } | |
| else { | |
| s += this.gatherEscape(); | |
| c = this.peek(); | |
| } | |
| } | |
| else if (c == "\n" || c == "\r" || c == "\f") { | |
| break; | |
| } | |
| else | |
| s += c; | |
| previousChar = c; | |
| } | |
| return new jscsspToken(jscsspToken.STRING_TYPE, s); | |
| }, | |
| isWhiteSpace: function(c) { | |
| var code = c.charCodeAt(0); | |
| return code < 256 && (this.kLexTable[code] & IS_WHITESPACE) != 0; | |
| }, | |
| eatWhiteSpace: function(c) { | |
| var s = c; | |
| while ((c = this.read()) != -1) { | |
| if (!this.isWhiteSpace(c)) | |
| break; | |
| s += c; | |
| } | |
| if (c != -1) | |
| this.pushback(); | |
| return s; | |
| }, | |
| parseAtKeyword: function(c) { | |
| return new jscsspToken(jscsspToken.ATRULE_TYPE, this.gatherIdent(c)); | |
| }, | |
| nextToken: function() { | |
| var c = this.read(); | |
| if (c == -1) | |
| return new jscsspToken(jscsspToken.NULL_TYPE, null); | |
| if (this.startsWithIdent(c, this.peek())) | |
| return this.parseIdent(c); | |
| if (c == '@') { | |
| var nextChar = this.read(); | |
| if (nextChar != -1) { | |
| var followingChar = this.peek(); | |
| this.pushback(); | |
| if (this.startsWithIdent(nextChar, followingChar)) | |
| return this.parseAtKeyword(c); | |
| } | |
| } | |
| if (c == "." || c == "+" || c == "-") { | |
| var nextChar = this.peek(); | |
| if (this.isDigit(nextChar)) | |
| return this.parseNumber(c); | |
| else if (nextChar == "." && c != ".") { | |
| firstChar = this.read(); | |
| var secondChar = this.peek(); | |
| this.pushback(); | |
| if (this.isDigit(secondChar)) | |
| return this.parseNumber(c); | |
| } | |
| } | |
| if (this.isDigit(c)) { | |
| return this.parseNumber(c); | |
| } | |
| if (c == "'" || c == '"') | |
| return this.parseString(c); | |
| if (this.isWhiteSpace(c)) { | |
| var s = this.eatWhiteSpace(c); | |
| return new jscsspToken(jscsspToken.WHITESPACE_TYPE, s); | |
| } | |
| if (c == "|" || c == "~" || c == "^" || c == "$" || c == "*") { | |
| var nextChar = this.read(); | |
| if (nextChar == "=") { | |
| switch (c) { | |
| case "~" : | |
| return new jscsspToken(jscsspToken.INCLUDES_TYPE, "~="); | |
| case "|" : | |
| return new jscsspToken(jscsspToken.DASHMATCH_TYPE, "|="); | |
| case "^" : | |
| return new jscsspToken(jscsspToken.BEGINSMATCH_TYPE, "^="); | |
| case "$" : | |
| return new jscsspToken(jscsspToken.ENDSMATCH_TYPE, "$="); | |
| case "*" : | |
| return new jscsspToken(jscsspToken.CONTAINSMATCH_TYPE, "*="); | |
| default : | |
| break; | |
| } | |
| } else if (nextChar != -1) | |
| this.pushback(); | |
| } | |
| if (c == "/" && this.peek() == "*") | |
| return this.parseComment(c); | |
| return new jscsspToken(jscsspToken.SYMBOL_TYPE, c); | |
| } | |
| }; | |
| CSSParser.prototype.parseBackgroundImages = function() | |
| { | |
| var backgrounds = []; | |
| var token = this.getToken(true, true); | |
| while (token.isNotNull()) { | |
| if (token.isFunction("url(")) { | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| backgrounds.push( { type: "image", value: "url(" + urlContent }); | |
| token = this.getToken(true, true); | |
| } | |
| else if (token.isFunction("linear-gradient(") | |
| || token.isFunction("radial-gradient(") | |
| || token.isFunction("repeating-linear-gradient(") | |
| || token.isFunction("repeating-radial-gradient(")) { | |
| this.ungetToken(); | |
| var gradient = this.parseGradient(); | |
| if (gradient) { | |
| backgrounds.push({ | |
| type: gradient.isRadial ? "radial-gradient" : "linear-gradient", | |
| value: gradient | |
| }); | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return null; | |
| } | |
| else if (token.isIdent("none") | |
| || token.isIdent("inherit") | |
| || token.isIdent("initial")) { | |
| backgrounds.push( { type: token.value }); | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return null; | |
| if (token.isSymbol(",")) { | |
| token = this.getToken(true, true); | |
| if (!token.isNotNull()) | |
| return null; | |
| } | |
| } | |
| return backgrounds; | |
| }; | |
| CSSParser.prototype.parseBackgroundShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var kHPos = { | |
| "left" : true, | |
| "right" : true | |
| }; | |
| var kVPos = { | |
| "top" : true, | |
| "bottom" : true | |
| }; | |
| var kPos = { | |
| "left" : true, | |
| "right" : true, | |
| "top" : true, | |
| "bottom" : true, | |
| "center" : true | |
| }; | |
| var bgColor = null; | |
| var bgRepeat = null; | |
| var bgAttachment = null; | |
| var bgImage = null; | |
| var bgPosition = null; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!bgColor | |
| && !bgRepeat | |
| && !bgAttachment | |
| && !bgImage | |
| && !bgPosition | |
| && token.isIdent(this.kINHERIT)) { | |
| bgColor = this.kINHERIT; | |
| bgRepeat = this.kINHERIT; | |
| bgAttachment = this.kINHERIT; | |
| bgImage = this.kINHERIT; | |
| bgPosition = this.kINHERIT; | |
| } | |
| else { | |
| if (!bgAttachment | |
| && (token.isIdent("scroll") || token.isIdent("fixed"))) { | |
| bgAttachment = token.value; | |
| } | |
| else if (!bgPosition | |
| && ((token.isIdent() && token.value in kPos) | |
| || token.isDimension() | |
| || token.isNumber("0") | |
| || token.isPercentage())) { | |
| bgPosition = token.value; | |
| token = this.getToken(true, true); | |
| if (token.isDimension() | |
| || token.isNumber("0") | |
| || token.isPercentage()) { | |
| bgPosition += " " + token.value; | |
| } else if (token.isIdent() && token.value in kPos) { | |
| if ((bgPosition in kHPos && token.value in kHPos) | |
| || (bgPosition in kVPos && token.value in kVPos)) | |
| return ""; | |
| bgPosition += " " + token.value; | |
| } else { | |
| this.ungetToken(); | |
| bgPosition += " center"; | |
| } | |
| } | |
| else if (!bgRepeat | |
| && (token.isIdent("repeat") | |
| || token.isIdent("repeat-x") | |
| || token.isIdent("repeat-y") | |
| || token.isIdent("no-repeat"))) { | |
| bgRepeat = token.value; | |
| } | |
| else if (!bgImage | |
| && (token.isFunction("url(") || token.isIdent("none"))) { | |
| bgImage = token.value; | |
| if (token.isFunction("url(")) { | |
| token = this.getToken(true, true); | |
| var url = this.parseURL(token); // TODO | |
| if (url) | |
| bgImage += url; | |
| else | |
| return ""; | |
| } | |
| } | |
| else if (!bgImage | |
| && (token.isFunction("linear-gradient(") | |
| || token.isFunction("radial-gradient(") | |
| || token.isFunction("repeating-linear-gradient(") || token.isFunction("repeating-radial-gradient("))) { | |
| this.ungetToken(); | |
| var gradient = this.parseGradient(); | |
| if (gradient) | |
| bgImage = this.serializeGradient(gradient); | |
| else | |
| return ""; | |
| } | |
| else { | |
| var color = this.parseColor(token); | |
| if (!bgColor && color) | |
| bgColor = color; | |
| else | |
| return ""; | |
| } | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| // create the declarations | |
| this.forgetState(); | |
| bgColor = bgColor ? bgColor : "transparent"; | |
| bgImage = bgImage ? bgImage : "none"; | |
| bgRepeat = bgRepeat ? bgRepeat : "repeat"; | |
| bgAttachment = bgAttachment ? bgAttachment : "scroll"; | |
| bgPosition = bgPosition ? bgPosition : "top left"; | |
| aDecl.push(this._createJscsspDeclarationFromValue("background-color", bgColor)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("background-image", bgImage)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("background-repeat", bgRepeat)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("background-attachment", bgAttachment)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("background-position", bgPosition)); | |
| return bgColor + " " + bgImage + " " + bgRepeat + " " + bgAttachment + " " + bgPosition; | |
| }; | |
| CSSParser.prototype.parseBorderColorShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var top = null; | |
| var bottom = null; | |
| var left = null; | |
| var right = null; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| token = this.getToken(true, true); | |
| break; | |
| } | |
| else { | |
| var color = this.parseColor(token); | |
| if (color) | |
| values.push(color); | |
| else | |
| return ""; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| top = values[0]; | |
| bottom = top; | |
| left = top; | |
| right = top; | |
| break; | |
| case 2: | |
| top = values[0]; | |
| bottom = top; | |
| left = values[1]; | |
| right = left; | |
| break; | |
| case 3: | |
| top = values[0]; | |
| left = values[1]; | |
| right = left; | |
| bottom = values[2]; | |
| break; | |
| case 4: | |
| top = values[0]; | |
| right = values[1]; | |
| bottom = values[2]; | |
| left = values[3]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-top-color", top)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-right-color", right)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-color", bottom)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-left-color", left)); | |
| return top + " " + right + " " + bottom + " " + left; | |
| }; | |
| CSSParser.prototype.parseBorderEdgeOrOutlineShorthand = function(token, aDecl, aAcceptPriority, aProperty) | |
| { | |
| var bWidth = null; | |
| var bStyle = null; | |
| var bColor = null; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!bWidth | |
| && !bStyle | |
| && !bColor | |
| && token.isIdent(this.kINHERIT)) { | |
| bWidth = this.kINHERIT; | |
| bStyle = this.kINHERIT; | |
| bColor = this.kINHERIT; | |
| } | |
| else if (!bWidth && | |
| (token.isDimension() | |
| || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES) | |
| || token.isNumber("0"))) { | |
| bWidth = token.value; | |
| } | |
| else if (!bStyle && | |
| (token.isIdent() && token.value in this.kBORDER_STYLE_NAMES)) { | |
| bStyle = token.value; | |
| } | |
| else { | |
| var color = (aProperty == "outline" && token.isIdent("invert")) | |
| ? "invert" : this.parseColor(token); | |
| if (!bColor && color) | |
| bColor = color; | |
| else | |
| return ""; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| // create the declarations | |
| this.forgetState(); | |
| bWidth = bWidth ? bWidth : "medium"; | |
| bStyle = bStyle ? bStyle : "none"; | |
| bColor = bColor ? bColor : "-moz-initial"; | |
| function addPropertyToDecl(aSelf, aDecl, property, w, s, c) { | |
| aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-width", w)); | |
| aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-style", s)); | |
| aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-color", c)); | |
| } | |
| if (aProperty == "border") { | |
| addPropertyToDecl(this, aDecl, "border-top", bWidth, bStyle, bColor); | |
| addPropertyToDecl(this, aDecl, "border-right", bWidth, bStyle, bColor); | |
| addPropertyToDecl(this, aDecl, "border-bottom", bWidth, bStyle, bColor); | |
| addPropertyToDecl(this, aDecl, "border-left", bWidth, bStyle, bColor); | |
| } | |
| else | |
| addPropertyToDecl(this, aDecl, aProperty, bWidth, bStyle, bColor); | |
| return bWidth + " " + bStyle + " " + bColor; | |
| }; | |
| CSSParser.prototype.parseBorderImage = function() | |
| { | |
| var borderImage = {url: "", offsets: [], widths: [], sizes: []}; | |
| var token = this.getToken(true, true); | |
| if (token.isFunction("url(")) { | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| if (urlContent) { | |
| borderImage.url = urlContent.substr(0, urlContent.length - 1).trim(); | |
| if ((borderImage.url[0] == '"' && borderImage.url[borderImage.url.length - 1] == '"') | |
| || (borderImage.url[0] == "'" && borderImage.url[borderImage.url.length - 1] == "'")) | |
| borderImage.url = borderImage.url.substr(1, borderImage.url.length - 2); | |
| } | |
| else | |
| return null; | |
| } | |
| else | |
| return null; | |
| token = this.getToken(true, true); | |
| if (token.isNumber() | |
| || token.isPercentage()) | |
| borderImage.offsets.push(token.value); | |
| else | |
| return null; | |
| var i; | |
| for (i= 0; i < 3; i++) { | |
| token = this.getToken(true, true); | |
| if (token.isNumber() | |
| || token.isPercentage()) | |
| borderImage.offsets.push(token.value); | |
| else | |
| break; | |
| } | |
| if (i == 3) | |
| token = this.getToken(true, true); | |
| if (token.isSymbol("/")) { | |
| token = this.getToken(true, true); | |
| if (token.isDimension() | |
| || token.isNumber("0") | |
| || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)) | |
| borderImage.widths.push(token.value); | |
| else | |
| return null; | |
| for (var i = 0; i < 3; i++) { | |
| token = this.getToken(true, true); | |
| if (token.isDimension() | |
| || token.isNumber("0") | |
| || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)) | |
| borderImage.widths.push(token.value); | |
| else | |
| break; | |
| } | |
| if (i == 3) | |
| token = this.getToken(true, true); | |
| } | |
| for (var i = 0; i < 2; i++) { | |
| if (token.isIdent("stretch") | |
| || token.isIdent("repeat") | |
| || token.isIdent("round")) | |
| borderImage.sizes.push(token.value); | |
| else if (!token.isNotNull()) | |
| return borderImage; | |
| else | |
| return null; | |
| token = this.getToken(true, true); | |
| } | |
| if (!token.isNotNull()) | |
| return borderImage; | |
| return null; | |
| }; | |
| CSSParser.prototype.parseBorderStyleShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var top = null; | |
| var bottom = null; | |
| var left = null; | |
| var right = null; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| } | |
| else if (token.isIdent() && token.value in this.kBORDER_STYLE_NAMES) { | |
| values.push(token.value); | |
| } | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| top = values[0]; | |
| bottom = top; | |
| left = top; | |
| right = top; | |
| break; | |
| case 2: | |
| top = values[0]; | |
| bottom = top; | |
| left = values[1]; | |
| right = left; | |
| break; | |
| case 3: | |
| top = values[0]; | |
| left = values[1]; | |
| right = left; | |
| bottom = values[2]; | |
| break; | |
| case 4: | |
| top = values[0]; | |
| right = values[1]; | |
| bottom = values[2]; | |
| left = values[3]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-top-style", top)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-right-style", right)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-style", bottom)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-left-style", left)); | |
| return top + " " + right + " " + bottom + " " + left; | |
| }; | |
| CSSParser.prototype.parseBorderWidthShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var top = null; | |
| var bottom = null; | |
| var left = null; | |
| var right = null; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| } | |
| else if (token.isDimension() | |
| || token.isNumber("0") | |
| || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)) { | |
| values.push(token.value); | |
| } | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| top = values[0]; | |
| bottom = top; | |
| left = top; | |
| right = top; | |
| break; | |
| case 2: | |
| top = values[0]; | |
| bottom = top; | |
| left = values[1]; | |
| right = left; | |
| break; | |
| case 3: | |
| top = values[0]; | |
| left = values[1]; | |
| right = left; | |
| bottom = values[2]; | |
| break; | |
| case 4: | |
| top = values[0]; | |
| right = values[1]; | |
| bottom = values[2]; | |
| left = values[3]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-top-width", top)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-right-width", right)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-width", bottom)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("border-left-width", left)); | |
| return top + " " + right + " " + bottom + " " + left; | |
| }; | |
| CSSParser.prototype.parseBoxShadows = function() | |
| { | |
| var shadows = []; | |
| var token = this.getToken(true, true); | |
| var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px", spreadRadius = "0px"; | |
| var inset = false; | |
| while (token.isNotNull()) { | |
| if (token.isIdent("none")) { | |
| shadows.push( { none: true } ); | |
| token = this.getToken(true, true); | |
| } | |
| else { | |
| if (token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var offsetX = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return []; | |
| if (!inset && token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var offsetY = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return []; | |
| if (!inset && token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var blurRadius = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| if (!inset && token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var spreadRadius = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| if (!inset && token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isFunction("rgb(") || | |
| token.isFunction("rgba(") || | |
| token.isFunction("hsl(") || | |
| token.isFunction("hsla(") || | |
| token.isSymbol("#") || | |
| token.isIdent()) { | |
| var color = this.parseColor(token); | |
| token = this.getToken(true, true); | |
| } | |
| if (!inset && token.isIdent('inset')) { | |
| inset = true; | |
| token = this.getToken(true, true); | |
| } | |
| shadows.push( { none: false, | |
| color: color, | |
| offsetX: offsetX, offsetY: offsetY, | |
| blurRadius: blurRadius, | |
| spreadRadius: spreadRadius, | |
| inset: inset | |
| } ); | |
| if (token.isSymbol(",")) { | |
| inset = false; | |
| color = ""; | |
| blurRadius = "0px"; | |
| spreadRadius = "0px" | |
| offsetX = "0px"; | |
| offsetY = "0px"; | |
| token = this.getToken(true, true); | |
| } | |
| else if (!token.isNotNull()) | |
| return shadows; | |
| else | |
| return []; | |
| } | |
| } | |
| return shadows; | |
| }; | |
| CSSParser.prototype.parseCharsetRule = function(aSheet) { | |
| var token = this.getToken(false, false); | |
| if (token.isAtRule("@charset") && token.value == "@charset") { // lowercase check | |
| var s = token.value; | |
| token = this.getToken(false, false); | |
| s += token.value; | |
| if (token.isWhiteSpace(" ")) { | |
| token = this.getToken(false, false); | |
| s += token.value; | |
| if (token.isString()) { | |
| var encoding = token.value; | |
| token = this.getToken(false, false); | |
| s += token.value; | |
| if (token.isSymbol(";")) { | |
| var rule = new jscsspCharsetRule(); | |
| rule.encoding = encoding; | |
| rule.parsedCssText = s; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| return true; | |
| } | |
| else | |
| this.reportError(kCHARSET_RULE_MISSING_SEMICOLON); | |
| } | |
| else | |
| this.reportError(kCHARSET_RULE_CHARSET_IS_STRING); | |
| } | |
| else | |
| this.reportError(kCHARSET_RULE_MISSING_WS); | |
| } | |
| this.addUnknownAtRule(aSheet, s); | |
| return false; | |
| }; | |
| CSSParser.prototype.parseColor = function(token) | |
| { | |
| var color = ""; | |
| if (token.isFunction("rgb(") | |
| || token.isFunction("rgba(")) { | |
| color = token.value; | |
| var isRgba = token.isFunction("rgba(") | |
| token = this.getToken(true, true); | |
| if (!token.isNumber() && !token.isPercentage()) | |
| return ""; | |
| color += token.value; | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isNumber() && !token.isPercentage()) | |
| return ""; | |
| color += token.value; | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isNumber() && !token.isPercentage()) | |
| return ""; | |
| color += token.value; | |
| if (isRgba) { | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isNumber()) | |
| return ""; | |
| color += token.value; | |
| } | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(")")) | |
| return ""; | |
| color += token.value; | |
| } | |
| else if (token.isFunction("hsl(") | |
| || token.isFunction("hsla(")) { | |
| color = token.value; | |
| var isHsla = token.isFunction("hsla(") | |
| token = this.getToken(true, true); | |
| if (!token.isNumber()) | |
| return ""; | |
| color += token.value; | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isPercentage()) | |
| return ""; | |
| color += token.value; | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isPercentage()) | |
| return ""; | |
| color += token.value; | |
| if (isHsla) { | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return ""; | |
| color += ", "; | |
| token = this.getToken(true, true); | |
| if (!token.isNumber()) | |
| return ""; | |
| color += token.value; | |
| } | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(")")) | |
| return ""; | |
| color += token.value; | |
| } | |
| else if (token.isIdent() | |
| && (token.value in this.kCOLOR_NAMES)) | |
| color = token.value; | |
| else if (token.isSymbol("#")) { | |
| token = this.getHexValue(); | |
| if (!token.isHex()) | |
| return ""; | |
| var length = token.value.length; | |
| if (length != 3 && length != 6) | |
| return ""; | |
| if (token.value.match( /[a-fA-F0-9]/g ).length != length) | |
| return ""; | |
| color = "#" + token.value; | |
| } | |
| return color; | |
| }; | |
| CSSParser.prototype.parseCueShorthand = function(token, declarations, aAcceptPriority) | |
| { | |
| var before = ""; | |
| var after = ""; | |
| var values = []; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| } | |
| else if (token.isIdent("none")) | |
| values.push(token.value); | |
| else if (token.isFunction("url(")) { | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| if (urlContent) | |
| values.push("url(" + urlContent); | |
| else | |
| return ""; | |
| } | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| before = values[0]; | |
| after = before; | |
| break; | |
| case 2: | |
| before = values[0]; | |
| after = values[1]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue("cue-before", before)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("cue-after", after)); | |
| return before + " " + after; | |
| }; | |
| CSSParser.prototype.parseDeclaration = function(aToken, aDecl, aAcceptPriority, aExpandShorthands, aSheet) { | |
| this.preserveState(); | |
| var blocks = []; | |
| if (aToken.isIdent()) { | |
| var descriptor = aToken.value.toLowerCase(); | |
| var token = this.getToken(true, true); | |
| if (token.isSymbol(":")) { | |
| var token = this.getToken(true, true); | |
| var value = ""; | |
| var declarations = []; | |
| if (aExpandShorthands) | |
| switch (descriptor) { | |
| case "background": | |
| value = this.parseBackgroundShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "margin": | |
| case "padding": | |
| value = this.parseMarginOrPaddingShorthand(token, declarations, aAcceptPriority, descriptor); | |
| break; | |
| case "border-color": | |
| value = this.parseBorderColorShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "border-style": | |
| value = this.parseBorderStyleShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "border-width": | |
| value = this.parseBorderWidthShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "border-top": | |
| case "border-right": | |
| case "border-bottom": | |
| case "border-left": | |
| case "border": | |
| case "outline": | |
| value = this.parseBorderEdgeOrOutlineShorthand(token, declarations, aAcceptPriority, descriptor); | |
| break; | |
| case "cue": | |
| value = this.parseCueShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "pause": | |
| value = this.parsePauseShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "font": | |
| value = this.parseFontShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| case "list-style": | |
| value = this.parseListStyleShorthand(token, declarations, aAcceptPriority); | |
| break; | |
| default: | |
| value = this.parseDefaultPropertyValue(token, declarations, aAcceptPriority, descriptor, aSheet); | |
| break; | |
| } | |
| else | |
| value = this.parseDefaultPropertyValue(token, declarations, aAcceptPriority, descriptor, aSheet); | |
| token = this.currentToken(); | |
| if (value) // no error above | |
| { | |
| var priority = false; | |
| if (token.isSymbol("!")) { | |
| token = this.getToken(true, true); | |
| if (token.isIdent("important")) { | |
| priority = true; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(";") || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| } | |
| else return ""; | |
| } | |
| else return ""; | |
| } | |
| else if (token.isNotNull() && !token.isSymbol(";") && !token.isSymbol("}")) | |
| return ""; | |
| for (var i = 0; i < declarations.length; i++) { | |
| declarations[i].priority = priority; | |
| aDecl.push(declarations[i]); | |
| } | |
| return descriptor + ": " + value + ";"; | |
| } | |
| } | |
| } | |
| else if (aToken.isComment()) { | |
| if (this.mPreserveComments) { | |
| this.forgetState(); | |
| var comment = new jscsspComment(); | |
| comment.parsedCssText = aToken.value; | |
| aDecl.push(comment); | |
| } | |
| return aToken.value; | |
| } | |
| // we have an error here, let's skip it | |
| this.restoreState(); | |
| var s = aToken.value; | |
| blocks = []; | |
| var token = this.getToken(false, false); | |
| while (token.isNotNull()) { | |
| s += token.value; | |
| if ((token.isSymbol(";") || token.isSymbol("}")) && !blocks.length) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } else if (token.isSymbol("{") | |
| || token.isSymbol("(") | |
| || token.isSymbol("[") | |
| || token.isFunction()) { | |
| blocks.push(token.isFunction() ? "(" : token.value); | |
| } else if (token.isSymbol("}") | |
| || token.isSymbol(")") | |
| || token.isSymbol("]")) { | |
| if (blocks.length) { | |
| var ontop = blocks[blocks.length - 1]; | |
| if ((token.isSymbol("}") && ontop == "{") | |
| || (token.isSymbol(")") && ontop == "(") | |
| || (token.isSymbol("]") && ontop == "[")) { | |
| blocks.pop(); | |
| } | |
| } | |
| } | |
| token = this.getToken(false, false); | |
| } | |
| return ""; | |
| }; | |
| CSSParser.prototype.reportError = function(aMsg) { | |
| this.mError = aMsg; | |
| }; | |
| CSSParser.prototype.consumeError = function() { | |
| var e = this.mError; | |
| this.mError = null; | |
| return e; | |
| }; | |
| function CSSParser(aString) | |
| { | |
| this.mToken = null; | |
| this.mLookAhead = null; | |
| this.mScanner = new CSSScanner(aString); | |
| this.mPreserveWS = true; | |
| this.mPreserveComments = true; | |
| this.mPreservedTokens = []; | |
| this.mError = null; | |
| } | |
| CSSParser.prototype._init = function() { | |
| this.mToken = null; | |
| this.mLookAhead = null; | |
| }; | |
| CSSParser.prototype.kINHERIT = "inherit", | |
| CSSParser.prototype.kBORDER_WIDTH_NAMES = { | |
| "thin": true, | |
| "medium": true, | |
| "thick": true | |
| }; | |
| CSSParser.prototype.kBORDER_STYLE_NAMES = { | |
| "none": true, | |
| "hidden": true, | |
| "dotted": true, | |
| "dashed": true, | |
| "solid": true, | |
| "double": true, | |
| "groove": true, | |
| "ridge": true, | |
| "inset": true, | |
| "outset": true | |
| }; | |
| CSSParser.prototype.kCOLOR_NAMES = { | |
| "transparent": true, | |
| "black": true, | |
| "silver": true, | |
| "gray": true, | |
| "white": true, | |
| "maroon": true, | |
| "red": true, | |
| "purple": true, | |
| "fuchsia": true, | |
| "green": true, | |
| "lime": true, | |
| "olive": true, | |
| "yellow": true, | |
| "navy": true, | |
| "blue": true, | |
| "teal": true, | |
| "aqua": true, | |
| "aliceblue": true, | |
| "antiquewhite": true, | |
| "aquamarine": true, | |
| "azure": true, | |
| "beige": true, | |
| "bisque": true, | |
| "blanchedalmond": true, | |
| "blueviolet": true, | |
| "brown": true, | |
| "burlywood": true, | |
| "cadetblue": true, | |
| "chartreuse": true, | |
| "chocolate": true, | |
| "coral": true, | |
| "cornflowerblue": true, | |
| "cornsilk": true, | |
| "crimson": true, | |
| "cyan": true, | |
| "darkblue": true, | |
| "darkcyan": true, | |
| "darkgoldenrod": true, | |
| "darkgray": true, | |
| "darkgreen": true, | |
| "darkgrey": true, | |
| "darkkhaki": true, | |
| "darkmagenta": true, | |
| "darkolivegreen": true, | |
| "darkorange": true, | |
| "darkorchid": true, | |
| "darkred": true, | |
| "darksalmon": true, | |
| "darkseagreen": true, | |
| "darkslateblue": true, | |
| "darkslategray": true, | |
| "darkslategrey": true, | |
| "darkturquoise": true, | |
| "darkviolet": true, | |
| "deeppink": true, | |
| "deepskyblue": true, | |
| "dimgray": true, | |
| "dimgrey": true, | |
| "dodgerblue": true, | |
| "firebrick": true, | |
| "floralwhite": true, | |
| "forestgreen": true, | |
| "gainsboro": true, | |
| "ghostwhite": true, | |
| "gold": true, | |
| "goldenrod": true, | |
| "greenyellow": true, | |
| "grey": true, | |
| "honeydew": true, | |
| "hotpink": true, | |
| "indianred": true, | |
| "indigo": true, | |
| "ivory": true, | |
| "khaki": true, | |
| "lavender": true, | |
| "lavenderblush": true, | |
| "lawngreen": true, | |
| "lemonchiffon": true, | |
| "lightblue": true, | |
| "lightcoral": true, | |
| "lightcyan": true, | |
| "lightgoldenrodyellow": true, | |
| "lightgray": true, | |
| "lightgreen": true, | |
| "lightgrey": true, | |
| "lightpink": true, | |
| "lightsalmon": true, | |
| "lightseagreen": true, | |
| "lightskyblue": true, | |
| "lightslategray": true, | |
| "lightslategrey": true, | |
| "lightsteelblue": true, | |
| "lightyellow": true, | |
| "limegreen": true, | |
| "linen": true, | |
| "magenta": true, | |
| "mediumaquamarine": true, | |
| "mediumblue": true, | |
| "mediumorchid": true, | |
| "mediumpurple": true, | |
| "mediumseagreen": true, | |
| "mediumslateblue": true, | |
| "mediumspringgreen": true, | |
| "mediumturquoise": true, | |
| "mediumvioletred": true, | |
| "midnightblue": true, | |
| "mintcream": true, | |
| "mistyrose": true, | |
| "moccasin": true, | |
| "navajowhite": true, | |
| "oldlace": true, | |
| "olivedrab": true, | |
| "orange": true, | |
| "orangered": true, | |
| "orchid": true, | |
| "palegoldenrod": true, | |
| "palegreen": true, | |
| "paleturquoise": true, | |
| "palevioletred": true, | |
| "papayawhip": true, | |
| "peachpuff": true, | |
| "peru": true, | |
| "pink": true, | |
| "plum": true, | |
| "powderblue": true, | |
| "rosybrown": true, | |
| "royalblue": true, | |
| "saddlebrown": true, | |
| "salmon": true, | |
| "sandybrown": true, | |
| "seagreen": true, | |
| "seashell": true, | |
| "sienna": true, | |
| "skyblue": true, | |
| "slateblue": true, | |
| "slategray": true, | |
| "slategrey": true, | |
| "snow": true, | |
| "springgreen": true, | |
| "steelblue": true, | |
| "tan": true, | |
| "thistle": true, | |
| "tomato": true, | |
| "turquoise": true, | |
| "violet": true, | |
| "wheat": true, | |
| "whitesmoke": true, | |
| "yellowgreen": true, | |
| "activeborder": true, | |
| "activecaption": true, | |
| "appworkspace": true, | |
| "background": true, | |
| "buttonface": true, | |
| "buttonhighlight": true, | |
| "buttonshadow": true, | |
| "buttontext": true, | |
| "captiontext": true, | |
| "graytext": true, | |
| "highlight": true, | |
| "highlighttext": true, | |
| "inactiveborder": true, | |
| "inactivecaption": true, | |
| "inactivecaptiontext": true, | |
| "infobackground": true, | |
| "infotext": true, | |
| "menu": true, | |
| "menutext": true, | |
| "scrollbar": true, | |
| "threeddarkshadow": true, | |
| "threedface": true, | |
| "threedhighlight": true, | |
| "threedlightshadow": true, | |
| "threedshadow": true, | |
| "window": true, | |
| "windowframe": true, | |
| "windowtext": true | |
| }; | |
| CSSParser.prototype.kLIST_STYLE_TYPE_NAMES = { | |
| "decimal": true, | |
| "decimal-leading-zero": true, | |
| "lower-roman": true, | |
| "upper-roman": true, | |
| "georgian": true, | |
| "armenian": true, | |
| "lower-latin": true, | |
| "lower-alpha": true, | |
| "upper-latin": true, | |
| "upper-alpha": true, | |
| "lower-greek": true, | |
| "disc": true, | |
| "circle": true, | |
| "square": true, | |
| "none": true, | |
| /* CSS 3 */ | |
| "box": true, | |
| "check": true, | |
| "diamond": true, | |
| "hyphen": true, | |
| "lower-armenian": true, | |
| "cjk-ideographic": true, | |
| "ethiopic-numeric": true, | |
| "hebrew": true, | |
| "japanese-formal": true, | |
| "japanese-informal": true, | |
| "simp-chinese-formal": true, | |
| "simp-chinese-informal": true, | |
| "syriac": true, | |
| "tamil": true, | |
| "trad-chinese-formal": true, | |
| "trad-chinese-informal": true, | |
| "upper-armenian": true, | |
| "arabic-indic": true, | |
| "binary": true, | |
| "bengali": true, | |
| "cambodian": true, | |
| "khmer": true, | |
| "devanagari": true, | |
| "gujarati": true, | |
| "gurmukhi": true, | |
| "kannada": true, | |
| "lower-hexadecimal": true, | |
| "lao": true, | |
| "malayalam": true, | |
| "mongolian": true, | |
| "myanmar": true, | |
| "octal": true, | |
| "oriya": true, | |
| "persian": true, | |
| "urdu": true, | |
| "telugu": true, | |
| "tibetan": true, | |
| "upper-hexadecimal": true, | |
| "afar": true, | |
| "ethiopic-halehame-aa-et": true, | |
| "ethiopic-halehame-am-et": true, | |
| "amharic-abegede": true, | |
| "ehiopic-abegede-am-et": true, | |
| "cjk-earthly-branch": true, | |
| "cjk-heavenly-stem": true, | |
| "ethiopic": true, | |
| "ethiopic-abegede": true, | |
| "ethiopic-abegede-gez": true, | |
| "hangul-consonant": true, | |
| "hangul": true, | |
| "hiragana-iroha": true, | |
| "hiragana": true, | |
| "katakana-iroha": true, | |
| "katakana": true, | |
| "lower-norwegian": true, | |
| "oromo": true, | |
| "ethiopic-halehame-om-et": true, | |
| "sidama": true, | |
| "ethiopic-halehame-sid-et": true, | |
| "somali": true, | |
| "ethiopic-halehame-so-et": true, | |
| "tigre": true, | |
| "ethiopic-halehame-tig": true, | |
| "tigrinya-er-abegede": true, | |
| "ethiopic-abegede-ti-er": true, | |
| "tigrinya-et": true, | |
| "ethiopic-halehame-ti-et": true, | |
| "upper-greek": true, | |
| "asterisks": true, | |
| "footnotes": true, | |
| "circled-decimal": true, | |
| "circled-lower-latin": true, | |
| "circled-upper-latin": true, | |
| "dotted-decimal": true, | |
| "double-circled-decimal": true, | |
| "filled-circled-decimal": true, | |
| "parenthesised-decimal": true, | |
| "parenthesised-lower-latin": true | |
| }; | |
| CSSParser.prototype.parseFontFaceRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| var valid = false; | |
| var descriptors = []; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| if (token.isNotNull()) { | |
| // expecting block start | |
| if (token.isSymbol("{")) { | |
| s += " " + token.value; | |
| var token = this.getToken(true, false); | |
| while (true) { | |
| if (token.isSymbol("}")) { | |
| s += "}"; | |
| valid = true; | |
| break; | |
| } else { | |
| var d = this.parseDeclaration(token, descriptors, false, false, aSheet); | |
| s += ((d && descriptors.length) ? " " : "") + d; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| } | |
| if (valid) { | |
| this.forgetState(); | |
| var rule = new jscsspFontFaceRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.descriptors = descriptors; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule) | |
| return true; | |
| } | |
| this.restoreState(); | |
| return false; | |
| }; | |
| CSSParser.prototype.parseFontShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var kStyle = {"italic": true, "oblique": true }; | |
| var kVariant = {"small-caps": true }; | |
| var kWeight = { "bold": true, "bolder": true, "lighter": true, | |
| "100": true, "200": true, "300": true, "400": true, | |
| "500": true, "600": true, "700": true, "800": true, | |
| "900": true }; | |
| var kSize = { "xx-small": true, "x-small": true, "small": true, "medium": true, | |
| "large": true, "x-large": true, "xx-large": true, | |
| "larger": true, "smaller": true }; | |
| var kValues = { "caption": true, "icon": true, "menu": true, "message-box": true, "small-caption": true, "status-bar": true }; | |
| var kFamily = { "serif": true, "sans-serif": true, "cursive": true, "fantasy": true, "monospace": true }; | |
| var fStyle = null; | |
| var fVariant = null; | |
| var fWeight = null; | |
| var fSize = null; | |
| var fLineHeight = null; | |
| var fFamily = ""; | |
| var fSystem = null; | |
| var fFamilyValues = []; | |
| var normalCount = 0; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!fStyle && !fVariant && !fWeight | |
| && !fSize && !fLineHeight && !fFamily | |
| && !fSystem | |
| && token.isIdent(this.kINHERIT)) { | |
| fStyle = this.kINHERIT; | |
| fVariant = this.kINHERIT; | |
| fWeight = this.kINHERIT; | |
| fSize = this.kINHERIT; | |
| fLineHeight = this.kINHERIT; | |
| fFamily = this.kINHERIT; | |
| fSystem = this.kINHERIT; | |
| } | |
| else { | |
| if (!fSystem && (token.isIdent() && token.value in kValues)) { | |
| fSystem = token.value; | |
| break; | |
| } | |
| else { | |
| if (!fStyle | |
| && token.isIdent() | |
| && (token.value in kStyle)) { | |
| fStyle = token.value; | |
| } | |
| else if (!fVariant | |
| && token.isIdent() | |
| && (token.value in kVariant)) { | |
| fVariant = token.value; | |
| } | |
| else if (!fWeight | |
| && (token.isIdent() || token.isNumber()) | |
| && (token.value in kWeight)) { | |
| fWeight = token.value; | |
| } | |
| else if (!fSize | |
| && ((token.isIdent() && (token.value in kSize)) | |
| || token.isDimension() | |
| || token.isPercentage())) { | |
| fSize = token.value; | |
| token = this.getToken(false, false); | |
| if (token.isSymbol("/")) { | |
| token = this.getToken(false, false); | |
| if (!fLineHeight && | |
| (token.isDimension() || token.isNumber() || token.isPercentage())) { | |
| fLineHeight = token.value; | |
| } | |
| else | |
| return ""; | |
| } | |
| else if (!token.isWhiteSpace()) | |
| continue; | |
| } | |
| else if (token.isIdent("normal")) { | |
| normalCount++; | |
| if (normalCount > 3) | |
| return ""; | |
| } | |
| else if (!fFamily && // *MUST* be last to be tested here | |
| (token.isString() | |
| || token.isIdent())) { | |
| var lastWasComma = false; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| else if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (token.isIdent() && token.value in kFamily) { | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null); | |
| value.value = token.value; | |
| fFamilyValues.push(value); | |
| fFamily += token.value; | |
| break; | |
| } | |
| else if (token.isString() || token.isIdent()) { | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null); | |
| value.value = token.value; | |
| fFamilyValues.push(value); | |
| fFamily += token.value; | |
| lastWasComma = false; | |
| } | |
| else if (!lastWasComma && token.isSymbol(",")) { | |
| fFamily += ", "; | |
| lastWasComma = true; | |
| } | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| } | |
| else { | |
| return ""; | |
| } | |
| } | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| // create the declarations | |
| this.forgetState(); | |
| if (fSystem) { | |
| aDecl.push(this._createJscsspDeclarationFromValue("font", fSystem)); | |
| return fSystem; | |
| } | |
| fStyle = fStyle ? fStyle : "normal"; | |
| fVariant = fVariant ? fVariant : "normal"; | |
| fWeight = fWeight ? fWeight : "normal"; | |
| fSize = fSize ? fSize : "medium"; | |
| fLineHeight = fLineHeight ? fLineHeight : "normal"; | |
| fFamily = fFamily ? fFamily : "-moz-initial"; | |
| aDecl.push(this._createJscsspDeclarationFromValue("font-style", fStyle)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("font-variant", fVariant)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("font-weight", fWeight)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("font-size", fSize)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("line-height", fLineHeight)); | |
| aDecl.push(this._createJscsspDeclarationFromValuesArray("font-family", fFamilyValues, fFamily)); | |
| return fStyle + " " + fVariant + " " + fWeight + " " + fSize + "/" + fLineHeight + " " + fFamily; | |
| }; | |
| CSSParser.prototype.parseFunctionArgument = function(token) | |
| { | |
| var value = ""; | |
| if (token.isString()) | |
| { | |
| value += token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else { | |
| var parenthesis = 1; | |
| while (true) | |
| { | |
| if (!token.isNotNull()) | |
| return ""; | |
| if (token.isFunction() || token.isSymbol("(")) | |
| parenthesis++; | |
| if (token.isSymbol(")")) { | |
| parenthesis--; | |
| if (!parenthesis) | |
| break; | |
| } | |
| value += token.value; | |
| token = this.getToken(false, false); | |
| } | |
| } | |
| if (token.isSymbol(")")) | |
| return value + ")"; | |
| return ""; | |
| }; | |
| CSSParser.prototype.parseColorStop = function(token) | |
| { | |
| var color = this.parseColor(token); | |
| var position = ""; | |
| if (!color) | |
| return null; | |
| token = this.getToken(true, true); | |
| if (token.isLength()) { | |
| position = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| return { color: color, position: position } | |
| }; | |
| CSSParser.prototype.parseGradient = function () | |
| { | |
| var kHPos = {"left": true, "right": true }; | |
| var kVPos = {"top": true, "bottom": true }; | |
| var kPos = {"left": true, "right": true, "top": true, "bottom": true, "center": true}; | |
| var isRadial = false; | |
| var gradient = { isRepeating: false }; | |
| var token = this.getToken(true, true); | |
| if (token.isNotNull()) { | |
| if (token.isFunction("linear-gradient(") || | |
| token.isFunction("radial-gradient(") || | |
| token.isFunction("repeating-linear-gradient(") || | |
| token.isFunction("repeating-radial-gradient(")) { | |
| if (token.isFunction("radial-gradient(") || | |
| token.isFunction("repeating-radial-gradient(")) { | |
| gradient.isRadial = true; | |
| } | |
| if (token.isFunction("repeating-linear-gradient(") || | |
| token.isFunction("repeating-radial-gradient(")) { | |
| gradient.isRepeating = true; | |
| } | |
| token = this.getToken(true, true); | |
| var foundPosition = false; | |
| var haveAngle = false; | |
| /********** LINEAR **********/ | |
| if (token.isAngle()) { | |
| gradient.angle = token.value; | |
| haveAngle = true; | |
| token = this.getToken(true, true); | |
| if (!token.isSymbol(",")) | |
| return null; | |
| token = this.getToken(true, true); | |
| } | |
| else if (token.isIdent("to")) { | |
| foundPosition = true; | |
| token = this.getToken(true, true); | |
| if (token.isIdent("top") | |
| || token.isIdent("bottom") | |
| || token.isIdent("left") | |
| || token.isIdent("right")) { | |
| gradient.position = token.value; | |
| token = this.getToken(true, true); | |
| if (((gradient.position == "top" || gradient.position == "bottom") && (token.isIdent("left") || token.isIdent("right"))) | |
| || ((gradient.position == "left" || gradient.position == "right") && (token.isIdent("top") || token.isIdent("bottom")))) { | |
| gradient.position += " " + token.value; | |
| token = this.getToken(true, true); | |
| } | |
| } | |
| else | |
| return null; | |
| if (!token.isSymbol(",")) | |
| return null; | |
| token = this.getToken(true, true); | |
| } | |
| /********** RADIAL **********/ | |
| else if (gradient.isRadial) { | |
| gradient.shape = ""; | |
| gradient.extent = ""; | |
| gradient.positions = []; | |
| gradient.at = ""; | |
| while (!token.isIdent("at") && !token.isSymbol(",")) { | |
| if (!gradient.shape | |
| && (token.isIdent("circle") || token.isIdent("ellipse"))) { | |
| gradient.shape = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else if (!gradient.extent | |
| && (token.isIdent("closest-corner") | |
| || token.isIdent("closes-side") | |
| || token.isIdent("farthest-corner") | |
| || token.isIdent("farthest-corner"))) { | |
| gradient.extent = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else if (gradient.positions.length < 2 && token.isLength()){ | |
| gradient.positions.push(token.value); | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| break; | |
| } | |
| // verify if the shape is null of well defined | |
| if ((gradient.positions.length == 1 && !gradient.extent && (gradient.shape == "circle" || !gradient.shape)) | |
| || (gradient.positions.length == 2 && !gradient.extent && (gradient.shape == "ellipse" || !gradient.shape)) | |
| || (!gradient.positions.length && gradient.extent) | |
| || (!gradient.positions.length && !gradient.extent)) { | |
| // shape ok | |
| } | |
| else { | |
| return null; | |
| } | |
| if (token.isIdent("at")) { | |
| token = this.getToken(true, true); | |
| if (((token.isIdent() && token.value in kPos) | |
| || token.isDimension() | |
| || token.isNumber("0") | |
| || token.isPercentage())) { | |
| gradient.at = token.value; | |
| token = this.getToken(true, true); | |
| if (token.isDimension() || token.isNumber("0") || token.isPercentage()) { | |
| gradient.at += " " + token.value; | |
| } | |
| else if (token.isIdent() && token.value in kPos) { | |
| if ((gradient.at in kHPos && token.value in kHPos) || | |
| (gradient.at in kVPos && token.value in kVPos)) | |
| return ""; | |
| gradient.at += " " + token.value; | |
| } | |
| else { | |
| this.ungetToken(); | |
| gradient.at += " center"; | |
| } | |
| } | |
| else | |
| return null; | |
| token = this.getToken(true, true); | |
| } | |
| if (gradient.shape || gradient.extent || gradient.positions.length || gradient.at) { | |
| if (!token.isSymbol(",")) | |
| return null; | |
| token = this.getToken(true, true); | |
| } | |
| } | |
| // now color stops... | |
| var stop1 = this.parseColorStop(token); | |
| if (!stop1) | |
| return null; | |
| token = this.currentToken(); | |
| if (!token.isSymbol(",")) | |
| return null; | |
| token = this.getToken(true, true); | |
| var stop2 = this.parseColorStop(token); | |
| if (!stop2) | |
| return null; | |
| token = this.currentToken(); | |
| if (token.isSymbol(",")) { | |
| token = this.getToken(true, true); | |
| } | |
| // ok we have at least two color stops | |
| gradient.stops = [stop1, stop2]; | |
| while (!token.isSymbol(")")) { | |
| var colorstop = this.parseColorStop(token); | |
| if (!colorstop) | |
| return null; | |
| token = this.currentToken(); | |
| if (!token.isSymbol(")") && !token.isSymbol(",")) | |
| return null; | |
| if (token.isSymbol(",")) | |
| token = this.getToken(true, true); | |
| gradient.stops.push(colorstop); | |
| } | |
| return gradient; | |
| } | |
| } | |
| return null; | |
| }; | |
| CSSParser.prototype.serializeGradient = function(gradient) | |
| { | |
| var s = gradient.isRadial | |
| ? (gradient.isRepeating ? "repeating-radial-gradient(" : "radial-gradient(" ) | |
| : (gradient.isRepeating ? "repeating-linear-gradient(" : "linear-gradient(" ); | |
| if (gradient.angle || gradient.position) | |
| s += (gradient.angle ? gradient.angle: "") + | |
| (gradient.position ? "to " + gradient.position : "") + | |
| ", "; | |
| if (gradient.isRadial) | |
| s += (gradient.shape ? gradient.shape + " " : "") + | |
| (gradient.extent ? gradient.extent + " " : "") + | |
| (gradient.positions.length ? gradient.positions.join(" ") + " " : "") + | |
| (gradient.at ? "at " + gradient.at + " " : "") + | |
| (gradient.shape || gradient.extent || gradient.positions.length || gradient.at ? ", " : ""); | |
| for (var i = 0; i < gradient.stops.length; i++) { | |
| var colorstop = gradient.stops[i]; | |
| s += colorstop.color + (colorstop.position ? " " + colorstop.position : ""); | |
| if (i != gradient.stops.length -1) | |
| s += ", "; | |
| } | |
| s += ")"; | |
| return s; | |
| }; | |
| CSSParser.prototype.parseImportRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| var media = []; | |
| var href = ""; | |
| if (token.isString()) { | |
| href = token.value; | |
| s += " " + href; | |
| } | |
| else if (token.isFunction("url(")) { | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| if (urlContent) { | |
| href = "url(" + urlContent; | |
| s += " " + href; | |
| } | |
| } | |
| else | |
| this.reportError(kIMPORT_RULE_MISSING_URL); | |
| if (href) { | |
| token = this.getToken(true, true); | |
| while (token.isIdent()) { | |
| s += " " + token.value; | |
| media.push(token.value); | |
| token = this.getToken(true, true); | |
| if (!token) | |
| break; | |
| if (token.isSymbol(",")) { | |
| s += ","; | |
| } else if (token.isSymbol(";")) { | |
| break; | |
| } else | |
| break; | |
| token = this.getToken(true, true); | |
| } | |
| if (!media.length) { | |
| media.push("all"); | |
| } | |
| if (token.isSymbol(";")) { | |
| s += ";" | |
| this.forgetState(); | |
| var rule = new jscsspImportRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.href = href; | |
| rule.media = media; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| return true; | |
| } | |
| } | |
| this.restoreState(); | |
| this.addUnknownAtRule(aSheet, "@import"); | |
| return false; | |
| }; | |
| CSSParser.prototype.parseKeyframesRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| var valid = false; | |
| var keyframesRule = new jscsspKeyframesRule(); | |
| keyframesRule.currentLine = currentLine; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| var foundName = false; | |
| while (token.isNotNull()) { | |
| if (token.isIdent()) { | |
| // should be the keyframes' name | |
| foundName = true; | |
| s += " " + token.value; | |
| keyframesRule.name = token.value; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol("{")) | |
| this.ungetToken(); | |
| else { | |
| // error... | |
| token.type = jscsspToken.NULL_TYPE; | |
| break; | |
| } | |
| } | |
| else if (token.isSymbol("{")) { | |
| if (!foundName) { | |
| token.type = jscsspToken.NULL_TYPE; | |
| // not a valid keyframes at-rule | |
| } | |
| break; | |
| } | |
| else { | |
| token.type = jscsspToken.NULL_TYPE; | |
| // not a valid keyframes at-rule | |
| break; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isSymbol("{") && keyframesRule.name) { | |
| // ok let's parse keyframe rules now... | |
| s += " { "; | |
| token = this.getToken(true, false); | |
| while (token.isNotNull()) { | |
| if (token.isComment() && this.mPreserveComments) { | |
| s += " " + token.value; | |
| var comment = new jscsspComment(); | |
| comment.parsedCssText = token.value; | |
| keyframesRule.cssRules.push(comment); | |
| } else if (token.isSymbol("}")) { | |
| valid = true; | |
| break; | |
| } else { | |
| var r = this.parseKeyframeRule(token, keyframesRule, true); | |
| if (r) | |
| s += r; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| if (valid) { | |
| this.forgetState(); | |
| keyframesRule.currentLine = currentLine; | |
| keyframesRule.parsedCssText = s; | |
| aSheet.cssRules.push(keyframesRule); | |
| return true; | |
| } | |
| this.restoreState(); | |
| return false; | |
| }; | |
| CSSParser.prototype.parseKeyframeRule = function(aToken, aOwner) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| this.preserveState(); | |
| var token = aToken; | |
| // find the keyframe keys | |
| var key = ""; | |
| while (token.isNotNull()) { | |
| if (token.isIdent() || token.isPercentage()) { | |
| if (token.isIdent() | |
| && !token.isIdent("from") | |
| && !token.isIdent("to")) { | |
| key = ""; | |
| break; | |
| } | |
| key += token.value; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol("{")) { | |
| this.ungetToken(); | |
| break; | |
| } | |
| else | |
| if (token.isSymbol(",")) { | |
| key += ", "; | |
| } | |
| else { | |
| key = ""; | |
| break; | |
| } | |
| } | |
| else { | |
| key = ""; | |
| break; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| var valid = false; | |
| var declarations = []; | |
| if (key) { | |
| var s = key; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol("{")) { | |
| s += " { "; | |
| token = this.getToken(true, false); | |
| while (true) { | |
| if (!token.isNotNull()) { | |
| valid = true; | |
| break; | |
| } | |
| if (token.isSymbol("}")) { | |
| s += "}"; | |
| valid = true; | |
| break; | |
| } else { | |
| var d = this.parseDeclaration(token, declarations, true, true, aOwner); | |
| s += ((d && declarations.length) ? " " : "") + d; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| } | |
| else { | |
| // key is invalid so the whole rule is invalid with it | |
| } | |
| if (valid) { | |
| var rule = new jscsspKeyframeRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.declarations = declarations; | |
| rule.keyText = key; | |
| rule.parentRule = aOwner; | |
| aOwner.cssRules.push(rule); | |
| return s; | |
| } | |
| this.restoreState(); | |
| s = this.currentToken().value; | |
| this.addUnknownAtRule(aOwner, s); | |
| return ""; | |
| }; | |
| CSSParser.prototype.parseListStyleShorthand = function(token, aDecl, aAcceptPriority) | |
| { | |
| var kPosition = { "inside": true, "outside": true }; | |
| var lType = null; | |
| var lPosition = null; | |
| var lImage = null; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!lType && !lPosition && ! lImage | |
| && token.isIdent(this.kINHERIT)) { | |
| lType = this.kINHERIT; | |
| lPosition = this.kINHERIT; | |
| lImage = this.kINHERIT; | |
| } | |
| else if (!lType && | |
| (token.isIdent() && token.value in this.kLIST_STYLE_TYPE_NAMES)) { | |
| lType = token.value; | |
| } | |
| else if (!lPosition && | |
| (token.isIdent() && token.value in kPosition)) { | |
| lPosition = token.value; | |
| } | |
| else if (!lImage && token.isFunction("url")) { | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| if (urlContent) { | |
| lImage = "url(" + urlContent; | |
| } | |
| else | |
| return ""; | |
| } | |
| else if (!token.isIdent("none")) | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| // create the declarations | |
| this.forgetState(); | |
| lType = lType ? lType : "none"; | |
| lImage = lImage ? lImage : "none"; | |
| lPosition = lPosition ? lPosition : "outside"; | |
| aDecl.push(this._createJscsspDeclarationFromValue("list-style-type", lType)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("list-style-position", lPosition)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("list-style-image", lImage)); | |
| return lType + " " + lPosition + " " + lImage; | |
| }; | |
| CSSParser.prototype.parse = function(aString, aTryToPreserveWhitespaces, aTryToPreserveComments) { | |
| if (!aString) | |
| return null; // early way out if we can | |
| this.mPreserveWS = aTryToPreserveWhitespaces; | |
| this.mPreserveComments = aTryToPreserveComments; | |
| this.mPreservedTokens = []; | |
| this.mScanner.init(aString); | |
| var sheet = new jscsspStylesheet(); | |
| // @charset can only appear at first char of the stylesheet | |
| var token = this.getToken(false, false); | |
| if (!token.isNotNull()) | |
| return sheet; | |
| if (token.isAtRule("@charset")) { | |
| this.ungetToken(); | |
| this.parseCharsetRule(sheet); | |
| token = this.getToken(false, false); | |
| } | |
| var foundStyleRules = false; | |
| var foundImportRules = false; | |
| var foundNameSpaceRules = false; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isWhiteSpace()) | |
| { | |
| if (aTryToPreserveWhitespaces) | |
| this.addWhitespace(sheet, token.value); | |
| } | |
| else if (token.isComment()) | |
| { | |
| if (this.mPreserveComments) | |
| this.addComment(sheet, token.value); | |
| } | |
| else if (token.isAtRule()) { | |
| if (token.isAtRule("@variables")) { | |
| if (!foundImportRules && !foundStyleRules) | |
| this.parseVariablesRule(token, sheet); | |
| else { | |
| this.reportError(kVARIABLES_RULE_POSITION); | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| } | |
| else if (token.isAtRule("@import")) { | |
| // @import rules MUST occur before all style and namespace | |
| // rules | |
| if (!foundStyleRules && !foundNameSpaceRules) | |
| foundImportRules = this.parseImportRule(token, sheet); | |
| else { | |
| this.reportError(kIMPORT_RULE_POSITION); | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| } | |
| else if (token.isAtRule("@namespace")) { | |
| // @namespace rules MUST occur before all style rule and | |
| // after all @import rules | |
| if (!foundStyleRules) | |
| foundNameSpaceRules = this.parseNamespaceRule(token, sheet); | |
| else { | |
| this.reportError(kNAMESPACE_RULE_POSITION); | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| } | |
| else if (token.isAtRule("@font-face")) { | |
| if (this.parseFontFaceRule(token, sheet)) | |
| foundStyleRules = true; | |
| else | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| else if (token.isAtRule("@page")) { | |
| if (this.parsePageRule(token, sheet)) | |
| foundStyleRules = true; | |
| else | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| else if (token.isAtRule("@media")) { | |
| if (this.parseMediaRule(token, sheet)) | |
| foundStyleRules = true; | |
| else | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| else if (token.isAtRule("@keyframes")) { | |
| if (!this.parseKeyframesRule(token, sheet)) | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| else if (token.isAtRule("@charset")) { | |
| this.reportError(kCHARSET_RULE_CHARSET_SOF); | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| else { | |
| this.reportError(kUNKNOWN_AT_RULE); | |
| this.addUnknownAtRule(sheet, token.value); | |
| } | |
| } | |
| else // plain style rules | |
| { | |
| var ruleText = this.parseStyleRule(token, sheet, false); | |
| if (ruleText) | |
| foundStyleRules = true; | |
| } | |
| token = this.getToken(false); | |
| } | |
| return sheet; | |
| }; | |
| CSSParser.prototype.parseMarginOrPaddingShorthand = function(token, aDecl, aAcceptPriority, aProperty) | |
| { | |
| var top = null; | |
| var bottom = null; | |
| var left = null; | |
| var right = null; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| token = this.getToken(true, true); | |
| break; | |
| } | |
| else if (token.isDimension() | |
| || token.isNumber("0") | |
| || token.isPercentage() | |
| || token.isIdent("auto")) { | |
| values.push(token.value); | |
| } | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| top = values[0]; | |
| bottom = top; | |
| left = top; | |
| right = top; | |
| break; | |
| case 2: | |
| top = values[0]; | |
| bottom = top; | |
| left = values[1]; | |
| right = left; | |
| break; | |
| case 3: | |
| top = values[0]; | |
| left = values[1]; | |
| right = left; | |
| bottom = values[2]; | |
| break; | |
| case 4: | |
| top = values[0]; | |
| right = values[1]; | |
| bottom = values[2]; | |
| left = values[3]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-top", top)); | |
| aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-right", right)); | |
| aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-bottom", bottom)); | |
| aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-left", left)); | |
| return top + " " + right + " " + bottom + " " + left; | |
| }; | |
| CSSParser.prototype.parseMediaQuery = function() | |
| { | |
| var kCONSTRAINTS = { | |
| "width": true, | |
| "min-width": true, | |
| "max-width": true, | |
| "height": true, | |
| "min-height": true, | |
| "max-height": true, | |
| "device-width": true, | |
| "min-device-width": true, | |
| "max-device-width": true, | |
| "device-height": true, | |
| "min-device-height": true, | |
| "max-device-height": true, | |
| "orientation": true, | |
| "aspect-ratio": true, | |
| "min-aspect-ratio": true, | |
| "max-aspect-ratio": true, | |
| "device-aspect-ratio": true, | |
| "min-device-aspect-ratio": true, | |
| "max-device-aspect-ratio": true, | |
| "color": true, | |
| "min-color": true, | |
| "max-color": true, | |
| "color-index": true, | |
| "min-color-index": true, | |
| "max-color-index": true, | |
| "monochrome": true, | |
| "min-monochrome": true, | |
| "max-monochrome": true, | |
| "resolution": true, | |
| "min-resolution": true, | |
| "max-resolution": true, | |
| "scan": true, | |
| "grid": true | |
| }; | |
| var m = {cssText: "", amplifier: "", medium: "", constraints: []}; | |
| var token = this.getToken(true, true); | |
| if (token.isIdent("all") || | |
| token.isIdent("aural") || | |
| token.isIdent("braille") || | |
| token.isIdent("handheld") || | |
| token.isIdent("print") || | |
| token.isIdent("projection") || | |
| token.isIdent("screen") || | |
| token.isIdent("tty") || | |
| token.isIdent("tv")) { | |
| m.medium = token.value; | |
| m.cssText += token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else if (token.isIdent("not") || token.isIdent("only")) { | |
| m.amplifier = token.value.toLowerCase(); | |
| m.cssText += token.value.toLowerCase(); | |
| token = this.getToken(true, true); | |
| if (token.isIdent("all") || | |
| token.isIdent("aural") || | |
| token.isIdent("braille") || | |
| token.isIdent("handheld") || | |
| token.isIdent("print") || | |
| token.isIdent("projection") || | |
| token.isIdent("screen") || | |
| token.isIdent("tty") || | |
| token.isIdent("tv")) { | |
| m.cssText += " " + token.value; | |
| m.medium = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return null; | |
| } | |
| if (m.medium) { | |
| if (!token.isNotNull()) | |
| return m; | |
| if (token.isIdent("and")) { | |
| m.cssText += " and"; | |
| token = this.getToken(true, true); | |
| } | |
| else if (!token.isSymbol("{")) | |
| return null; | |
| } | |
| while (token.isSymbol("(")) { | |
| token = this.getToken(true, true); | |
| if (token.isIdent() && (token.value in kCONSTRAINTS)) { | |
| var constraint = token.value; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(":")) { | |
| token = this.getToken(true, true); | |
| var values = []; | |
| while (!token.isSymbol(")")) { | |
| values.push(token.value); | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isSymbol(")")) { | |
| m.constraints.push({constraint: constraint, value: values}); | |
| m.cssText += " (" + constraint + ": " + values.join(" ") + ")"; | |
| token = this.getToken(true, true); | |
| if (token.isNotNull()) { | |
| if (token.isIdent("and")) { | |
| m.cssText += " and"; | |
| token = this.getToken(true, true); | |
| } | |
| else if (!token.isSymbol("{")) | |
| return null; | |
| } | |
| else | |
| return m; | |
| } | |
| else | |
| return null; | |
| } | |
| else if (token.isSymbol(")")) { | |
| m.constraints.push({constraint: constraint, value: null}); | |
| m.cssText += " (" + constraint + ")"; | |
| token = this.getToken(true, true); | |
| if (token.isNotNull()) { | |
| if (token.isIdent("and")) { | |
| m.cssText += " and"; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return null; | |
| } | |
| else | |
| return m; | |
| } | |
| else | |
| return null; | |
| } | |
| else | |
| return null; | |
| } | |
| return m; | |
| }; | |
| CSSParser.prototype.parseMediaRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| var valid = false; | |
| var mediaRule = new jscsspMediaRule(); | |
| mediaRule.currentLine = currentLine; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| var foundMedia = false; | |
| while (token.isNotNull()) { | |
| this.ungetToken(); | |
| var mediaQuery = this.parseMediaQuery(); | |
| token = this.currentToken(); | |
| if (mediaQuery) { | |
| foundMedia = true; | |
| s += " " + mediaQuery.cssText; | |
| mediaRule.media.push(mediaQuery.cssText); | |
| if (token.isSymbol(",")) { | |
| s += ","; | |
| } else { | |
| if (token.isSymbol("{")) | |
| break; | |
| else { | |
| // error... | |
| token.type = jscsspToken.NULL_TYPE; | |
| break; | |
| } | |
| } | |
| } | |
| else if (token.isSymbol("{")) | |
| break; | |
| else if (foundMedia) { | |
| token.type = jscsspToken.NULL_TYPE; | |
| // not a media list | |
| break; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isSymbol("{") && mediaRule.media.length) { | |
| // ok let's parse style rules now... | |
| s += " { "; | |
| token = this.getToken(true, false); | |
| while (token.isNotNull()) { | |
| if (token.isComment()) { | |
| if (this.mPreserveComments) { | |
| s += " " + token.value; | |
| var comment = new jscsspComment(); | |
| comment.parsedCssText = token.value; | |
| mediaRule.cssRules.push(comment); | |
| } | |
| } else if (token.isSymbol("}")) { | |
| valid = true; | |
| break; | |
| } else { | |
| var r = this.parseStyleRule(token, mediaRule, true); | |
| if (r) | |
| s += r; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| if (valid) { | |
| this.forgetState(); | |
| mediaRule.parsedCssText = s; | |
| aSheet.cssRules.push(mediaRule); | |
| return true; | |
| } | |
| this.restoreState(); | |
| return false; | |
| }; | |
| CSSParser.prototype.parseNamespaceRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| var valid = false; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| if (token.isNotNull()) { | |
| var prefix = ""; | |
| var url = ""; | |
| if (token.isIdent()) { | |
| prefix = token.value; | |
| s += " " + prefix; | |
| token = this.getToken(true, true); | |
| } | |
| if (token) { | |
| var foundURL = false; | |
| if (token.isString()) { | |
| foundURL = true; | |
| url = token.value; | |
| s += " " + url; | |
| } else if (token.isFunction("url(")) { | |
| // get a url here... | |
| token = this.getToken(true, true); | |
| var urlContent = this.parseURL(token); | |
| if (urlContent) { | |
| url += "url(" + urlContent; | |
| foundURL = true; | |
| s += " " + urlContent; | |
| } | |
| } | |
| } | |
| if (foundURL) { | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(";")) { | |
| s += ";"; | |
| this.forgetState(); | |
| var rule = new jscsspNamespaceRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.prefix = prefix; | |
| rule.url = url; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| return true; | |
| } | |
| } | |
| } | |
| this.restoreState(); | |
| this.addUnknownAtRule(aSheet, "@namespace"); | |
| return false; | |
| }; | |
| CSSParser.prototype.parsePageRule = function(aToken, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = aToken.value; | |
| var valid = false; | |
| var declarations = []; | |
| this.preserveState(); | |
| var token = this.getToken(true, true); | |
| var pageSelector = ""; | |
| if (token.isSymbol(":") || token.isIdent()) { | |
| if (token.isSymbol(":")) { | |
| pageSelector = ":"; | |
| token = this.getToken(false, false); | |
| } | |
| if (token.isIdent()) { | |
| pageSelector += token.value; | |
| s += " " + pageSelector; | |
| token = this.getToken(true, true); | |
| } | |
| } | |
| if (token.isNotNull()) { | |
| // expecting block start | |
| if (token.isSymbol("{")) { | |
| s += " " + token.value; | |
| var token = this.getToken(true, false); | |
| while (true) { | |
| if (token.isSymbol("}")) { | |
| s += "}"; | |
| valid = true; | |
| break; | |
| } else { | |
| var d = this.parseDeclaration(token, declarations, true, true, aSheet); | |
| s += ((d && declarations.length) ? " " : "") + d; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| } | |
| if (valid) { | |
| this.forgetState(); | |
| var rule = new jscsspPageRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.pageSelector = pageSelector; | |
| rule.declarations = declarations; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule) | |
| return true; | |
| } | |
| this.restoreState(); | |
| return false; | |
| }; | |
| CSSParser.prototype.parsePauseShorthand = function(token, declarations, aAcceptPriority) | |
| { | |
| var before = ""; | |
| var after = ""; | |
| var values = []; | |
| var values = []; | |
| while (true) { | |
| if (!token.isNotNull()) | |
| break; | |
| if (token.isSymbol(";") | |
| || (aAcceptPriority && token.isSymbol("!")) | |
| || token.isSymbol("}")) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| else if (!values.length && token.isIdent(this.kINHERIT)) { | |
| values.push(token.value); | |
| } | |
| else if (token.isDimensionOfUnit("ms") | |
| || token.isDimensionOfUnit("s") | |
| || token.isPercentage() | |
| || token.isNumber("0")) | |
| values.push(token.value); | |
| else | |
| return ""; | |
| token = this.getToken(true, true); | |
| } | |
| var count = values.length; | |
| switch (count) { | |
| case 1: | |
| before = values[0]; | |
| after = before; | |
| break; | |
| case 2: | |
| before = values[0]; | |
| after = values[1]; | |
| break; | |
| default: | |
| return ""; | |
| } | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValue("pause-before", before)); | |
| aDecl.push(this._createJscsspDeclarationFromValue("pause-after", after)); | |
| return before + " " + after; | |
| }; | |
| CSSParser.prototype.parseDefaultPropertyValue = function(token, aDecl, aAcceptPriority, descriptor, aSheet) { | |
| var valueText = ""; | |
| var blocks = []; | |
| var foundPriority = false; | |
| var values = []; | |
| while (token.isNotNull()) { | |
| if ((token.isSymbol(";") | |
| || token.isSymbol("}") | |
| || token.isSymbol("!")) | |
| && !blocks.length) { | |
| if (token.isSymbol("}")) | |
| this.ungetToken(); | |
| break; | |
| } | |
| if (token.isIdent(this.kINHERIT)) { | |
| if (values.length) { | |
| return ""; | |
| } | |
| else { | |
| valueText = this.kINHERIT; | |
| var value = new jscsspVariable(kJscsspINHERIT_VALUE, aSheet); | |
| values.push(value); | |
| token = this.getToken(true, true); | |
| break; | |
| } | |
| } | |
| else if (token.isSymbol("{") | |
| || token.isSymbol("(") | |
| || token.isSymbol("[")) { | |
| blocks.push(token.value); | |
| } | |
| else if (token.isSymbol("}") | |
| || token.isSymbol("]")) { | |
| if (blocks.length) { | |
| var ontop = blocks[blocks.length - 1]; | |
| if ((token.isSymbol("}") && ontop == "{") | |
| || (token.isSymbol(")") && ontop == "(") | |
| || (token.isSymbol("]") && ontop == "[")) { | |
| blocks.pop(); | |
| } | |
| } | |
| } | |
| // XXX must find a better way to store individual values | |
| // probably a |values: []| field holding dimensions, percentages | |
| // functions, idents, numbers and symbols, in that order. | |
| if (token.isFunction()) { | |
| if (token.isFunction("var(")) { | |
| token = this.getToken(true, true); | |
| if (token.isIdent()) { | |
| var name = token.value; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(")")) { | |
| var value = new jscsspVariable(kJscsspVARIABLE_VALUE, aSheet); | |
| valueText += "var(" + name + ")"; | |
| value.name = name; | |
| values.push(value); | |
| } | |
| else | |
| return ""; | |
| } | |
| else | |
| return ""; | |
| } | |
| else { | |
| var fn = token.value; | |
| token = this.getToken(false, true); | |
| var arg = this.parseFunctionArgument(token); | |
| if (arg) { | |
| valueText += fn + arg; | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); | |
| value.value = fn + arg; | |
| values.push(value); | |
| } | |
| else | |
| return ""; | |
| } | |
| } | |
| else if (token.isSymbol("#")) { | |
| var color = this.parseColor(token); | |
| if (color) { | |
| valueText += color; | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); | |
| value.value = color; | |
| values.push(value); | |
| } | |
| else | |
| return ""; | |
| } | |
| else if (!token.isWhiteSpace() && !token.isSymbol(",")) { | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); | |
| value.value = token.value; | |
| values.push(value); | |
| valueText += token.value; | |
| } | |
| else | |
| valueText += token.value; | |
| token = this.getToken(false, true); | |
| } | |
| if (values.length && valueText) { | |
| this.forgetState(); | |
| aDecl.push(this._createJscsspDeclarationFromValuesArray(descriptor, values, valueText)); | |
| return valueText; | |
| } | |
| return ""; | |
| }; | |
| CSSParser.prototype.parseSelector = function(aToken, aParseSelectorOnly) { | |
| var s = ""; | |
| var specificity = {a: 0, b: 0, c: 0, d: 0}; // CSS 2.1 section 6.4.3 | |
| var isFirstInChain = true; | |
| var token = aToken; | |
| var valid = false; | |
| var combinatorFound = false; | |
| while (true) { | |
| if (!token.isNotNull()) { | |
| if (aParseSelectorOnly) | |
| return {selector: s, specificity: specificity }; | |
| return ""; | |
| } | |
| if (!aParseSelectorOnly && token.isSymbol("{")) { | |
| // end of selector | |
| valid = !combinatorFound; | |
| // don't unget if invalid since addUnknownRule is going to restore state anyway | |
| if (valid) | |
| this.ungetToken(); | |
| break; | |
| } | |
| if (token.isSymbol(",")) { // group of selectors | |
| s += token.value; | |
| isFirstInChain = true; | |
| combinatorFound = false; | |
| token = this.getToken(false, true); | |
| continue; | |
| } | |
| // now combinators and grouping... | |
| else if (!combinatorFound | |
| && (token.isWhiteSpace() | |
| || token.isSymbol(">") | |
| || token.isSymbol("+") | |
| || token.isSymbol("~"))) { | |
| if (token.isWhiteSpace()) { | |
| s += " "; | |
| var nextToken = this.lookAhead(true, true); | |
| if (!nextToken.isNotNull()) { | |
| if (aParseSelectorOnly) | |
| return {selector: s, specificity: specificity }; | |
| return ""; | |
| } | |
| if (nextToken.isSymbol(">") | |
| || nextToken.isSymbol("+") | |
| || nextToken.isSymbol("~")) { | |
| token = this.getToken(true, true); | |
| s += token.value + " "; | |
| combinatorFound = true; | |
| } | |
| } | |
| else { | |
| s += token.value; | |
| combinatorFound = true; | |
| } | |
| isFirstInChain = true; | |
| token = this.getToken(true, true); | |
| continue; | |
| } | |
| else { | |
| var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, true); | |
| if (!simpleSelector) | |
| break; // error | |
| s += simpleSelector.selector; | |
| specificity.b += simpleSelector.specificity.b; | |
| specificity.c += simpleSelector.specificity.c; | |
| specificity.d += simpleSelector.specificity.d; | |
| isFirstInChain = false; | |
| combinatorFound = false; | |
| } | |
| token = this.getToken(false, true); | |
| } | |
| if (valid) { | |
| return {selector: s, specificity: specificity }; | |
| } | |
| return ""; | |
| }; | |
| CSSParser.prototype.isPseudoElement = function(aIdent) | |
| { | |
| switch (aIdent) { | |
| case "first-letter": | |
| case "first-line": | |
| case "before": | |
| case "after": | |
| case "marker": | |
| return true; | |
| break; | |
| default: | |
| break; | |
| } | |
| return false; | |
| }; | |
| CSSParser.prototype.parseSimpleSelector = function(token, isFirstInChain, canNegate) | |
| { | |
| var s = ""; | |
| var specificity = {a: 0, b: 0, c: 0, d: 0}; // CSS 2.1 section 6.4.3 | |
| if (isFirstInChain | |
| && (token.isSymbol("*") || token.isSymbol("|") || token.isIdent())) { | |
| // type or universal selector | |
| if (token.isSymbol("*") || token.isIdent()) { | |
| // we don't know yet if it's a prefix or a universal | |
| // selector | |
| s += token.value; | |
| var isIdent = token.isIdent(); | |
| token = this.getToken(false, true); | |
| if (token.isSymbol("|")) { | |
| // it's a prefix | |
| s += token.value; | |
| token = this.getToken(false, true); | |
| if (token.isIdent() || token.isSymbol("*")) { | |
| // ok we now have a type element or universal | |
| // selector | |
| s += token.value; | |
| if (token.isIdent()) | |
| specificity.d++; | |
| } else | |
| // oops that's an error... | |
| return null; | |
| } else { | |
| this.ungetToken(); | |
| if (isIdent) | |
| specificity.d++; | |
| } | |
| } else if (token.isSymbol("|")) { | |
| s += token.value; | |
| token = this.getToken(false, true); | |
| if (token.isIdent() || token.isSymbol("*")) { | |
| s += token.value; | |
| if (token.isIdent()) | |
| specificity.d++; | |
| } else | |
| // oops that's an error | |
| return null; | |
| } | |
| } | |
| else if (token.isSymbol(".") || token.isSymbol("#")) { | |
| var isClass = token.isSymbol("."); | |
| s += token.value; | |
| token = this.getToken(false, true); | |
| if (token.isIdent()) { | |
| s += token.value; | |
| if (isClass) | |
| specificity.c++; | |
| else | |
| specificity.b++; | |
| } | |
| else | |
| return null; | |
| } | |
| else if (token.isSymbol(":")) { | |
| s += token.value; | |
| token = this.getToken(false, true); | |
| if (token.isSymbol(":")) { | |
| s += token.value; | |
| token = this.getToken(false, true); | |
| } | |
| if (token.isIdent()) { | |
| s += token.value; | |
| if (this.isPseudoElement(token.value)) | |
| specificity.d++; | |
| else | |
| specificity.c++; | |
| } | |
| else if (token.isFunction()) { | |
| s += token.value; | |
| if (token.isFunction(":not(")) { | |
| if (!canNegate) | |
| return null; | |
| token = this.getToken(true, true); | |
| var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, false); | |
| if (!simpleSelector) | |
| return null; | |
| else { | |
| s += simpleSelector.selector; | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(")")) | |
| s += ")"; | |
| else | |
| return null; | |
| } | |
| specificity.c++; | |
| } | |
| else { | |
| while (true) { | |
| token = this.getToken(false, true); | |
| if (token.isSymbol(")")) { | |
| s += ")"; | |
| break; | |
| } else | |
| s += token.value; | |
| } | |
| specificity.c++; | |
| } | |
| } else | |
| return null; | |
| } else if (token.isSymbol("[")) { | |
| s += "["; | |
| token = this.getToken(true, true); | |
| if (token.isIdent() || token.isSymbol("*")) { | |
| s += token.value; | |
| var nextToken = this.getToken(true, true); | |
| if (nextToken.isSymbol("|")) { | |
| s += "|"; | |
| token = this.getToken(true, true); | |
| if (token.isIdent()) | |
| s += token.value; | |
| else | |
| return null; | |
| } else | |
| this.ungetToken(); | |
| } else if (token.isSymbol("|")) { | |
| s += "|"; | |
| token = this.getToken(true, true); | |
| if (token.isIdent()) | |
| s += token.value; | |
| else | |
| return null; | |
| } | |
| else | |
| return null; | |
| // nothing, =, *=, $=, ^=, |= | |
| token = this.getToken(true, true); | |
| if (token.isIncludes() | |
| || token.isDashmatch() | |
| || token.isBeginsmatch() | |
| || token.isEndsmatch() | |
| || token.isContainsmatch() | |
| || token.isSymbol("=")) { | |
| s += token.value; | |
| token = this.getToken(true, true); | |
| if (token.isString() || token.isIdent()) { | |
| s += token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return null; | |
| if (token.isSymbol("]")) { | |
| s += token.value; | |
| specificity.c++; | |
| } | |
| else | |
| return null; | |
| } | |
| else if (token.isSymbol("]")) { | |
| s += token.value; | |
| specificity.c++; | |
| } | |
| else | |
| return null; | |
| } | |
| else if (token.isWhiteSpace()) { | |
| var t = this.lookAhead(true, true); | |
| if (t.isSymbol('{')) | |
| return "" | |
| } | |
| if (s) | |
| return {selector: s, specificity: specificity }; | |
| return null; | |
| }; | |
| CSSParser.prototype.trim11 = function(str) { | |
| str = str.replace(/^\s+/, ''); | |
| for (var i = str.length - 1; i >= 0; i--) { | |
| if (/\S/.test( str.charAt(i) )) { // XXX charat | |
| str = str.substring(0, i + 1); | |
| break; | |
| } | |
| } | |
| return str; | |
| }; | |
| CSSParser.prototype.parseStyleRule = function(aToken, aOwner, aIsInsideMediaRule) | |
| { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| this.preserveState(); | |
| // first let's see if we have a selector here... | |
| var selector = this.parseSelector(aToken, false); | |
| var valid = false; | |
| var declarations = []; | |
| if (selector) { | |
| selector = this.trim11(selector.selector); | |
| var s = selector; | |
| var token = this.getToken(true, true); | |
| if (token.isSymbol("{")) { | |
| s += " { "; | |
| var token = this.getToken(true, false); | |
| while (true) { | |
| if (!token.isNotNull()) { | |
| valid = true; | |
| break; | |
| } | |
| if (token.isSymbol("}")) { | |
| s += "}"; | |
| valid = true; | |
| break; | |
| } else { | |
| var d = this.parseDeclaration(token, declarations, true, true, aOwner); | |
| s += ((d && declarations.length) ? " " : "") + d; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| } | |
| else { | |
| // selector is invalid so the whole rule is invalid with it | |
| } | |
| if (valid) { | |
| var rule = new jscsspStyleRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.declarations = declarations; | |
| rule.mSelectorText = selector; | |
| if (aIsInsideMediaRule) | |
| rule.parentRule = aOwner; | |
| else | |
| rule.parentStyleSheet = aOwner; | |
| aOwner.cssRules.push(rule); | |
| return s; | |
| } | |
| this.restoreState(); | |
| s = this.currentToken().value; | |
| this.addUnknownAtRule(aOwner, s); | |
| return ""; | |
| }; | |
| CSSParser.prototype.parseTextShadows = function() | |
| { | |
| var shadows = []; | |
| var token = this.getToken(true, true); | |
| var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px"; | |
| while (token.isNotNull()) { | |
| if (token.isIdent("none")) { | |
| shadows.push( { none: true } ); | |
| token = this.getToken(true, true); | |
| } | |
| else { | |
| if (token.isFunction("rgb(") || | |
| token.isFunction("rgba(") || | |
| token.isFunction("hsl(") || | |
| token.isFunction("hsla(") || | |
| token.isSymbol("#") || | |
| token.isIdent()) { | |
| var color = this.parseColor(token); | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var offsetX = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return []; | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var offsetY = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| return []; | |
| if (token.isPercentage() || | |
| token.isDimensionOfUnit("cm") || | |
| token.isDimensionOfUnit("mm") || | |
| token.isDimensionOfUnit("in") || | |
| token.isDimensionOfUnit("pc") || | |
| token.isDimensionOfUnit("px") || | |
| token.isDimensionOfUnit("em") || | |
| token.isDimensionOfUnit("ex") || | |
| token.isDimensionOfUnit("pt")) { | |
| var blurRadius = token.value; | |
| token = this.getToken(true, true); | |
| } | |
| if (!color && | |
| (token.isFunction("rgb(") || | |
| token.isFunction("rgba(") || | |
| token.isFunction("hsl(") || | |
| token.isFunction("hsla(") || | |
| token.isSymbol("#") || | |
| token.isIdent())) { | |
| var color = this.parseColor(token); | |
| token = this.getToken(true, true); | |
| } | |
| shadows.push( { none: false, | |
| color: color, | |
| offsetX: offsetX, offsetY: offsetY, | |
| blurRadius: blurRadius } ); | |
| if (token.isSymbol(",")) { | |
| color = ""; | |
| blurRadius = "0px"; | |
| offsetX = "0px"; | |
| offsetY = "0px"; | |
| token = this.getToken(true, true); | |
| } | |
| else if (!token.isNotNull()) | |
| return shadows; | |
| else | |
| return []; | |
| } | |
| } | |
| return shadows; | |
| }; | |
| CSSParser.prototype.currentToken = function() { | |
| return this.mToken; | |
| }; | |
| CSSParser.prototype.getHexValue = function() { | |
| this.mToken = this.mScanner.nextHexValue(); | |
| return this.mToken; | |
| }; | |
| CSSParser.prototype.getToken = function(aSkipWS, aSkipComment) { | |
| if (this.mLookAhead) { | |
| this.mToken = this.mLookAhead; | |
| this.mLookAhead = null; | |
| return this.mToken; | |
| } | |
| this.mToken = this.mScanner.nextToken(); | |
| while (this.mToken && | |
| ((aSkipWS && this.mToken.isWhiteSpace()) || | |
| (aSkipComment && this.mToken.isComment()))) | |
| this.mToken = this.mScanner.nextToken(); | |
| return this.mToken; | |
| }; | |
| CSSParser.prototype.lookAhead = function(aSkipWS, aSkipComment) { | |
| var preservedToken = this.mToken; | |
| this.mScanner.preserveState(); | |
| var token = this.getToken(aSkipWS, aSkipComment); | |
| this.mScanner.restoreState(); | |
| this.mToken = preservedToken; | |
| return token; | |
| }; | |
| CSSParser.prototype.ungetToken = function() { | |
| this.mLookAhead = this.mToken; | |
| }; | |
| CSSParser.prototype.addWhitespace = function(aSheet, aString) { | |
| var rule = new jscsspWhitespace(); | |
| rule.parsedCssText = aString; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| }; | |
| CSSParser.prototype.addComment = function(aSheet, aString) { | |
| var rule = new jscsspComment(); | |
| rule.parsedCssText = aString; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| }; | |
| CSSParser.prototype._createJscsspDeclaration = function(property, value) | |
| { | |
| var decl = new jscsspDeclaration(); | |
| decl.property = property; | |
| decl.value = this.trim11(value); | |
| decl.parsedCssText = property + ": " + value + ";"; | |
| return decl; | |
| }; | |
| CSSParser.prototype._createJscsspDeclarationFromValue = function(property, valueText) | |
| { | |
| var decl = new jscsspDeclaration(); | |
| decl.property = property; | |
| var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null); | |
| value.value = valueText; | |
| decl.values = [value]; | |
| decl.valueText = valueText; | |
| decl.parsedCssText = property + ": " + valueText + ";"; | |
| return decl; | |
| }; | |
| CSSParser.prototype._createJscsspDeclarationFromValuesArray = function(property, values, valueText) | |
| { | |
| var decl = new jscsspDeclaration(); | |
| decl.property = property; | |
| decl.values = values; | |
| decl.valueText = valueText; | |
| decl.parsedCssText = property + ": " + valueText + ";"; | |
| return decl; | |
| }; | |
| CSSParser.prototype.preserveState = function() { | |
| this.mPreservedTokens.push(this.currentToken()); | |
| this.mScanner.preserveState(); | |
| }; | |
| CSSParser.prototype.restoreState = function() { | |
| if (this.mPreservedTokens.length) { | |
| this.mScanner.restoreState(); | |
| this.mToken = this.mPreservedTokens.pop(); | |
| } | |
| }; | |
| CSSParser.prototype.forgetState = function() { | |
| if (this.mPreservedTokens.length) { | |
| this.mScanner.forgetState(); | |
| this.mPreservedTokens.pop(); | |
| } | |
| }; | |
| CSSParser.prototype.addUnknownAtRule = function(aSheet, aString) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var blocks = []; | |
| var token = this.getToken(false, false); | |
| while (token.isNotNull()) { | |
| aString += token.value; | |
| if (token.isSymbol(";") && !blocks.length) | |
| break; | |
| else if (token.isSymbol("{") | |
| || token.isSymbol("(") | |
| || token.isSymbol("[") | |
| || token.type == "function") { | |
| blocks.push(token.isFunction() ? "(" : token.value); | |
| } else if (token.isSymbol("}") | |
| || token.isSymbol(")") | |
| || token.isSymbol("]")) { | |
| if (blocks.length) { | |
| var ontop = blocks[blocks.length - 1]; | |
| if ((token.isSymbol("}") && ontop == "{") | |
| || (token.isSymbol(")") && ontop == "(") | |
| || (token.isSymbol("]") && ontop == "[")) { | |
| blocks.pop(); | |
| if (!blocks.length && token.isSymbol("}")) | |
| break; | |
| } | |
| } | |
| } | |
| token = this.getToken(false, false); | |
| } | |
| this.addUnknownRule(aSheet, aString, currentLine); | |
| }; | |
| CSSParser.prototype.addUnknownRule = function(aSheet, aString, aCurrentLine) { | |
| var errorMsg = this.consumeError(); | |
| var rule = new jscsspErrorRule(errorMsg); | |
| rule.currentLine = aCurrentLine; | |
| rule.parsedCssText = aString; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule); | |
| }; | |
| CSSParser.prototype.parseURL = function(token) | |
| { | |
| var value = ""; | |
| if (token.isString()) | |
| { | |
| value += token.value; | |
| token = this.getToken(true, true); | |
| } | |
| else | |
| while (true) | |
| { | |
| if (!token.isNotNull()) { | |
| this.reportError(kURL_EOF); | |
| return ""; | |
| } | |
| if (token.isWhiteSpace()) { | |
| nextToken = this.lookAhead(true, true); | |
| // if next token is not a closing parenthesis, that's an error | |
| if (!nextToken.isSymbol(")")) { | |
| this.reportError(kURL_WS_INSIDE); | |
| token = this.currentToken(); | |
| break; | |
| } | |
| } | |
| if (token.isSymbol(")")) { | |
| break; | |
| } | |
| value += token.value; | |
| token = this.getToken(false, false); | |
| } | |
| if (token.isSymbol(")")) { | |
| return value + ")"; | |
| } | |
| return ""; | |
| }; | |
| CSSParser.prototype.parseVariablesRule = function(token, aSheet) { | |
| var currentLine = CountLF(this.mScanner.getAlreadyScanned()); | |
| var s = token.value; | |
| var declarations = []; | |
| var valid = false; | |
| this.preserveState(); | |
| token = this.getToken(true, true); | |
| var media = []; | |
| var foundMedia = false; | |
| while (token.isNotNull()) { | |
| if (token.isIdent()) { | |
| foundMedia = true; | |
| s += " " + token.value; | |
| media.push(token.value); | |
| token = this.getToken(true, true); | |
| if (token.isSymbol(",")) { | |
| s += ","; | |
| } else { | |
| if (token.isSymbol("{")) | |
| this.ungetToken(); | |
| else { | |
| // error... | |
| token.type = jscsspToken.NULL_TYPE; | |
| break; | |
| } | |
| } | |
| } else if (token.isSymbol("{")) | |
| break; | |
| else if (foundMedia) { | |
| token.type = jscsspToken.NULL_TYPE; | |
| // not a media list | |
| break; | |
| } | |
| token = this.getToken(true, true); | |
| } | |
| if (token.isSymbol("{")) { | |
| s += " {"; | |
| token = this.getToken(true, true); | |
| while (true) { | |
| if (!token.isNotNull()) { | |
| valid = true; | |
| break; | |
| } | |
| if (token.isSymbol("}")) { | |
| s += "}"; | |
| valid = true; | |
| break; | |
| } else { | |
| var d = this.parseDeclaration(token, declarations, true, false, aSheet); | |
| s += ((d && declarations.length) ? " " : "") + d; | |
| } | |
| token = this.getToken(true, false); | |
| } | |
| } | |
| if (valid) { | |
| this.forgetState(); | |
| var rule = new jscsspVariablesRule(); | |
| rule.currentLine = currentLine; | |
| rule.parsedCssText = s; | |
| rule.declarations = declarations; | |
| rule.media = media; | |
| rule.parentStyleSheet = aSheet; | |
| aSheet.cssRules.push(rule) | |
| return true; | |
| } | |
| this.restoreState(); | |
| return false; | |
| }; | |
| function jscsspToken(aType, aValue, aUnit) | |
| { | |
| this.type = aType; | |
| this.value = aValue; | |
| this.unit = aUnit; | |
| } | |
| jscsspToken.NULL_TYPE = 0; | |
| jscsspToken.WHITESPACE_TYPE = 1; | |
| jscsspToken.STRING_TYPE = 2; | |
| jscsspToken.COMMENT_TYPE = 3; | |
| jscsspToken.NUMBER_TYPE = 4; | |
| jscsspToken.IDENT_TYPE = 5; | |
| jscsspToken.FUNCTION_TYPE = 6; | |
| jscsspToken.ATRULE_TYPE = 7; | |
| jscsspToken.INCLUDES_TYPE = 8; | |
| jscsspToken.DASHMATCH_TYPE = 9; | |
| jscsspToken.BEGINSMATCH_TYPE = 10; | |
| jscsspToken.ENDSMATCH_TYPE = 11; | |
| jscsspToken.CONTAINSMATCH_TYPE = 12; | |
| jscsspToken.SYMBOL_TYPE = 13; | |
| jscsspToken.DIMENSION_TYPE = 14; | |
| jscsspToken.PERCENTAGE_TYPE = 15; | |
| jscsspToken.HEX_TYPE = 16; | |
| jscsspToken.prototype = { | |
| isNotNull: function () | |
| { | |
| return this.type; | |
| }, | |
| _isOfType: function (aType, aValue) | |
| { | |
| return (this.type == aType && (!aValue || this.value.toLowerCase() == aValue)); | |
| }, | |
| isWhiteSpace: function(w) | |
| { | |
| return this._isOfType(jscsspToken.WHITESPACE_TYPE, w); | |
| }, | |
| isString: function() | |
| { | |
| return this._isOfType(jscsspToken.STRING_TYPE); | |
| }, | |
| isComment: function() | |
| { | |
| return this._isOfType(jscsspToken.COMMENT_TYPE); | |
| }, | |
| isNumber: function(n) | |
| { | |
| return this._isOfType(jscsspToken.NUMBER_TYPE, n); | |
| }, | |
| isIdent: function(i) | |
| { | |
| return this._isOfType(jscsspToken.IDENT_TYPE, i); | |
| }, | |
| isFunction: function(f) | |
| { | |
| return this._isOfType(jscsspToken.FUNCTION_TYPE, f); | |
| }, | |
| isAtRule: function(a) | |
| { | |
| return this._isOfType(jscsspToken.ATRULE_TYPE, a); | |
| }, | |
| isIncludes: function() | |
| { | |
| return this._isOfType(jscsspToken.INCLUDES_TYPE); | |
| }, | |
| isDashmatch: function() | |
| { | |
| return this._isOfType(jscsspToken.DASHMATCH_TYPE); | |
| }, | |
| isBeginsmatch: function() | |
| { | |
| return this._isOfType(jscsspToken.BEGINSMATCH_TYPE); | |
| }, | |
| isEndsmatch: function() | |
| { | |
| return this._isOfType(jscsspToken.ENDSMATCH_TYPE); | |
| }, | |
| isContainsmatch: function() | |
| { | |
| return this._isOfType(jscsspToken.CONTAINSMATCH_TYPE); | |
| }, | |
| isSymbol: function(c) | |
| { | |
| return this._isOfType(jscsspToken.SYMBOL_TYPE, c); | |
| }, | |
| isDimension: function() | |
| { | |
| return this._isOfType(jscsspToken.DIMENSION_TYPE); | |
| }, | |
| isPercentage: function() | |
| { | |
| return this._isOfType(jscsspToken.PERCENTAGE_TYPE); | |
| }, | |
| isHex: function() | |
| { | |
| return this._isOfType(jscsspToken.HEX_TYPE); | |
| }, | |
| isDimensionOfUnit: function(aUnit) | |
| { | |
| return (this.isDimension() && this.unit == aUnit); | |
| }, | |
| isLength: function() | |
| { | |
| return (this.isPercentage() || | |
| this.isDimensionOfUnit("cm") || | |
| this.isDimensionOfUnit("mm") || | |
| this.isDimensionOfUnit("in") || | |
| this.isDimensionOfUnit("pc") || | |
| this.isDimensionOfUnit("px") || | |
| this.isDimensionOfUnit("em") || | |
| this.isDimensionOfUnit("ex") || | |
| this.isDimensionOfUnit("pt")); | |
| }, | |
| isAngle: function() | |
| { | |
| return (this.isDimensionOfUnit("deg") || | |
| this.isDimensionOfUnit("rad") || | |
| this.isDimensionOfUnit("grad")); | |
| } | |
| } | |
| /* kJscsspCHARSET_RULE */ | |
| function jscsspCharsetRule() | |
| { | |
| this.type = kJscsspCHARSET_RULE; | |
| this.encoding = null; | |
| this.parsedCssText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspCharsetRule.prototype = { | |
| cssText: function() { | |
| return "@charset " + this.encoding + ";"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| if (parser.parseCharsetRule(sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.encoding = newRule.encoding; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspCOMMENT */ | |
| function jscsspComment() | |
| { | |
| this.type = kJscsspCOMMENT; | |
| this.parsedCssText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspComment.prototype = { | |
| cssText: function() { | |
| return this.parsedCssText; | |
| }, | |
| setCssText: function(val) { | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, false); | |
| if (token.isComment()) | |
| this.parsedCssText = token.value; | |
| else | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspSTYLE_DECLARATION */ | |
| function jscsspDeclaration() | |
| { | |
| this.type = kJscsspSTYLE_DECLARATION; | |
| this.property = null; | |
| this.values = []; | |
| this.valueText = null; | |
| this.priority = null; | |
| this.parsedCssText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspDeclaration.prototype = { | |
| kCOMMA_SEPARATED: { | |
| "cursor": true, | |
| "font-family": true, | |
| "voice-family": true, | |
| "background-image": true | |
| }, | |
| kUNMODIFIED_COMMA_SEPARATED_PROPERTIES: { | |
| "text-shadow": true, | |
| "box-shadow": true, | |
| "-moz-transition": true, | |
| "-moz-transition-property": true, | |
| "-moz-transition-duration": true, | |
| "-moz-transition-timing-function": true, | |
| "-moz-transition-delay": true, | |
| "src": true, | |
| "-moz-font-feature-settings": true | |
| }, | |
| cssText: function() { | |
| var prefixes = PrefixHelper.prefixesForProperty(this.property); | |
| var rv = ""; | |
| if (this.property in this.kUNMODIFIED_COMMA_SEPARATED_PROPERTIES) { | |
| if (prefixes) { | |
| rv = ""; | |
| for (var propertyIndex = 0; propertyIndex < prefixes.length; propertyIndex++) { | |
| var property = prefixes[propertyIndex]; | |
| rv += (propertyIndex ? gTABS : "") + property + ": "; | |
| rv += this.valueText + (this.priority ? " !important" : "") + ";"; | |
| rv += ((prefixes.length > 1 && propertyIndex != prefixes.length -1) ? "\n" : ""); | |
| } | |
| return rv; | |
| } | |
| return this.property + ": " + this.valueText + | |
| (this.priority ? " !important" : "") + ";" | |
| } | |
| if (prefixes) { | |
| rv = ""; | |
| for (var propertyIndex = 0; propertyIndex < prefixes.length; propertyIndex++) { | |
| var property = prefixes[propertyIndex]; | |
| rv += (propertyIndex ? gTABS : "") + property + ": "; | |
| var separator = (property in this.kCOMMA_SEPARATED) ? ", " : " "; | |
| for (var i = 0; i < this.values.length; i++) | |
| if (this.values[i].cssText() != null) | |
| rv += (i ? separator : "") + this.values[i].cssText(); | |
| else | |
| return null; | |
| rv += (this.priority ? " !important" : "") + ";" + | |
| ((prefixes.length > 1 && propertyIndex != prefixes.length -1) ? "\n" : ""); | |
| } | |
| return rv; | |
| } | |
| var separator = (this.property in this.kCOMMA_SEPARATED) ? ", " : " "; | |
| var extras = {"webkit": false, "presto": false, "trident": false, "gecko1.9.2": false, "generic": false } | |
| for (var i = 0; i < this.values.length; i++) { | |
| var v = this.values[i].cssText(); | |
| if (v != null) { | |
| var paren = v.indexOf("("); | |
| var kwd = v; | |
| if (paren != -1) | |
| kwd = v.substr(0, paren); | |
| if (kwd in kCSS_VENDOR_VALUES) { | |
| for (var j in kCSS_VENDOR_VALUES[kwd]) { | |
| extras[j] = extras[j] || (kCSS_VENDOR_VALUES[kwd][j] != ""); | |
| } | |
| } | |
| } | |
| else | |
| return null; | |
| } | |
| for (var j in extras) { | |
| if (extras[j]) { | |
| var str = "\n" + gTABS + this.property + ": "; | |
| for (var i = 0; i < this.values.length; i++) { | |
| var v = this.values[i].cssText(); | |
| if (v != null) { | |
| var paren = v.indexOf("("); | |
| var kwd = v; | |
| if (paren != -1) | |
| kwd = v.substr(0, paren); | |
| if (kwd in kCSS_VENDOR_VALUES) { | |
| functor = kCSS_VENDOR_VALUES[kwd][j]; | |
| if (functor) { | |
| v = (typeof functor == "string") ? functor : functor(v, j); | |
| if (!v) { | |
| str = null; | |
| break; | |
| } | |
| } | |
| } | |
| str += (i ? separator : "") + v; | |
| } | |
| else | |
| return null; | |
| } | |
| if (str) | |
| rv += str + ";" | |
| else | |
| rv += "\n" + gTABS + "/* Impossible to translate property " + this.property + " for " + j + " */"; | |
| } | |
| } | |
| rv += "\n" + gTABS + this.property + ": "; | |
| for (var i = 0; i < this.values.length; i++) { | |
| var v = this.values[i].cssText(); | |
| if (v != null) { | |
| rv += (i ? separator : "") + v; | |
| } | |
| } | |
| rv += (this.priority ? " !important" : "") + ";"; | |
| return rv; | |
| }, | |
| setCssText: function(val) { | |
| var declarations = []; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (parser.parseDeclaration(token, declarations, true, true, null) | |
| && declarations.length | |
| && declarations[0].type == kJscsspSTYLE_DECLARATION) { | |
| var newDecl = declarations.cssRules[0]; | |
| this.property = newDecl.property; | |
| this.value = newDecl.value; | |
| this.priority = newDecl.priority; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspUNKNOWN_RULE */ | |
| function jscsspErrorRule(aErrorMsg) | |
| { | |
| this.error = aErrorMsg ? aErrorMsg : "INVALID"; | |
| this.type = kJscsspUNKNOWN_RULE; | |
| this.parsedCssText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspErrorRule.prototype = { | |
| cssText: function() { | |
| return this.parsedCssText; | |
| } | |
| }; | |
| /* kJscsspFONT_FACE_RULE */ | |
| function jscsspFontFaceRule() | |
| { | |
| this.type = kJscsspFONT_FACE_RULE; | |
| this.parsedCssText = null; | |
| this.descriptors = []; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspFontFaceRule.prototype = { | |
| cssText: function() { | |
| var rv = gTABS + "@font-face {\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.descriptors.length; i++) | |
| rv += gTABS + this.descriptors[i].cssText() + "\n"; | |
| gTABS = preservedGTABS; | |
| return rv + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@font-face")) { | |
| if (parser.parseFontFaceRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.descriptors = newRule.descriptors; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspIMPORT_RULE */ | |
| function jscsspImportRule() | |
| { | |
| this.type = kJscsspIMPORT_RULE; | |
| this.parsedCssText = null; | |
| this.href = null; | |
| this.media = []; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspImportRule.prototype = { | |
| cssText: function() { | |
| var mediaString = this.media.join(", "); | |
| return "@import " + this.href | |
| + ((mediaString && mediaString != "all") ? mediaString + " " : "") | |
| + ";"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@import")) { | |
| if (parser.parseImportRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.href = newRule.href; | |
| this.media = newRule.media; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspKEYFRAME_RULE */ | |
| function jscsspKeyframeRule() | |
| { | |
| this.type = kJscsspKEYFRAME_RULE; | |
| this.parsedCssText = null; | |
| this.declarations = [] | |
| this.keyText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspKeyframeRule.prototype = { | |
| cssText: function() { | |
| var rv = this.keyText + " {\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.declarations.length; i++) { | |
| var declText = this.declarations[i].cssText(); | |
| if (declText) | |
| rv += gTABS + this.declarations[i].cssText() + "\n"; | |
| } | |
| gTABS = preservedGTABS; | |
| return rv + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (!token.isNotNull()) { | |
| if (parser.parseKeyframeRule(token, sheet, false)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.keyText = newRule.keyText; | |
| this.declarations = newRule.declarations; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspKEYFRAMES_RULE */ | |
| function jscsspKeyframesRule() | |
| { | |
| this.type = kJscsspKEYFRAMES_RULE; | |
| this.parsedCssText = null; | |
| this.cssRules = []; | |
| this.name = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspKeyframesRule.prototype = { | |
| cssText: function() { | |
| var rv = ""; | |
| var prefixes = ["moz", "webkit", "ms", "o", ""]; | |
| for (var p = 0; p < prefixes.length; p++) { | |
| rv += gTABS | |
| + "@" + (prefixes[p] ? "-" + prefixes[p] + "-" : "") + "keyframes " | |
| + this.name + " {\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.cssRules.length; i++) | |
| rv += gTABS + this.cssRules[i].cssText() + "\n"; | |
| gTABS = preservedGTABS; | |
| rv += gTABS + "}\n\n"; | |
| } | |
| return rv; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@-mozkeyframes")) { | |
| if (parser.parseKeyframesRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.cssRules = newRule.cssRules; | |
| this.name = newRule.name; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspMEDIA_RULE */ | |
| function jscsspMediaRule() | |
| { | |
| this.type = kJscsspMEDIA_RULE; | |
| this.parsedCssText = null; | |
| this.cssRules = []; | |
| this.media = []; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspMediaRule.prototype = { | |
| cssText: function() { | |
| var rv = gTABS + "@media " + this.media.join(", ") + " {\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.cssRules.length; i++) | |
| rv += this.cssRules[i].cssText() + "\n"; | |
| gTABS = preservedGTABS; | |
| return rv + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@media")) { | |
| if (parser.parseMediaRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.cssRules = newRule.cssRules; | |
| this.media = newRule.media; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspNAMESPACE_RULE */ | |
| function jscsspNamespaceRule() | |
| { | |
| this.type = kJscsspNAMESPACE_RULE; | |
| this.parsedCssText = null; | |
| this.prefix = null; | |
| this.url = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspNamespaceRule.prototype = { | |
| cssText: function() { | |
| return "@namespace " + (this.prefix ? this.prefix + " ": "") | |
| + this.url | |
| + ";"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@namespace")) { | |
| if (parser.parseNamespaceRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.url = newRule.url; | |
| this.prefix = newRule.prefix; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspPAGE_RULE */ | |
| function jscsspPageRule() | |
| { | |
| this.type = kJscsspPAGE_RULE; | |
| this.parsedCssText = null; | |
| this.pageSelector = null; | |
| this.declarations = []; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspPageRule.prototype = { | |
| cssText: function() { | |
| var rv = gTABS + "@page " | |
| + (this.pageSelector ? this.pageSelector + " ": "") | |
| + "{\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.declarations.length; i++) | |
| rv += gTABS + this.declarations[i].cssText() + "\n"; | |
| gTABS = preservedGTABS; | |
| return rv + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@page")) { | |
| if (parser.parsePageRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.pageSelector = newRule.pageSelector; | |
| this.declarations = newRule.declarations; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspSTYLE_RULE */ | |
| function jscsspStyleRule() | |
| { | |
| this.type = kJscsspSTYLE_RULE; | |
| this.parsedCssText = null; | |
| this.declarations = [] | |
| this.mSelectorText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspStyleRule.prototype = { | |
| cssText: function() { | |
| var rv = gTABS + this.mSelectorText + " {"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.declarations.length; i++) { | |
| var declText = this.declarations[i].cssText(); | |
| if (declText) | |
| rv += gTABS + this.declarations[i].cssText() ; | |
| } | |
| gTABS = preservedGTABS; | |
| return rv + "\n" + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (!token.isNotNull()) { | |
| if (parser.parseStyleRule(token, sheet, false)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.mSelectorText = newRule.mSelectorText; | |
| this.declarations = newRule.declarations; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| }, | |
| selectorText: function() { | |
| return this.mSelectorText; | |
| }, | |
| setSelectorText: function(val) { | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (!token.isNotNull()) { | |
| var s = parser.parseSelector(token, true); | |
| if (s) { | |
| this.mSelectorText = s.selector; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| function jscsspStylesheet() | |
| { | |
| this.cssRules = []; | |
| this.variables = {}; | |
| } | |
| jscsspStylesheet.prototype = { | |
| insertRule: function(aRule, aIndex) { | |
| try { | |
| this.cssRules.splice(aIndex, 1, aRule); | |
| } | |
| catch(e) { | |
| } | |
| }, | |
| deleteRule: function(aIndex) { | |
| try { | |
| this.cssRules.splice(aIndex); | |
| } | |
| catch(e) { | |
| } | |
| }, | |
| cssText: function() { | |
| var rv = ""; | |
| for (var i = 0; i < this.cssRules.length; i++) | |
| rv += this.cssRules[i].cssText() + "\n\n"; | |
| return rv; | |
| } | |
| }; | |
| var kJscsspINHERIT_VALUE = 0; | |
| var kJscsspPRIMITIVE_VALUE = 1; | |
| var kJscsspVARIABLE_VALUE = 4; | |
| function jscsspVariable(aType, aSheet) | |
| { | |
| this.value = ""; | |
| this.type = aType; | |
| this.name = null; | |
| this.parentRule = null; | |
| this.parentStyleSheet = aSheet; | |
| } | |
| jscsspVariable.prototype = { | |
| cssText: function() { | |
| if (this.type == kJscsspVARIABLE_VALUE) | |
| return this.resolveVariable(this.name, this.parentRule, this.parentStyleSheet); | |
| else | |
| return this.value; | |
| }, | |
| setCssText: function(val) { | |
| if (this.type == kJscsspVARIABLE_VALUE) | |
| throw DOMException.SYNTAX_ERR; | |
| else | |
| this.value = val; | |
| }, | |
| resolveVariable: function(aName, aRule, aSheet) | |
| { | |
| return "var(" + aName + ")"; | |
| } | |
| }; | |
| /* kJscsspVARIABLES_RULE */ | |
| function jscsspVariablesRule() | |
| { | |
| this.type = kJscsspVARIABLES_RULE; | |
| this.parsedCssText = null; | |
| this.declarations = []; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| this.media = null; | |
| } | |
| jscsspVariablesRule.prototype = { | |
| cssText: function() { | |
| var rv = gTABS + "@variables " + | |
| (this.media.length ? this.media.join(", ") + " " : "") + | |
| "{\n"; | |
| var preservedGTABS = gTABS; | |
| gTABS += " "; | |
| for (var i = 0; i < this.declarations.length; i++) | |
| rv += gTABS + this.declarations[i].cssText() + "\n"; | |
| gTABS = preservedGTABS; | |
| return rv + gTABS + "}"; | |
| }, | |
| setCssText: function(val) { | |
| var sheet = {cssRules: []}; | |
| var parser = new CSSParser(val); | |
| var token = parser.getToken(true, true); | |
| if (token.isAtRule("@variables")) { | |
| if (parser.parseVariablesRule(token, sheet)) { | |
| var newRule = sheet.cssRules[0]; | |
| this.declarations = newRule.declarations; | |
| this.parsedCssText = newRule.parsedCssText; | |
| return; | |
| } | |
| } | |
| throw DOMException.SYNTAX_ERR; | |
| } | |
| }; | |
| /* kJscsspWHITE_SPACE */ | |
| function jscsspWhitespace() | |
| { | |
| this.type = kJscsspWHITE_SPACE; | |
| this.parsedCssText = null; | |
| this.parentStyleSheet = null; | |
| this.parentRule = null; | |
| } | |
| jscsspWhitespace.prototype = { | |
| cssText: function() { | |
| return this.parsedCssText; | |
| } | |
| }; | |
| var kJscsspUNKNOWN_RULE = 0; | |
| var kJscsspSTYLE_RULE = 1 | |
| var kJscsspCHARSET_RULE = 2; | |
| var kJscsspIMPORT_RULE = 3; | |
| var kJscsspMEDIA_RULE = 4; | |
| var kJscsspFONT_FACE_RULE = 5; | |
| var kJscsspPAGE_RULE = 6; | |
| var kJscsspKEYFRAMES_RULE = 7; | |
| var kJscsspKEYFRAME_RULE = 8; | |
| var kJscsspNAMESPACE_RULE = 100; | |
| var kJscsspCOMMENT = 101; | |
| var kJscsspWHITE_SPACE = 102; | |
| var kJscsspVARIABLES_RULE = 200; | |
| var kJscsspSTYLE_DECLARATION = 1000; | |
| var gTABS = ""; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment