Files
Umbraco-CMS/src/Umbraco.Web.UI.Client/lib/cssparser/cssparser.js
2014-05-09 12:23:59 +02:00

5496 lines
172 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ***** 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 = "";