diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
index 582f518525454ee8824be06b2dbf7d93adb6f851..db84371104bfc068151687aebde7002e55289c18 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
@@ -28,7 +28,7 @@
 
 <script type="text/javascript" src="&dtml-portal_url;/codemirror/lib/codemirror.js"></script>\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/lib/codemirror.css">\n
-<script type="text/javascript" src="&dtml-portal_url;/codemirror/mode/python/python.js"></script>\n
+<script type="text/javascript" src="&dtml-portal_url;/codemirror/mode/&dtml-mode;/&dtml-mode;.js"></script>\n
 <script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/edit/matchbrackets.js"></script>\n
 \n
 <!-- Trailing spaces -->\n
@@ -50,6 +50,7 @@
  -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/hint/show-hint.css">\n
 <script src="&dtml-portal_url;/codemirror/addon/hint/show-hint.js"></script>\n
+<script src="&dtml-portal_url;/codemirror/addon/hint/anyword-hint.js"></script>\n
 \n
 <!-- Code folding -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/fold/foldgutter.css">\n
@@ -63,11 +64,18 @@
 <script type="text/javascript" src="&dtml-portal_url;/diff_match_patch/javascript/diff_match_patch_uncompressed.js"></script>\n
 <script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/merge/merge.js"></script>\n
 \n
-<!-- Lint\n
-     TODO: Only support Python for now -->\n
+<!-- Linter -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/lint/lint.css">\n
 <script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/lint/lint.js"></script>\n
 \n
+<dtml-if expr="mode == \'javascript\'">\n
+<script type="text/javascript" src="&dtml-portal_url;/jshint.js"></script>\n
+<script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/lint/javascript-lint.js"></script>\n
+<dtml-elif expr="mode == \'css\'">\n
+<script type="text/javascript" src="&dtml-portal_url;/csslint.js"></script>\n
+<script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/lint/css-lint.js"></script>\n
+</dtml-if>\n
+\n
 <style type="text/css">\n
  .maximize_fullscreen_message {\n
    display: table;\n
@@ -134,6 +142,8 @@
  }\n
 </style>\n
 \n
+<!-- TODO: Only supported for ZODB Components -->\n
+<dtml-unless bound_names>\n
 <input type="button" value="Maximize" onclick="maximize()"\n
        class="editor_action_button" />\n
 <input type="button" value="Fullscreen" onclick="switchToFullScreen(cm)"\n
@@ -141,11 +151,8 @@
 \n
 <div id="merge" style="height: 100%; width: 100%">\n
   <div id="view" style="display: none;"></div>\n
-\n
-<textarea id="&dtml-field_id;" name="&dtml-field_id;" style="display: none;">\n
-<dtml-var content>\n
-</textarea>\n
 </div>\n
+</dtml-unless>\n
 \n
 <script type="text/javascript">\n
  error_element = $(\'div.input > .error\');\n
@@ -155,6 +162,29 @@
  merge_mode_elem = null;\n
 \n
  maximize_mode_message = $(\'<span id="maximize_message">Press ESC to leave maximize mode</span>\');\n
+\n
+ function getTextareaField() {\n
+   // When the textarea does not exist yet (eg ERP5Form EditorField)\n
+<dtml-if field_id>\n
+   textarea = $(\'#&dtml-field_id;\');\n
+   if(!textarea.length) {\n
+     $(\'#merge\').append(\n
+       \'<textarea id="&dtml-field_id;" name="&dtml-field_id;" style="display: none;">\' + \n
+       `&dtml-content;` +\n
+       \'</textarea>\');\n
+\n
+     textarea = $(\'#&dtml-field_id;\');\n
+   }\n
+<dtml-elif textarea_selector>\n
+   textarea = $(\'<dtml-var name="textarea_selector">\');\n
+<dtml-else>\n
+   <dtml-raise NameError>\n
+     Either \'textarea_selector\' or \'field_id\' (ID of the textarea field to be\n
+     created) must be passed.\n
+   </dtml-raise>\n
+</dtml-if>\n
+  return textarea;\n
+ }\n
 \n
  function maximizeFullscreenRemoveSaveMessage() {\n
    $(\'.maximize_fullscreen_message\').remove();\n
@@ -291,7 +321,7 @@
 \n
    if(merge_mode_elem)\n
      // TODO: Hack, \'cm\' should work!\n
-     $(\'#&dtml-field_id;\').val(merge_mode_elem.edit.getValue());\n
+     getTextareaField().val(merge_mode_elem.edit.getValue());\n
    else\n
      cm.save();\n
 \n
@@ -401,9 +431,14 @@
  }\n
 \n
  function checkPythonSourceCode(text, updateLinting, options, cm) {\n
+   checker_parameters = {code: text};\n
+<dtml-if bound_names>\n
+   checker_parameters[\'bound_names\'] = <dtml-var name="bound_names">;\n
+   checker_parameters[\'params\'] = $(\'input[name="params"]\').val();\n
+</dtml-if>\n
    $.post(\n
      \'&dtml-portal_url;/ERP5Site_checkPythonSourceCodeAsJSON\',\n
-     {\'data\': JSON.stringify({code: text})},\n
+     {\'data\': JSON.stringify(checker_parameters)},\n
       function(data){\n
         var messages = data.annotations;\n
         var found = [];\n
@@ -420,11 +455,20 @@
         updateLinting(cm, found);\n
    });\n
  }\n
+\n
+<dtml-if expr="mode == \'python\'">\n
+ lint_option = {"getAnnotations": checkPythonSourceCode,\n
+                "async": true};\n
+<dtml-elif expr="mode in (\'css\', \'javascript\')">\n
+ lint_option = true;\n
+<dtml-else>\n
+ lint_option = false;\n
+</dtml-if>\n
 \n
  // CodeMirror expects a DOM element, not a JQuery Object\n
  var cm = CodeMirror.fromTextArea(\n
-   $(\'#&dtml-field_id;\')[0],\n
-   {mode: "python",\n
+   getTextareaField()[0],\n
+   {mode: "&dtml-mode;",\n
     lineNumbers: true,\n
     showTrailingSpace: true,\n
     tabSize: 2,\n
@@ -439,8 +483,7 @@
     gutters: ["CodeMirror-lint-markers",\n
               "CodeMirror-linenumbers",\n
               "CodeMirror-foldgutter"],\n
-    lint: {"getAnnotations": checkPythonSourceCode,\n
-           "async": true}\n
+    lint: lint_option\n
     });\n
  //cm.foldCode(CodeMirror.Pos(8, 0));\n
 \n
@@ -475,7 +518,7 @@
      {value: cm.getValue(),\n
       orig: data,\n
       highlightDifferences: true,\n
-      mode: "python",\n
+      mode: "&dtml-mode;",\n
       lineNumbers: true,\n
       showTrailingSpace: true,\n
       matchBrackets: true,\n
@@ -630,7 +673,10 @@
          success: successHandler});\n
  }\n
 \n
+<dtml-unless bound_names>\n
+ <!-- TODO: Not supported for Python Scripts yet -->\n
  generateHistorySelectElement();\n
+</dtml-unless>\n
 </script>\n
 
 
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/csslint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/csslint.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..95b12447e10ae855705596d1e9541b8316cec1a0
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/csslint.js.xml
@@ -0,0 +1,9388 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts29784826.78</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>csslint.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>306511</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+CSSLint\n
+Copyright (c) 2013 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.\n
+\n
+Permission is hereby granted, free of charge, to any person obtaining a copy\n
+of this software and associated documentation files (the "Software"), to deal\n
+in the Software without restriction, including without limitation the rights\n
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n
+copies of the Software, and to permit persons to whom the Software is\n
+furnished to do so, subject to the following conditions:\n
+\n
+The above copyright notice and this permission notice shall be included in\n
+all copies or substantial portions of the Software.\n
+\n
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n
+THE SOFTWARE.\n
+\n
+*/\n
+/* Build: v0.10.0 15-August-2013 01:07:22 */\n
+var exports = exports || {};\n
+var CSSLint = (function(){\n
+/*!\n
+Parser-Lib\n
+Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n
+\n
+Permission is hereby granted, free of charge, to any person obtaining a copy\n
+of this software and associated documentation files (the "Software"), to deal\n
+in the Software without restriction, including without limitation the rights\n
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n
+copies of the Software, and to permit persons to whom the Software is\n
+furnished to do so, subject to the following conditions:\n
+\n
+The above copyright notice and this permission notice shall be included in\n
+all copies or substantial portions of the Software.\n
+\n
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n
+THE SOFTWARE.\n
+\n
+*/\n
+/* Version v0.2.3, Build time: 19-June-2013 11:16:15 */\n
+var parserlib = {};\n
+(function(){\n
+\n
+\n
+/**\n
+ * A generic base to inherit from for any object\n
+ * that needs event handling.\n
+ * @class EventTarget\n
+ * @constructor\n
+ */\n
+function EventTarget(){\n
+\n
+    /**\n
+     * The array of listeners for various events.\n
+     * @type Object\n
+     * @property _listeners\n
+     * @private\n
+     */\n
+    this._listeners = {};\n
+}\n
+\n
+EventTarget.prototype = {\n
+\n
+    //restore constructor\n
+    constructor: EventTarget,\n
+\n
+    /**\n
+     * Adds a listener for a given event type.\n
+     * @param {String} type The type of event to add a listener for.\n
+     * @param {Function} listener The function to call when the event occurs.\n
+     * @return {void}\n
+     * @method addListener\n
+     */\n
+    addListener: function(type, listener){\n
+        if (!this._listeners[type]){\n
+            this._listeners[type] = [];\n
+        }\n
+\n
+        this._listeners[type].push(listener);\n
+    },\n
+\n
+    /**\n
+     * Fires an event based on the passed-in object.\n
+     * @param {Object|String} event An object with at least a \'type\' attribute\n
+     *      or a string indicating the event name.\n
+     * @return {void}\n
+     * @method fire\n
+     */\n
+    fire: function(event){\n
+        if (typeof event == "string"){\n
+            event = { type: event };\n
+        }\n
+        if (typeof event.target != "undefined"){\n
+            event.target = this;\n
+        }\n
+\n
+        if (typeof event.type == "undefined"){\n
+            throw new Error("Event object missing \'type\' property.");\n
+        }\n
+\n
+        if (this._listeners[event.type]){\n
+\n
+            //create a copy of the array and use that so listeners can\'t chane\n
+            var listeners = this._listeners[event.type].concat();\n
+            for (var i=0, len=listeners.length; i < len; i++){\n
+                listeners[i].call(this, event);\n
+            }\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Removes a listener for a given event type.\n
+     * @param {String} type The type of event to remove a listener from.\n
+     * @param {Function} listener The function to remove from the event.\n
+     * @return {void}\n
+     * @method removeListener\n
+     */\n
+    removeListener: function(type, listener){\n
+        if (this._listeners[type]){\n
+            var listeners = this._listeners[type];\n
+            for (var i=0, len=listeners.length; i < len; i++){\n
+                if (listeners[i] === listener){\n
+                    listeners.splice(i, 1);\n
+                    break;\n
+                }\n
+            }\n
+\n
+\n
+        }\n
+    }\n
+};\n
+/**\n
+ * Convenient way to read through strings.\n
+ * @namespace parserlib.util\n
+ * @class StringReader\n
+ * @constructor\n
+ * @param {String} text The text to read.\n
+ */\n
+function StringReader(text){\n
+\n
+    /**\n
+     * The input text with line endings normalized.\n
+     * @property _input\n
+     * @type String\n
+     * @private\n
+     */\n
+    this._input = text.replace(/\\n\\r?/g, "\\n");\n
+\n
+\n
+    /**\n
+     * The row for the character to be read next.\n
+     * @property _line\n
+     * @type int\n
+     * @private\n
+     */\n
+    this._line = 1;\n
+\n
+\n
+    /**\n
+     * The column for the character to be read next.\n
+     * @property _col\n
+     * @type int\n
+     * @private\n
+     */\n
+    this._col = 1;\n
+\n
+    /**\n
+     * The index of the character in the input to be read next.\n
+     * @property _cursor\n
+     * @type int\n
+     * @private\n
+     */\n
+    this._cursor = 0;\n
+}\n
+\n
+StringReader.prototype = {\n
+\n
+    //restore constructor\n
+    constructor: StringReader,\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Position info\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Returns the column of the character to be read next.\n
+     * @return {int} The column of the character to be read next.\n
+     * @method getCol\n
+     */\n
+    getCol: function(){\n
+        return this._col;\n
+    },\n
+\n
+    /**\n
+     * Returns the row of the character to be read next.\n
+     * @return {int} The row of the character to be read next.\n
+     * @method getLine\n
+     */\n
+    getLine: function(){\n
+        return this._line ;\n
+    },\n
+\n
+    /**\n
+     * Determines if you\'re at the end of the input.\n
+     * @return {Boolean} True if there\'s no more input, false otherwise.\n
+     * @method eof\n
+     */\n
+    eof: function(){\n
+        return (this._cursor == this._input.length);\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Basic reading\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Reads the next character without advancing the cursor.\n
+     * @param {int} count How many characters to look ahead (default is 1).\n
+     * @return {String} The next character or null if there is no next character.\n
+     * @method peek\n
+     */\n
+    peek: function(count){\n
+        var c = null;\n
+        count = (typeof count == "undefined" ? 1 : count);\n
+\n
+        //if we\'re not at the end of the input...\n
+        if (this._cursor < this._input.length){\n
+\n
+            //get character and increment cursor and column\n
+            c = this._input.charAt(this._cursor + count - 1);\n
+        }\n
+\n
+        return c;\n
+    },\n
+\n
+    /**\n
+     * Reads the next character from the input and adjusts the row and column\n
+     * accordingly.\n
+     * @return {String} The next character or null if there is no next character.\n
+     * @method read\n
+     */\n
+    read: function(){\n
+        var c = null;\n
+\n
+        //if we\'re not at the end of the input...\n
+        if (this._cursor < this._input.length){\n
+\n
+            //if the last character was a newline, increment row count\n
+            //and reset column count\n
+            if (this._input.charAt(this._cursor) == "\\n"){\n
+                this._line++;\n
+                this._col=1;\n
+            } else {\n
+                this._col++;\n
+            }\n
+\n
+            //get character and increment cursor and column\n
+            c = this._input.charAt(this._cursor++);\n
+        }\n
+\n
+        return c;\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Misc\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Saves the current location so it can be returned to later.\n
+     * @method mark\n
+     * @return {void}\n
+     */\n
+    mark: function(){\n
+        this._bookmark = {\n
+            cursor: this._cursor,\n
+            line:   this._line,\n
+            col:    this._col\n
+        };\n
+    },\n
+\n
+    reset: function(){\n
+        if (this._bookmark){\n
+            this._cursor = this._bookmark.cursor;\n
+            this._line = this._bookmark.line;\n
+            this._col = this._bookmark.col;\n
+            delete this._bookmark;\n
+        }\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Advanced reading\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Reads up to and including the given string. Throws an error if that\n
+     * string is not found.\n
+     * @param {String} pattern The string to read.\n
+     * @return {String} The string when it is found.\n
+     * @throws Error when the string pattern is not found.\n
+     * @method readTo\n
+     */\n
+    readTo: function(pattern){\n
+\n
+        var buffer = "",\n
+            c;\n
+\n
+        /*\n
+         * First, buffer must be the same length as the pattern.\n
+         * Then, buffer must end with the pattern or else reach the\n
+         * end of the input.\n
+         */\n
+        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){\n
+            c = this.read();\n
+            if (c){\n
+                buffer += c;\n
+            } else {\n
+                throw new Error("Expected \\"" + pattern + "\\" at line " + this._line  + ", col " + this._col + ".");\n
+            }\n
+        }\n
+\n
+        return buffer;\n
+\n
+    },\n
+\n
+    /**\n
+     * Reads characters while each character causes the given\n
+     * filter function to return true. The function is passed\n
+     * in each character and either returns true to continue\n
+     * reading or false to stop.\n
+     * @param {Function} filter The function to read on each character.\n
+     * @return {String} The string made up of all characters that passed the\n
+     *      filter check.\n
+     * @method readWhile\n
+     */\n
+    readWhile: function(filter){\n
+\n
+        var buffer = "",\n
+            c = this.read();\n
+\n
+        while(c !== null && filter(c)){\n
+            buffer += c;\n
+            c = this.read();\n
+        }\n
+\n
+        return buffer;\n
+\n
+    },\n
+\n
+    /**\n
+     * Reads characters that match either text or a regular expression and\n
+     * returns those characters. If a match is found, the row and column\n
+     * are adjusted; if no match is found, the reader\'s state is unchanged.\n
+     * reading or false to stop.\n
+     * @param {String|RegExp} matchter If a string, then the literal string\n
+     *      value is searched for. If a regular expression, then any string\n
+     *      matching the pattern is search for.\n
+     * @return {String} The string made up of all characters that matched or\n
+     *      null if there was no match.\n
+     * @method readMatch\n
+     */\n
+    readMatch: function(matcher){\n
+\n
+        var source = this._input.substring(this._cursor),\n
+            value = null;\n
+\n
+        //if it\'s a string, just do a straight match\n
+        if (typeof matcher == "string"){\n
+            if (source.indexOf(matcher) === 0){\n
+                value = this.readCount(matcher.length);\n
+            }\n
+        } else if (matcher instanceof RegExp){\n
+            if (matcher.test(source)){\n
+                value = this.readCount(RegExp.lastMatch.length);\n
+            }\n
+        }\n
+\n
+        return value;\n
+    },\n
+\n
+\n
+    /**\n
+     * Reads a given number of characters. If the end of the input is reached,\n
+     * it reads only the remaining characters and does not throw an error.\n
+     * @param {int} count The number of characters to read.\n
+     * @return {String} The string made up the read characters.\n
+     * @method readCount\n
+     */\n
+    readCount: function(count){\n
+        var buffer = "";\n
+\n
+        while(count--){\n
+            buffer += this.read();\n
+        }\n
+\n
+        return buffer;\n
+    }\n
+\n
+};\n
+/**\n
+ * Type to use when a syntax error occurs.\n
+ * @class SyntaxError\n
+ * @namespace parserlib.util\n
+ * @constructor\n
+ * @param {String} message The error message.\n
+ * @param {int} line The line at which the error occurred.\n
+ * @param {int} col The column at which the error occurred.\n
+ */\n
+function SyntaxError(message, line, col){\n
+\n
+    /**\n
+     * The column at which the error occurred.\n
+     * @type int\n
+     * @property col\n
+     */\n
+    this.col = col;\n
+\n
+    /**\n
+     * The line at which the error occurred.\n
+     * @type int\n
+     * @property line\n
+     */\n
+    this.line = line;\n
+\n
+    /**\n
+     * The text representation of the unit.\n
+     * @type String\n
+     * @property text\n
+     */\n
+    this.message = message;\n
+\n
+}\n
+\n
+//inherit from Error\n
+SyntaxError.prototype = new Error();\n
+/**\n
+ * Base type to represent a single syntactic unit.\n
+ * @class SyntaxUnit\n
+ * @namespace parserlib.util\n
+ * @constructor\n
+ * @param {String} text The text of the unit.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function SyntaxUnit(text, line, col, type){\n
+\n
+\n
+    /**\n
+     * The column of text on which the unit resides.\n
+     * @type int\n
+     * @property col\n
+     */\n
+    this.col = col;\n
+\n
+    /**\n
+     * The line of text on which the unit resides.\n
+     * @type int\n
+     * @property line\n
+     */\n
+    this.line = line;\n
+\n
+    /**\n
+     * The text representation of the unit.\n
+     * @type String\n
+     * @property text\n
+     */\n
+    this.text = text;\n
+\n
+    /**\n
+     * The type of syntax unit.\n
+     * @type int\n
+     * @property type\n
+     */\n
+    this.type = type;\n
+}\n
+\n
+/**\n
+ * Create a new syntax unit based solely on the given token.\n
+ * Convenience method for creating a new syntax unit when\n
+ * it represents a single token instead of multiple.\n
+ * @param {Object} token The token object to represent.\n
+ * @return {parserlib.util.SyntaxUnit} The object representing the token.\n
+ * @static\n
+ * @method fromToken\n
+ */\n
+SyntaxUnit.fromToken = function(token){\n
+    return new SyntaxUnit(token.value, token.startLine, token.startCol);\n
+};\n
+\n
+SyntaxUnit.prototype = {\n
+\n
+    //restore constructor\n
+    constructor: SyntaxUnit,\n
+\n
+    /**\n
+     * Returns the text representation of the unit.\n
+     * @return {String} The text representation of the unit.\n
+     * @method valueOf\n
+     */\n
+    valueOf: function(){\n
+        return this.toString();\n
+    },\n
+\n
+    /**\n
+     * Returns the text representation of the unit.\n
+     * @return {String} The text representation of the unit.\n
+     * @method toString\n
+     */\n
+    toString: function(){\n
+        return this.text;\n
+    }\n
+\n
+};\n
+/*global StringReader, SyntaxError*/\n
+\n
+/**\n
+ * Generic TokenStream providing base functionality.\n
+ * @class TokenStreamBase\n
+ * @namespace parserlib.util\n
+ * @constructor\n
+ * @param {String|StringReader} input The text to tokenize or a reader from\n
+ *      which to read the input.\n
+ */\n
+function TokenStreamBase(input, tokenData){\n
+\n
+    /**\n
+     * The string reader for easy access to the text.\n
+     * @type StringReader\n
+     * @property _reader\n
+     * @private\n
+     */\n
+    this._reader = input ? new StringReader(input.toString()) : null;\n
+\n
+    /**\n
+     * Token object for the last consumed token.\n
+     * @type Token\n
+     * @property _token\n
+     * @private\n
+     */\n
+    this._token = null;\n
+\n
+    /**\n
+     * The array of token information.\n
+     * @type Array\n
+     * @property _tokenData\n
+     * @private\n
+     */\n
+    this._tokenData = tokenData;\n
+\n
+    /**\n
+     * Lookahead token buffer.\n
+     * @type Array\n
+     * @property _lt\n
+     * @private\n
+     */\n
+    this._lt = [];\n
+\n
+    /**\n
+     * Lookahead token buffer index.\n
+     * @type int\n
+     * @property _ltIndex\n
+     * @private\n
+     */\n
+    this._ltIndex = 0;\n
+\n
+    this._ltIndexCache = [];\n
+}\n
+\n
+/**\n
+ * Accepts an array of token information and outputs\n
+ * an array of token data containing key-value mappings\n
+ * and matching functions that the TokenStream needs.\n
+ * @param {Array} tokens An array of token descriptors.\n
+ * @return {Array} An array of processed token data.\n
+ * @method createTokenData\n
+ * @static\n
+ */\n
+TokenStreamBase.createTokenData = function(tokens){\n
+\n
+    var nameMap     = [],\n
+        typeMap     = {},\n
+        tokenData     = tokens.concat([]),\n
+        i            = 0,\n
+        len            = tokenData.length+1;\n
+\n
+    tokenData.UNKNOWN = -1;\n
+    tokenData.unshift({name:"EOF"});\n
+\n
+    for (; i < len; i++){\n
+        nameMap.push(tokenData[i].name);\n
+        tokenData[tokenData[i].name] = i;\n
+        if (tokenData[i].text){\n
+            typeMap[tokenData[i].text] = i;\n
+        }\n
+    }\n
+\n
+    tokenData.name = function(tt){\n
+        return nameMap[tt];\n
+    };\n
+\n
+    tokenData.type = function(c){\n
+        return typeMap[c];\n
+    };\n
+\n
+    return tokenData;\n
+};\n
+\n
+TokenStreamBase.prototype = {\n
+\n
+    //restore constructor\n
+    constructor: TokenStreamBase,\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Matching methods\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Determines if the next token matches the given token type.\n
+     * If so, that token is consumed; if not, the token is placed\n
+     * back onto the token stream. You can pass in any number of\n
+     * token types and this will return true if any of the token\n
+     * types is found.\n
+     * @param {int|int[]} tokenTypes Either a single token type or an array of\n
+     *      token types that the next token might be. If an array is passed,\n
+     *      it\'s assumed that the token can be any of these.\n
+     * @param {variant} channel (Optional) The channel to read from. If not\n
+     *      provided, reads from the default (unnamed) channel.\n
+     * @return {Boolean} True if the token type matches, false if not.\n
+     * @method match\n
+     */\n
+    match: function(tokenTypes, channel){\n
+\n
+        //always convert to an array, makes things easier\n
+        if (!(tokenTypes instanceof Array)){\n
+            tokenTypes = [tokenTypes];\n
+        }\n
+\n
+        var tt  = this.get(channel),\n
+            i   = 0,\n
+            len = tokenTypes.length;\n
+\n
+        while(i < len){\n
+            if (tt == tokenTypes[i++]){\n
+                return true;\n
+            }\n
+        }\n
+\n
+        //no match found, put the token back\n
+        this.unget();\n
+        return false;\n
+    },\n
+\n
+    /**\n
+     * Determines if the next token matches the given token type.\n
+     * If so, that token is consumed; if not, an error is thrown.\n
+     * @param {int|int[]} tokenTypes Either a single token type or an array of\n
+     *      token types that the next token should be. If an array is passed,\n
+     *      it\'s assumed that the token must be one of these.\n
+     * @param {variant} channel (Optional) The channel to read from. If not\n
+     *      provided, reads from the default (unnamed) channel.\n
+     * @return {void}\n
+     * @method mustMatch\n
+     */\n
+    mustMatch: function(tokenTypes, channel){\n
+\n
+        var token;\n
+\n
+        //always convert to an array, makes things easier\n
+        if (!(tokenTypes instanceof Array)){\n
+            tokenTypes = [tokenTypes];\n
+        }\n
+\n
+        if (!this.match.apply(this, arguments)){\n
+            token = this.LT(1);\n
+            throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name +\n
+                " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);\n
+        }\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Consuming methods\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Keeps reading from the token stream until either one of the specified\n
+     * token types is found or until the end of the input is reached.\n
+     * @param {int|int[]} tokenTypes Either a single token type or an array of\n
+     *      token types that the next token should be. If an array is passed,\n
+     *      it\'s assumed that the token must be one of these.\n
+     * @param {variant} channel (Optional) The channel to read from. If not\n
+     *      provided, reads from the default (unnamed) channel.\n
+     * @return {void}\n
+     * @method advance\n
+     */\n
+    advance: function(tokenTypes, channel){\n
+\n
+        while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){\n
+            this.get();\n
+        }\n
+\n
+        return this.LA(0);\n
+    },\n
+\n
+    /**\n
+     * Consumes the next token from the token stream.\n
+     * @return {int} The token type of the token that was just consumed.\n
+     * @method get\n
+     */\n
+    get: function(channel){\n
+\n
+        var tokenInfo   = this._tokenData,\n
+            reader      = this._reader,\n
+            value,\n
+            i           =0,\n
+            len         = tokenInfo.length,\n
+            found       = false,\n
+            token,\n
+            info;\n
+\n
+        //check the lookahead buffer first\n
+        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){\n
+\n
+            i++;\n
+            this._token = this._lt[this._ltIndex++];\n
+            info = tokenInfo[this._token.type];\n
+\n
+            //obey channels logic\n
+            while((info.channel !== undefined && channel !== info.channel) &&\n
+                    this._ltIndex < this._lt.length){\n
+                this._token = this._lt[this._ltIndex++];\n
+                info = tokenInfo[this._token.type];\n
+                i++;\n
+            }\n
+\n
+            //here be dragons\n
+            if ((info.channel === undefined || channel === info.channel) &&\n
+                    this._ltIndex <= this._lt.length){\n
+                this._ltIndexCache.push(i);\n
+                return this._token.type;\n
+            }\n
+        }\n
+\n
+        //call token retriever method\n
+        token = this._getToken();\n
+\n
+        //if it should be hidden, don\'t save a token\n
+        if (token.type > -1 && !tokenInfo[token.type].hide){\n
+\n
+            //apply token channel\n
+            token.channel = tokenInfo[token.type].channel;\n
+\n
+            //save for later\n
+            this._token = token;\n
+            this._lt.push(token);\n
+\n
+            //save space that will be moved (must be done before array is truncated)\n
+            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);\n
+\n
+            //keep the buffer under 5 items\n
+            if (this._lt.length > 5){\n
+                this._lt.shift();\n
+            }\n
+\n
+            //also keep the shift buffer under 5 items\n
+            if (this._ltIndexCache.length > 5){\n
+                this._ltIndexCache.shift();\n
+            }\n
+\n
+            //update lookahead index\n
+            this._ltIndex = this._lt.length;\n
+        }\n
+\n
+        /*\n
+         * Skip to the next token if:\n
+         * 1. The token type is marked as hidden.\n
+         * 2. The token type has a channel specified and it isn\'t the current channel.\n
+         */\n
+        info = tokenInfo[token.type];\n
+        if (info &&\n
+                (info.hide ||\n
+                (info.channel !== undefined && channel !== info.channel))){\n
+            return this.get(channel);\n
+        } else {\n
+            //return just the type\n
+            return token.type;\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Looks ahead a certain number of tokens and returns the token type at\n
+     * that position. This will throw an error if you lookahead past the\n
+     * end of input, past the size of the lookahead buffer, or back past\n
+     * the first token in the lookahead buffer.\n
+     * @param {int} The index of the token type to retrieve. 0 for the\n
+     *      current token, 1 for the next, -1 for the previous, etc.\n
+     * @return {int} The token type of the token in the given position.\n
+     * @method LA\n
+     */\n
+    LA: function(index){\n
+        var total = index,\n
+            tt;\n
+        if (index > 0){\n
+            //TODO: Store 5 somewhere\n
+            if (index > 5){\n
+                throw new Error("Too much lookahead.");\n
+            }\n
+\n
+            //get all those tokens\n
+            while(total){\n
+                tt = this.get();\n
+                total--;\n
+            }\n
+\n
+            //unget all those tokens\n
+            while(total < index){\n
+                this.unget();\n
+                total++;\n
+            }\n
+        } else if (index < 0){\n
+\n
+            if(this._lt[this._ltIndex+index]){\n
+                tt = this._lt[this._ltIndex+index].type;\n
+            } else {\n
+                throw new Error("Too much lookbehind.");\n
+            }\n
+\n
+        } else {\n
+            tt = this._token.type;\n
+        }\n
+\n
+        return tt;\n
+\n
+    },\n
+\n
+    /**\n
+     * Looks ahead a certain number of tokens and returns the token at\n
+     * that position. This will throw an error if you lookahead past the\n
+     * end of input, past the size of the lookahead buffer, or back past\n
+     * the first token in the lookahead buffer.\n
+     * @param {int} The index of the token type to retrieve. 0 for the\n
+     *      current token, 1 for the next, -1 for the previous, etc.\n
+     * @return {Object} The token of the token in the given position.\n
+     * @method LA\n
+     */\n
+    LT: function(index){\n
+\n
+        //lookahead first to prime the token buffer\n
+        this.LA(index);\n
+\n
+        //now find the token, subtract one because _ltIndex is already at the next index\n
+        return this._lt[this._ltIndex+index-1];\n
+    },\n
+\n
+    /**\n
+     * Returns the token type for the next token in the stream without\n
+     * consuming it.\n
+     * @return {int} The token type of the next token in the stream.\n
+     * @method peek\n
+     */\n
+    peek: function(){\n
+        return this.LA(1);\n
+    },\n
+\n
+    /**\n
+     * Returns the actual token object for the last consumed token.\n
+     * @return {Token} The token object for the last consumed token.\n
+     * @method token\n
+     */\n
+    token: function(){\n
+        return this._token;\n
+    },\n
+\n
+    /**\n
+     * Returns the name of the token for the given token type.\n
+     * @param {int} tokenType The type of token to get the name of.\n
+     * @return {String} The name of the token or "UNKNOWN_TOKEN" for any\n
+     *      invalid token type.\n
+     * @method tokenName\n
+     */\n
+    tokenName: function(tokenType){\n
+        if (tokenType < 0 || tokenType > this._tokenData.length){\n
+            return "UNKNOWN_TOKEN";\n
+        } else {\n
+            return this._tokenData[tokenType].name;\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Returns the token type value for the given token name.\n
+     * @param {String} tokenName The name of the token whose value should be returned.\n
+     * @return {int} The token type value for the given token name or -1\n
+     *      for an unknown token.\n
+     * @method tokenName\n
+     */\n
+    tokenType: function(tokenName){\n
+        return this._tokenData[tokenName] || -1;\n
+    },\n
+\n
+    /**\n
+     * Returns the last consumed token to the token stream.\n
+     * @method unget\n
+     */\n
+    unget: function(){\n
+        //if (this._ltIndex > -1){\n
+        if (this._ltIndexCache.length){\n
+            this._ltIndex -= this._ltIndexCache.pop();//--;\n
+            this._token = this._lt[this._ltIndex - 1];\n
+        } else {\n
+            throw new Error("Too much lookahead.");\n
+        }\n
+    }\n
+\n
+};\n
+\n
+\n
+\n
+\n
+parserlib.util = {\n
+StringReader: StringReader,\n
+SyntaxError : SyntaxError,\n
+SyntaxUnit  : SyntaxUnit,\n
+EventTarget : EventTarget,\n
+TokenStreamBase : TokenStreamBase\n
+};\n
+})();\n
+\n
+\n
+/*\n
+Parser-Lib\n
+Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n
+\n
+Permission is hereby granted, free of charge, to any person obtaining a copy\n
+of this software and associated documentation files (the "Software"), to deal\n
+in the Software without restriction, including without limitation the rights\n
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n
+copies of the Software, and to permit persons to whom the Software is\n
+furnished to do so, subject to the following conditions:\n
+\n
+The above copyright notice and this permission notice shall be included in\n
+all copies or substantial portions of the Software.\n
+\n
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n
+THE SOFTWARE.\n
+\n
+*/\n
+/* Version v0.2.3, Build time: 19-June-2013 11:16:15 */\n
+(function(){\n
+var EventTarget = parserlib.util.EventTarget,\n
+TokenStreamBase = parserlib.util.TokenStreamBase,\n
+StringReader = parserlib.util.StringReader,\n
+SyntaxError = parserlib.util.SyntaxError,\n
+SyntaxUnit  = parserlib.util.SyntaxUnit;\n
+\n
+\n
+var Colors = {\n
+    aliceblue       :"#f0f8ff",\n
+    antiquewhite    :"#faebd7",\n
+    aqua            :"#00ffff",\n
+    aquamarine      :"#7fffd4",\n
+    azure           :"#f0ffff",\n
+    beige           :"#f5f5dc",\n
+    bisque          :"#ffe4c4",\n
+    black           :"#000000",\n
+    blanchedalmond  :"#ffebcd",\n
+    blue            :"#0000ff",\n
+    blueviolet      :"#8a2be2",\n
+    brown           :"#a52a2a",\n
+    burlywood       :"#deb887",\n
+    cadetblue       :"#5f9ea0",\n
+    chartreuse      :"#7fff00",\n
+    chocolate       :"#d2691e",\n
+    coral           :"#ff7f50",\n
+    cornflowerblue  :"#6495ed",\n
+    cornsilk        :"#fff8dc",\n
+    crimson         :"#dc143c",\n
+    cyan            :"#00ffff",\n
+    darkblue        :"#00008b",\n
+    darkcyan        :"#008b8b",\n
+    darkgoldenrod   :"#b8860b",\n
+    darkgray        :"#a9a9a9",\n
+    darkgreen       :"#006400",\n
+    darkkhaki       :"#bdb76b",\n
+    darkmagenta     :"#8b008b",\n
+    darkolivegreen  :"#556b2f",\n
+    darkorange      :"#ff8c00",\n
+    darkorchid      :"#9932cc",\n
+    darkred         :"#8b0000",\n
+    darksalmon      :"#e9967a",\n
+    darkseagreen    :"#8fbc8f",\n
+    darkslateblue   :"#483d8b",\n
+    darkslategray   :"#2f4f4f",\n
+    darkturquoise   :"#00ced1",\n
+    darkviolet      :"#9400d3",\n
+    deeppink        :"#ff1493",\n
+    deepskyblue     :"#00bfff",\n
+    dimgray         :"#696969",\n
+    dodgerblue      :"#1e90ff",\n
+    firebrick       :"#b22222",\n
+    floralwhite     :"#fffaf0",\n
+    forestgreen     :"#228b22",\n
+    fuchsia         :"#ff00ff",\n
+    gainsboro       :"#dcdcdc",\n
+    ghostwhite      :"#f8f8ff",\n
+    gold            :"#ffd700",\n
+    goldenrod       :"#daa520",\n
+    gray            :"#808080",\n
+    green           :"#008000",\n
+    greenyellow     :"#adff2f",\n
+    honeydew        :"#f0fff0",\n
+    hotpink         :"#ff69b4",\n
+    indianred       :"#cd5c5c",\n
+    indigo          :"#4b0082",\n
+    ivory           :"#fffff0",\n
+    khaki           :"#f0e68c",\n
+    lavender        :"#e6e6fa",\n
+    lavenderblush   :"#fff0f5",\n
+    lawngreen       :"#7cfc00",\n
+    lemonchiffon    :"#fffacd",\n
+    lightblue       :"#add8e6",\n
+    lightcoral      :"#f08080",\n
+    lightcyan       :"#e0ffff",\n
+    lightgoldenrodyellow  :"#fafad2",\n
+    lightgray       :"#d3d3d3",\n
+    lightgreen      :"#90ee90",\n
+    lightpink       :"#ffb6c1",\n
+    lightsalmon     :"#ffa07a",\n
+    lightseagreen   :"#20b2aa",\n
+    lightskyblue    :"#87cefa",\n
+    lightslategray  :"#778899",\n
+    lightsteelblue  :"#b0c4de",\n
+    lightyellow     :"#ffffe0",\n
+    lime            :"#00ff00",\n
+    limegreen       :"#32cd32",\n
+    linen           :"#faf0e6",\n
+    magenta         :"#ff00ff",\n
+    maroon          :"#800000",\n
+    mediumaquamarine:"#66cdaa",\n
+    mediumblue      :"#0000cd",\n
+    mediumorchid    :"#ba55d3",\n
+    mediumpurple    :"#9370d8",\n
+    mediumseagreen  :"#3cb371",\n
+    mediumslateblue :"#7b68ee",\n
+    mediumspringgreen   :"#00fa9a",\n
+    mediumturquoise :"#48d1cc",\n
+    mediumvioletred :"#c71585",\n
+    midnightblue    :"#191970",\n
+    mintcream       :"#f5fffa",\n
+    mistyrose       :"#ffe4e1",\n
+    moccasin        :"#ffe4b5",\n
+    navajowhite     :"#ffdead",\n
+    navy            :"#000080",\n
+    oldlace         :"#fdf5e6",\n
+    olive           :"#808000",\n
+    olivedrab       :"#6b8e23",\n
+    orange          :"#ffa500",\n
+    orangered       :"#ff4500",\n
+    orchid          :"#da70d6",\n
+    palegoldenrod   :"#eee8aa",\n
+    palegreen       :"#98fb98",\n
+    paleturquoise   :"#afeeee",\n
+    palevioletred   :"#d87093",\n
+    papayawhip      :"#ffefd5",\n
+    peachpuff       :"#ffdab9",\n
+    peru            :"#cd853f",\n
+    pink            :"#ffc0cb",\n
+    plum            :"#dda0dd",\n
+    powderblue      :"#b0e0e6",\n
+    purple          :"#800080",\n
+    red             :"#ff0000",\n
+    rosybrown       :"#bc8f8f",\n
+    royalblue       :"#4169e1",\n
+    saddlebrown     :"#8b4513",\n
+    salmon          :"#fa8072",\n
+    sandybrown      :"#f4a460",\n
+    seagreen        :"#2e8b57",\n
+    seashell        :"#fff5ee",\n
+    sienna          :"#a0522d",\n
+    silver          :"#c0c0c0",\n
+    skyblue         :"#87ceeb",\n
+    slateblue       :"#6a5acd",\n
+    slategray       :"#708090",\n
+    snow            :"#fffafa",\n
+    springgreen     :"#00ff7f",\n
+    steelblue       :"#4682b4",\n
+    tan             :"#d2b48c",\n
+    teal            :"#008080",\n
+    thistle         :"#d8bfd8",\n
+    tomato          :"#ff6347",\n
+    turquoise       :"#40e0d0",\n
+    violet          :"#ee82ee",\n
+    wheat           :"#f5deb3",\n
+    white           :"#ffffff",\n
+    whitesmoke      :"#f5f5f5",\n
+    yellow          :"#ffff00",\n
+    yellowgreen     :"#9acd32",\n
+    //CSS2 system colors http://www.w3.org/TR/css3-color/#css2-system\n
+    activeBorder        :"Active window border.",\n
+    activecaption       :"Active window caption.",\n
+    appworkspace        :"Background color of multiple document interface.",\n
+    background          :"Desktop background.",\n
+    buttonface          :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.",\n
+    buttonhighlight     :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",\n
+    buttonshadow        :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",\n
+    buttontext          :"Text on push buttons.",\n
+    captiontext         :"Text in caption, size box, and scrollbar arrow box.",\n
+    graytext            :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.",\n
+    highlight           :"Item(s) selected in a control.",\n
+    highlighttext       :"Text of item(s) selected in a control.",\n
+    inactiveborder      :"Inactive window border.",\n
+    inactivecaption     :"Inactive window caption.",\n
+    inactivecaptiontext :"Color of text in an inactive caption.",\n
+    infobackground      :"Background color for tooltip controls.",\n
+    infotext            :"Text color for tooltip controls.",\n
+    menu                :"Menu background.",\n
+    menutext            :"Text in menus.",\n
+    scrollbar           :"Scroll bar gray area.",\n
+    threeddarkshadow    :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",\n
+    threedface          :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",\n
+    threedhighlight     :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",\n
+    threedlightshadow   :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",\n
+    threedshadow        :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",\n
+    window              :"Window background.",\n
+    windowframe         :"Window frame.",\n
+    windowtext          :"Text in windows."\n
+};\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a selector combinator (whitespace, +, >).\n
+ * @namespace parserlib.css\n
+ * @class Combinator\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {String} text The text representation of the unit.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function Combinator(text, line, col){\n
+\n
+    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);\n
+\n
+    /**\n
+     * The type of modifier.\n
+     * @type String\n
+     * @property type\n
+     */\n
+    this.type = "unknown";\n
+\n
+    //pretty simple\n
+    if (/^\\s+$/.test(text)){\n
+        this.type = "descendant";\n
+    } else if (text == ">"){\n
+        this.type = "child";\n
+    } else if (text == "+"){\n
+        this.type = "adjacent-sibling";\n
+    } else if (text == "~"){\n
+        this.type = "sibling";\n
+    }\n
+\n
+}\n
+\n
+Combinator.prototype = new SyntaxUnit();\n
+Combinator.prototype.constructor = Combinator;\n
+\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a media feature, such as max-width:500.\n
+ * @namespace parserlib.css\n
+ * @class MediaFeature\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {SyntaxUnit} name The name of the feature.\n
+ * @param {SyntaxUnit} value The value of the feature or null if none.\n
+ */\n
+function MediaFeature(name, value){\n
+\n
+    SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);\n
+\n
+    /**\n
+     * The name of the media feature\n
+     * @type String\n
+     * @property name\n
+     */\n
+    this.name = name;\n
+\n
+    /**\n
+     * The value for the feature or null if there is none.\n
+     * @type SyntaxUnit\n
+     * @property value\n
+     */\n
+    this.value = value;\n
+}\n
+\n
+MediaFeature.prototype = new SyntaxUnit();\n
+MediaFeature.prototype.constructor = MediaFeature;\n
+\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents an individual media query.\n
+ * @namespace parserlib.css\n
+ * @class MediaQuery\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {String} modifier The modifier "not" or "only" (or null).\n
+ * @param {String} mediaType The type of media (i.e., "print").\n
+ * @param {Array} parts Array of selectors parts making up this selector.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function MediaQuery(modifier, mediaType, features, line, col){\n
+\n
+    SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE);\n
+\n
+    /**\n
+     * The media modifier ("not" or "only")\n
+     * @type String\n
+     * @property modifier\n
+     */\n
+    this.modifier = modifier;\n
+\n
+    /**\n
+     * The mediaType (i.e., "print")\n
+     * @type String\n
+     * @property mediaType\n
+     */\n
+    this.mediaType = mediaType;\n
+\n
+    /**\n
+     * The parts that make up the selector.\n
+     * @type Array\n
+     * @property features\n
+     */\n
+    this.features = features;\n
+\n
+}\n
+\n
+MediaQuery.prototype = new SyntaxUnit();\n
+MediaQuery.prototype.constructor = MediaQuery;\n
+\n
+\n
+/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit,\n
+    PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector,\n
+    PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */\n
+\n
+/**\n
+ * A CSS3 parser.\n
+ * @namespace parserlib.css\n
+ * @class Parser\n
+ * @constructor\n
+ * @param {Object} options (Optional) Various options for the parser:\n
+ *      starHack (true|false) to allow IE6 star hack as valid,\n
+ *      underscoreHack (true|false) to interpret leading underscores\n
+ *      as IE6-7 targeting for known properties, ieFilters (true|false)\n
+ *      to indicate that IE < 8 filters should be accepted and not throw\n
+ *      syntax errors.\n
+ */\n
+function Parser(options){\n
+\n
+    //inherit event functionality\n
+    EventTarget.call(this);\n
+\n
+\n
+    this.options = options || {};\n
+\n
+    this._tokenStream = null;\n
+}\n
+\n
+//Static constants\n
+Parser.DEFAULT_TYPE = 0;\n
+Parser.COMBINATOR_TYPE = 1;\n
+Parser.MEDIA_FEATURE_TYPE = 2;\n
+Parser.MEDIA_QUERY_TYPE = 3;\n
+Parser.PROPERTY_NAME_TYPE = 4;\n
+Parser.PROPERTY_VALUE_TYPE = 5;\n
+Parser.PROPERTY_VALUE_PART_TYPE = 6;\n
+Parser.SELECTOR_TYPE = 7;\n
+Parser.SELECTOR_PART_TYPE = 8;\n
+Parser.SELECTOR_SUB_PART_TYPE = 9;\n
+\n
+Parser.prototype = function(){\n
+\n
+    var proto = new EventTarget(),  //new prototype\n
+        prop,\n
+        additions =  {\n
+\n
+            //restore constructor\n
+            constructor: Parser,\n
+\n
+            //instance constants - yuck\n
+            DEFAULT_TYPE : 0,\n
+            COMBINATOR_TYPE : 1,\n
+            MEDIA_FEATURE_TYPE : 2,\n
+            MEDIA_QUERY_TYPE : 3,\n
+            PROPERTY_NAME_TYPE : 4,\n
+            PROPERTY_VALUE_TYPE : 5,\n
+            PROPERTY_VALUE_PART_TYPE : 6,\n
+            SELECTOR_TYPE : 7,\n
+            SELECTOR_PART_TYPE : 8,\n
+            SELECTOR_SUB_PART_TYPE : 9,\n
+\n
+            //-----------------------------------------------------------------\n
+            // Grammar\n
+            //-----------------------------------------------------------------\n
+\n
+            _stylesheet: function(){\n
+\n
+                /*\n
+                 * stylesheet\n
+                 *  : [ CHARSET_SYM S* STRING S* \';\' ]?\n
+                 *    [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*\n
+                 *    [ namespace [S|CDO|CDC]* ]*\n
+                 *    [ [ ruleset | media | page | font_face | keyframes ] [S|CDO|CDC]* ]*\n
+                 *  ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    charset     = null,\n
+                    count,\n
+                    token,\n
+                    tt;\n
+\n
+                this.fire("startstylesheet");\n
+\n
+                //try to read character set\n
+                this._charset();\n
+\n
+                this._skipCruft();\n
+\n
+                //try to read imports - may be more than one\n
+                while (tokenStream.peek() == Tokens.IMPORT_SYM){\n
+                    this._import();\n
+                    this._skipCruft();\n
+                }\n
+\n
+                //try to read namespaces - may be more than one\n
+                while (tokenStream.peek() == Tokens.NAMESPACE_SYM){\n
+                    this._namespace();\n
+                    this._skipCruft();\n
+                }\n
+\n
+                //get the next token\n
+                tt = tokenStream.peek();\n
+\n
+                //try to read the rest\n
+                while(tt > Tokens.EOF){\n
+\n
+                    try {\n
+\n
+                        switch(tt){\n
+                            case Tokens.MEDIA_SYM:\n
+                                this._media();\n
+                                this._skipCruft();\n
+                                break;\n
+                            case Tokens.PAGE_SYM:\n
+                                this._page();\n
+                                this._skipCruft();\n
+                                break;\n
+                            case Tokens.FONT_FACE_SYM:\n
+                                this._font_face();\n
+                                this._skipCruft();\n
+                                break;\n
+                            case Tokens.KEYFRAMES_SYM:\n
+                                this._keyframes();\n
+                                this._skipCruft();\n
+                                break;\n
+                            case Tokens.VIEWPORT_SYM:\n
+                                this._viewport();\n
+                                this._skipCruft();\n
+                                break;\n
+                            case Tokens.UNKNOWN_SYM:  //unknown @ rule\n
+                                tokenStream.get();\n
+                                if (!this.options.strict){\n
+\n
+                                    //fire error event\n
+                                    this.fire({\n
+                                        type:       "error",\n
+                                        error:      null,\n
+                                        message:    "Unknown @ rule: " + tokenStream.LT(0).value + ".",\n
+                                        line:       tokenStream.LT(0).startLine,\n
+                                        col:        tokenStream.LT(0).startCol\n
+                                    });\n
+\n
+                                    //skip braces\n
+                                    count=0;\n
+                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){\n
+                                        count++;    //keep track of nesting depth\n
+                                    }\n
+\n
+                                    while(count){\n
+                                        tokenStream.advance([Tokens.RBRACE]);\n
+                                        count--;\n
+                                    }\n
+\n
+                                } else {\n
+                                    //not a syntax error, rethrow it\n
+                                    throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);\n
+                                }\n
+                                break;\n
+                            case Tokens.S:\n
+                                this._readWhitespace();\n
+                                break;\n
+                            default:\n
+                                if(!this._ruleset()){\n
+\n
+                                    //error handling for known issues\n
+                                    switch(tt){\n
+                                        case Tokens.CHARSET_SYM:\n
+                                            token = tokenStream.LT(1);\n
+                                            this._charset(false);\n
+                                            throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol);\n
+                                        case Tokens.IMPORT_SYM:\n
+                                            token = tokenStream.LT(1);\n
+                                            this._import(false);\n
+                                            throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol);\n
+                                        case Tokens.NAMESPACE_SYM:\n
+                                            token = tokenStream.LT(1);\n
+                                            this._namespace(false);\n
+                                            throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol);\n
+                                        default:\n
+                                            tokenStream.get();  //get the last token\n
+                                            this._unexpectedToken(tokenStream.token());\n
+                                    }\n
+\n
+                                }\n
+                        }\n
+                    } catch(ex) {\n
+                        if (ex instanceof SyntaxError && !this.options.strict){\n
+                            this.fire({\n
+                                type:       "error",\n
+                                error:      ex,\n
+                                message:    ex.message,\n
+                                line:       ex.line,\n
+                                col:        ex.col\n
+                            });\n
+                        } else {\n
+                            throw ex;\n
+                        }\n
+                    }\n
+\n
+                    tt = tokenStream.peek();\n
+                }\n
+\n
+                if (tt != Tokens.EOF){\n
+                    this._unexpectedToken(tokenStream.token());\n
+                }\n
+\n
+                this.fire("endstylesheet");\n
+            },\n
+\n
+            _charset: function(emit){\n
+                var tokenStream = this._tokenStream,\n
+                    charset,\n
+                    token,\n
+                    line,\n
+                    col;\n
+\n
+                if (tokenStream.match(Tokens.CHARSET_SYM)){\n
+                    line = tokenStream.token().startLine;\n
+                    col = tokenStream.token().startCol;\n
+\n
+                    this._readWhitespace();\n
+                    tokenStream.mustMatch(Tokens.STRING);\n
+\n
+                    token = tokenStream.token();\n
+                    charset = token.value;\n
+\n
+                    this._readWhitespace();\n
+                    tokenStream.mustMatch(Tokens.SEMICOLON);\n
+\n
+                    if (emit !== false){\n
+                        this.fire({\n
+                            type:   "charset",\n
+                            charset:charset,\n
+                            line:   line,\n
+                            col:    col\n
+                        });\n
+                    }\n
+                }\n
+            },\n
+\n
+            _import: function(emit){\n
+                /*\n
+                 * import\n
+                 *   : IMPORT_SYM S*\n
+                 *    [STRING|URI] S* media_query_list? \';\' S*\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    tt,\n
+                    uri,\n
+                    importToken,\n
+                    mediaList   = [];\n
+\n
+                //read import symbol\n
+                tokenStream.mustMatch(Tokens.IMPORT_SYM);\n
+                importToken = tokenStream.token();\n
+                this._readWhitespace();\n
+\n
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n
+\n
+                //grab the URI value\n
+                uri = tokenStream.token().value.replace(/(?:url\\()?["\']([^"\']+)["\']\\)?/, "$1");\n
+\n
+                this._readWhitespace();\n
+\n
+                mediaList = this._media_query_list();\n
+\n
+                //must end with a semicolon\n
+                tokenStream.mustMatch(Tokens.SEMICOLON);\n
+                this._readWhitespace();\n
+\n
+                if (emit !== false){\n
+                    this.fire({\n
+                        type:   "import",\n
+                        uri:    uri,\n
+                        media:  mediaList,\n
+                        line:   importToken.startLine,\n
+                        col:    importToken.startCol\n
+                    });\n
+                }\n
+\n
+            },\n
+\n
+            _namespace: function(emit){\n
+                /*\n
+                 * namespace\n
+                 *   : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* \';\' S*\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col,\n
+                    prefix,\n
+                    uri;\n
+\n
+                //read import symbol\n
+                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);\n
+                line = tokenStream.token().startLine;\n
+                col = tokenStream.token().startCol;\n
+                this._readWhitespace();\n
+\n
+                //it\'s a namespace prefix - no _namespace_prefix() method because it\'s just an IDENT\n
+                if (tokenStream.match(Tokens.IDENT)){\n
+                    prefix = tokenStream.token().value;\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n
+                /*if (!tokenStream.match(Tokens.STRING)){\n
+                    tokenStream.mustMatch(Tokens.URI);\n
+                }*/\n
+\n
+                //grab the URI value\n
+                uri = tokenStream.token().value.replace(/(?:url\\()?["\']([^"\']+)["\']\\)?/, "$1");\n
+\n
+                this._readWhitespace();\n
+\n
+                //must end with a semicolon\n
+                tokenStream.mustMatch(Tokens.SEMICOLON);\n
+                this._readWhitespace();\n
+\n
+                if (emit !== false){\n
+                    this.fire({\n
+                        type:   "namespace",\n
+                        prefix: prefix,\n
+                        uri:    uri,\n
+                        line:   line,\n
+                        col:    col\n
+                    });\n
+                }\n
+\n
+            },\n
+\n
+            _media: function(){\n
+                /*\n
+                 * media\n
+                 *   : MEDIA_SYM S* media_query_list S* \'{\' S* ruleset* \'}\' S*\n
+                 *   ;\n
+                 */\n
+                var tokenStream     = this._tokenStream,\n
+                    line,\n
+                    col,\n
+                    mediaList;//       = [];\n
+\n
+                //look for @media\n
+                tokenStream.mustMatch(Tokens.MEDIA_SYM);\n
+                line = tokenStream.token().startLine;\n
+                col = tokenStream.token().startCol;\n
+\n
+                this._readWhitespace();\n
+\n
+                mediaList = this._media_query_list();\n
+\n
+                tokenStream.mustMatch(Tokens.LBRACE);\n
+                this._readWhitespace();\n
+\n
+                this.fire({\n
+                    type:   "startmedia",\n
+                    media:  mediaList,\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+\n
+                while(true) {\n
+                    if (tokenStream.peek() == Tokens.PAGE_SYM){\n
+                        this._page();\n
+                    } else   if (tokenStream.peek() == Tokens.FONT_FACE_SYM){\n
+                        this._font_face();\n
+                    } else if (!this._ruleset()){\n
+                        break;\n
+                    }\n
+                }\n
+\n
+                tokenStream.mustMatch(Tokens.RBRACE);\n
+                this._readWhitespace();\n
+\n
+                this.fire({\n
+                    type:   "endmedia",\n
+                    media:  mediaList,\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+            },\n
+\n
+\n
+            //CSS3 Media Queries\n
+            _media_query_list: function(){\n
+                /*\n
+                 * media_query_list\n
+                 *   : S* [media_query [ \',\' S* media_query ]* ]?\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    mediaList   = [];\n
+\n
+\n
+                this._readWhitespace();\n
+\n
+                if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){\n
+                    mediaList.push(this._media_query());\n
+                }\n
+\n
+                while(tokenStream.match(Tokens.COMMA)){\n
+                    this._readWhitespace();\n
+                    mediaList.push(this._media_query());\n
+                }\n
+\n
+                return mediaList;\n
+            },\n
+\n
+            /*\n
+             * Note: "expression" in the grammar maps to the _media_expression\n
+             * method.\n
+\n
+             */\n
+            _media_query: function(){\n
+                /*\n
+                 * media_query\n
+                 *   : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*\n
+                 *   | expression [ AND S* expression ]*\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    type        = null,\n
+                    ident       = null,\n
+                    token       = null,\n
+                    expressions = [];\n
+\n
+                if (tokenStream.match(Tokens.IDENT)){\n
+                    ident = tokenStream.token().value.toLowerCase();\n
+\n
+                    //since there\'s no custom tokens for these, need to manually check\n
+                    if (ident != "only" && ident != "not"){\n
+                        tokenStream.unget();\n
+                        ident = null;\n
+                    } else {\n
+                        token = tokenStream.token();\n
+                    }\n
+                }\n
+\n
+                this._readWhitespace();\n
+\n
+                if (tokenStream.peek() == Tokens.IDENT){\n
+                    type = this._media_type();\n
+                    if (token === null){\n
+                        token = tokenStream.token();\n
+                    }\n
+                } else if (tokenStream.peek() == Tokens.LPAREN){\n
+                    if (token === null){\n
+                        token = tokenStream.LT(1);\n
+                    }\n
+                    expressions.push(this._media_expression());\n
+                }\n
+\n
+                if (type === null && expressions.length === 0){\n
+                    return null;\n
+                } else {\n
+                    this._readWhitespace();\n
+                    while (tokenStream.match(Tokens.IDENT)){\n
+                        if (tokenStream.token().value.toLowerCase() != "and"){\n
+                            this._unexpectedToken(tokenStream.token());\n
+                        }\n
+\n
+                        this._readWhitespace();\n
+                        expressions.push(this._media_expression());\n
+                    }\n
+                }\n
+\n
+                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);\n
+            },\n
+\n
+            //CSS3 Media Queries\n
+            _media_type: function(){\n
+                /*\n
+                 * media_type\n
+                 *   : IDENT\n
+                 *   ;\n
+                 */\n
+                return this._media_feature();\n
+            },\n
+\n
+            /**\n
+             * Note: in CSS3 Media Queries, this is called "expression".\n
+             * Renamed here to avoid conflict with CSS3 Selectors\n
+             * definition of "expression". Also note that "expr" in the\n
+             * grammar now maps to "expression" from CSS3 selectors.\n
+             * @method _media_expression\n
+             * @private\n
+             */\n
+            _media_expression: function(){\n
+                /*\n
+                 * expression\n
+                 *  : \'(\' S* media_feature S* [ \':\' S* expr ]? \')\' S*\n
+                 *  ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    feature     = null,\n
+                    token,\n
+                    expression  = null;\n
+\n
+                tokenStream.mustMatch(Tokens.LPAREN);\n
+\n
+                feature = this._media_feature();\n
+                this._readWhitespace();\n
+\n
+                if (tokenStream.match(Tokens.COLON)){\n
+                    this._readWhitespace();\n
+                    token = tokenStream.LT(1);\n
+                    expression = this._expression();\n
+                }\n
+\n
+                tokenStream.mustMatch(Tokens.RPAREN);\n
+                this._readWhitespace();\n
+\n
+                return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null));\n
+            },\n
+\n
+            //CSS3 Media Queries\n
+            _media_feature: function(){\n
+                /*\n
+                 * media_feature\n
+                 *   : IDENT\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream;\n
+\n
+                tokenStream.mustMatch(Tokens.IDENT);\n
+\n
+                return SyntaxUnit.fromToken(tokenStream.token());\n
+            },\n
+\n
+            //CSS3 Paged Media\n
+            _page: function(){\n
+                /*\n
+                 * page:\n
+                 *    PAGE_SYM S* IDENT? pseudo_page? S*\n
+                 *    \'{\' S* [ declaration | margin ]? [ \';\' S* [ declaration | margin ]? ]* \'}\' S*\n
+                 *    ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col,\n
+                    identifier  = null,\n
+                    pseudoPage  = null;\n
+\n
+                //look for @page\n
+                tokenStream.mustMatch(Tokens.PAGE_SYM);\n
+                line = tokenStream.token().startLine;\n
+                col = tokenStream.token().startCol;\n
+\n
+                this._readWhitespace();\n
+\n
+                if (tokenStream.match(Tokens.IDENT)){\n
+                    identifier = tokenStream.token().value;\n
+\n
+                    //The value \'auto\' may not be used as a page name and MUST be treated as a syntax error.\n
+                    if (identifier.toLowerCase() === "auto"){\n
+                        this._unexpectedToken(tokenStream.token());\n
+                    }\n
+                }\n
+\n
+                //see if there\'s a colon upcoming\n
+                if (tokenStream.peek() == Tokens.COLON){\n
+                    pseudoPage = this._pseudo_page();\n
+                }\n
+\n
+                this._readWhitespace();\n
+\n
+                this.fire({\n
+                    type:   "startpage",\n
+                    id:     identifier,\n
+                    pseudo: pseudoPage,\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+\n
+                this._readDeclarations(true, true);\n
+\n
+                this.fire({\n
+                    type:   "endpage",\n
+                    id:     identifier,\n
+                    pseudo: pseudoPage,\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+\n
+            },\n
+\n
+            //CSS3 Paged Media\n
+            _margin: function(){\n
+                /*\n
+                 * margin :\n
+                 *    margin_sym S* \'{\' declaration [ \';\' S* declaration? ]* \'}\' S*\n
+                 *    ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col,\n
+                    marginSym   = this._margin_sym();\n
+\n
+                if (marginSym){\n
+                    line = tokenStream.token().startLine;\n
+                    col = tokenStream.token().startCol;\n
+\n
+                    this.fire({\n
+                        type: "startpagemargin",\n
+                        margin: marginSym,\n
+                        line:   line,\n
+                        col:    col\n
+                    });\n
+\n
+                    this._readDeclarations(true);\n
+\n
+                    this.fire({\n
+                        type: "endpagemargin",\n
+                        margin: marginSym,\n
+                        line:   line,\n
+                        col:    col\n
+                    });\n
+                    return true;\n
+                } else {\n
+                    return false;\n
+                }\n
+            },\n
+\n
+            //CSS3 Paged Media\n
+            _margin_sym: function(){\n
+\n
+                /*\n
+                 * margin_sym :\n
+                 *    TOPLEFTCORNER_SYM |\n
+                 *    TOPLEFT_SYM |\n
+                 *    TOPCENTER_SYM |\n
+                 *    TOPRIGHT_SYM |\n
+                 *    TOPRIGHTCORNER_SYM |\n
+                 *    BOTTOMLEFTCORNER_SYM |\n
+                 *    BOTTOMLEFT_SYM |\n
+                 *    BOTTOMCENTER_SYM |\n
+                 *    BOTTOMRIGHT_SYM |\n
+                 *    BOTTOMRIGHTCORNER_SYM |\n
+                 *    LEFTTOP_SYM |\n
+                 *    LEFTMIDDLE_SYM |\n
+                 *    LEFTBOTTOM_SYM |\n
+                 *    RIGHTTOP_SYM |\n
+                 *    RIGHTMIDDLE_SYM |\n
+                 *    RIGHTBOTTOM_SYM\n
+                 *    ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream;\n
+\n
+                if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM,\n
+                        Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM,\n
+                        Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM,\n
+                        Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM,\n
+                        Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM,\n
+                        Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM,\n
+                        Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM]))\n
+                {\n
+                    return SyntaxUnit.fromToken(tokenStream.token());\n
+                } else {\n
+                    return null;\n
+                }\n
+\n
+            },\n
+\n
+            _pseudo_page: function(){\n
+                /*\n
+                 * pseudo_page\n
+                 *   : \':\' IDENT\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream;\n
+\n
+                tokenStream.mustMatch(Tokens.COLON);\n
+                tokenStream.mustMatch(Tokens.IDENT);\n
+\n
+                //TODO: CSS3 Paged Media says only "left", "center", and "right" are allowed\n
+\n
+                return tokenStream.token().value;\n
+            },\n
+\n
+            _font_face: function(){\n
+                /*\n
+                 * font_face\n
+                 *   : FONT_FACE_SYM S*\n
+                 *     \'{\' S* declaration [ \';\' S* declaration ]* \'}\' S*\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col;\n
+\n
+                //look for @page\n
+                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);\n
+                line = tokenStream.token().startLine;\n
+                col = tokenStream.token().startCol;\n
+\n
+                this._readWhitespace();\n
+\n
+                this.fire({\n
+                    type:   "startfontface",\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+\n
+                this._readDeclarations(true);\n
+\n
+                this.fire({\n
+                    type:   "endfontface",\n
+                    line:   line,\n
+                    col:    col\n
+                });\n
+            },\n
+\n
+            _viewport: function(){\n
+                /*\n
+                 * viewport\n
+                 *   : VIEWPORT_SYM S*\n
+                 *     \'{\' S* declaration? [ \';\' S* declaration? ]* \'}\' S*\n
+                 *   ;\n
+                 */\n
+                 var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col;\n
+\n
+                    tokenStream.mustMatch(Tokens.VIEWPORT_SYM);\n
+                    line = tokenStream.token().startLine;\n
+                    col = tokenStream.token().startCol;\n
+\n
+                    this._readWhitespace();\n
+\n
+                    this.fire({\n
+                        type:   "startviewport",\n
+                        line:   line,\n
+                        col:    col\n
+                    });\n
+\n
+                    this._readDeclarations(true);\n
+\n
+                    this.fire({\n
+                        type:   "endviewport",\n
+                        line:   line,\n
+                        col:    col\n
+                    });\n
+\n
+            },\n
+\n
+            _operator: function(inFunction){\n
+\n
+                /*\n
+                 * operator (outside function)\n
+                 *  : \'/\' S* | \',\' S* | /( empty )/\n
+                 * operator (inside function)\n
+                 *  : \'/\' S* | \'+\' S* | \'*\' S* | \'-\' S* /( empty )/\n
+                 *  ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    token       = null;\n
+\n
+                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) ||\n
+                    (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){\n
+                    token =  tokenStream.token();\n
+                    this._readWhitespace();\n
+                }\n
+                return token ? PropertyValuePart.fromToken(token) : null;\n
+\n
+            },\n
+\n
+            _combinator: function(){\n
+\n
+                /*\n
+                 * combinator\n
+                 *  : PLUS S* | GREATER S* | TILDE S* | S+\n
+                 *  ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    value       = null,\n
+                    token;\n
+\n
+                if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){\n
+                    token = tokenStream.token();\n
+                    value = new Combinator(token.value, token.startLine, token.startCol);\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return value;\n
+            },\n
+\n
+            _unary_operator: function(){\n
+\n
+                /*\n
+                 * unary_operator\n
+                 *  : \'-\' | \'+\'\n
+                 *  ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream;\n
+\n
+                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){\n
+                    return tokenStream.token().value;\n
+                } else {\n
+                    return null;\n
+                }\n
+            },\n
+\n
+            _property: function(){\n
+\n
+                /*\n
+                 * property\n
+                 *   : IDENT S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    value       = null,\n
+                    hack        = null,\n
+                    tokenValue,\n
+                    token,\n
+                    line,\n
+                    col;\n
+\n
+                //check for star hack - throws error if not allowed\n
+                if (tokenStream.peek() == Tokens.STAR && this.options.starHack){\n
+                    tokenStream.get();\n
+                    token = tokenStream.token();\n
+                    hack = token.value;\n
+                    line = token.startLine;\n
+                    col = token.startCol;\n
+                }\n
+\n
+                if(tokenStream.match(Tokens.IDENT)){\n
+                    token = tokenStream.token();\n
+                    tokenValue = token.value;\n
+\n
+                    //check for underscore hack - no error if not allowed because it\'s valid CSS syntax\n
+                    if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){\n
+                        hack = "_";\n
+                        tokenValue = tokenValue.substring(1);\n
+                    }\n
+\n
+                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return value;\n
+            },\n
+\n
+            //Augmented with CSS3 Selectors\n
+            _ruleset: function(){\n
+                /*\n
+                 * ruleset\n
+                 *   : selectors_group\n
+                 *     \'{\' S* declaration? [ \';\' S* declaration? ]* \'}\' S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    tt,\n
+                    selectors;\n
+\n
+\n
+                /*\n
+                 * Error Recovery: If even a single selector fails to parse,\n
+                 * then the entire ruleset should be thrown away.\n
+                 */\n
+                try {\n
+                    selectors = this._selectors_group();\n
+                } catch (ex){\n
+                    if (ex instanceof SyntaxError && !this.options.strict){\n
+\n
+                        //fire error event\n
+                        this.fire({\n
+                            type:       "error",\n
+                            error:      ex,\n
+                            message:    ex.message,\n
+                            line:       ex.line,\n
+                            col:        ex.col\n
+                        });\n
+\n
+                        //skip over everything until closing brace\n
+                        tt = tokenStream.advance([Tokens.RBRACE]);\n
+                        if (tt == Tokens.RBRACE){\n
+                            //if there\'s a right brace, the rule is finished so don\'t do anything\n
+                        } else {\n
+                            //otherwise, rethrow the error because it wasn\'t handled properly\n
+                            throw ex;\n
+                        }\n
+\n
+                    } else {\n
+                        //not a syntax error, rethrow it\n
+                        throw ex;\n
+                    }\n
+\n
+                    //trigger parser to continue\n
+                    return true;\n
+                }\n
+\n
+                //if it got here, all selectors parsed\n
+                if (selectors){\n
+\n
+                    this.fire({\n
+                        type:       "startrule",\n
+                        selectors:  selectors,\n
+                        line:       selectors[0].line,\n
+                        col:        selectors[0].col\n
+                    });\n
+\n
+                    this._readDeclarations(true);\n
+\n
+                    this.fire({\n
+                        type:       "endrule",\n
+                        selectors:  selectors,\n
+                        line:       selectors[0].line,\n
+                        col:        selectors[0].col\n
+                    });\n
+\n
+                }\n
+\n
+                return selectors;\n
+\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _selectors_group: function(){\n
+\n
+                /*\n
+                 * selectors_group\n
+                 *   : selector [ COMMA S* selector ]*\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    selectors   = [],\n
+                    selector;\n
+\n
+                selector = this._selector();\n
+                if (selector !== null){\n
+\n
+                    selectors.push(selector);\n
+                    while(tokenStream.match(Tokens.COMMA)){\n
+                        this._readWhitespace();\n
+                        selector = this._selector();\n
+                        if (selector !== null){\n
+                            selectors.push(selector);\n
+                        } else {\n
+                            this._unexpectedToken(tokenStream.LT(1));\n
+                        }\n
+                    }\n
+                }\n
+\n
+                return selectors.length ? selectors : null;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _selector: function(){\n
+                /*\n
+                 * selector\n
+                 *   : simple_selector_sequence [ combinator simple_selector_sequence ]*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    selector    = [],\n
+                    nextSelector = null,\n
+                    combinator  = null,\n
+                    ws          = null;\n
+\n
+                //if there\'s no simple selector, then there\'s no selector\n
+                nextSelector = this._simple_selector_sequence();\n
+                if (nextSelector === null){\n
+                    return null;\n
+                }\n
+\n
+                selector.push(nextSelector);\n
+\n
+                do {\n
+\n
+                    //look for a combinator\n
+                    combinator = this._combinator();\n
+\n
+                    if (combinator !== null){\n
+                        selector.push(combinator);\n
+                        nextSelector = this._simple_selector_sequence();\n
+\n
+                        //there must be a next selector\n
+                        if (nextSelector === null){\n
+                            this._unexpectedToken(tokenStream.LT(1));\n
+                        } else {\n
+\n
+                            //nextSelector is an instance of SelectorPart\n
+                            selector.push(nextSelector);\n
+                        }\n
+                    } else {\n
+\n
+                        //if there\'s not whitespace, we\'re done\n
+                        if (this._readWhitespace()){\n
+\n
+                            //add whitespace separator\n
+                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);\n
+\n
+                            //combinator is not required\n
+                            combinator = this._combinator();\n
+\n
+                            //selector is required if there\'s a combinator\n
+                            nextSelector = this._simple_selector_sequence();\n
+                            if (nextSelector === null){\n
+                                if (combinator !== null){\n
+                                    this._unexpectedToken(tokenStream.LT(1));\n
+                                }\n
+                            } else {\n
+\n
+                                if (combinator !== null){\n
+                                    selector.push(combinator);\n
+                                } else {\n
+                                    selector.push(ws);\n
+                                }\n
+\n
+                                selector.push(nextSelector);\n
+                            }\n
+                        } else {\n
+                            break;\n
+                        }\n
+\n
+                    }\n
+                } while(true);\n
+\n
+                return new Selector(selector, selector[0].line, selector[0].col);\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _simple_selector_sequence: function(){\n
+                /*\n
+                 * simple_selector_sequence\n
+                 *   : [ type_selector | universal ]\n
+                 *     [ HASH | class | attrib | pseudo | negation ]*\n
+                 *   | [ HASH | class | attrib | pseudo | negation ]+\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+\n
+                    //parts of a simple selector\n
+                    elementName = null,\n
+                    modifiers   = [],\n
+\n
+                    //complete selector text\n
+                    selectorText= "",\n
+\n
+                    //the different parts after the element name to search for\n
+                    components  = [\n
+                        //HASH\n
+                        function(){\n
+                            return tokenStream.match(Tokens.HASH) ?\n
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :\n
+                                    null;\n
+                        },\n
+                        this._class,\n
+                        this._attrib,\n
+                        this._pseudo,\n
+                        this._negation\n
+                    ],\n
+                    i           = 0,\n
+                    len         = components.length,\n
+                    component   = null,\n
+                    found       = false,\n
+                    line,\n
+                    col;\n
+\n
+\n
+                //get starting line and column for the selector\n
+                line = tokenStream.LT(1).startLine;\n
+                col = tokenStream.LT(1).startCol;\n
+\n
+                elementName = this._type_selector();\n
+                if (!elementName){\n
+                    elementName = this._universal();\n
+                }\n
+\n
+                if (elementName !== null){\n
+                    selectorText += elementName;\n
+                }\n
+\n
+                while(true){\n
+\n
+                    //whitespace means we\'re done\n
+                    if (tokenStream.peek() === Tokens.S){\n
+                        break;\n
+                    }\n
+\n
+                    //check for each component\n
+                    while(i < len && component === null){\n
+                        component = components[i++].call(this);\n
+                    }\n
+\n
+                    if (component === null){\n
+\n
+                        //we don\'t have a selector\n
+                        if (selectorText === ""){\n
+                            return null;\n
+                        } else {\n
+                            break;\n
+                        }\n
+                    } else {\n
+                        i = 0;\n
+                        modifiers.push(component);\n
+                        selectorText += component.toString();\n
+                        component = null;\n
+                    }\n
+                }\n
+\n
+\n
+                return selectorText !== "" ?\n
+                        new SelectorPart(elementName, modifiers, selectorText, line, col) :\n
+                        null;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _type_selector: function(){\n
+                /*\n
+                 * type_selector\n
+                 *   : [ namespace_prefix ]? element_name\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    ns          = this._namespace_prefix(),\n
+                    elementName = this._element_name();\n
+\n
+                if (!elementName){\n
+                    /*\n
+                     * Need to back out the namespace that was read due to both\n
+                     * type_selector and universal reading namespace_prefix\n
+                     * first. Kind of hacky, but only way I can figure out\n
+                     * right now how to not change the grammar.\n
+                     */\n
+                    if (ns){\n
+                        tokenStream.unget();\n
+                        if (ns.length > 1){\n
+                            tokenStream.unget();\n
+                        }\n
+                    }\n
+\n
+                    return null;\n
+                } else {\n
+                    if (ns){\n
+                        elementName.text = ns + elementName.text;\n
+                        elementName.col -= ns.length;\n
+                    }\n
+                    return elementName;\n
+                }\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _class: function(){\n
+                /*\n
+                 * class\n
+                 *   : \'.\' IDENT\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    token;\n
+\n
+                if (tokenStream.match(Tokens.DOT)){\n
+                    tokenStream.mustMatch(Tokens.IDENT);\n
+                    token = tokenStream.token();\n
+                    return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1);\n
+                } else {\n
+                    return null;\n
+                }\n
+\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _element_name: function(){\n
+                /*\n
+                 * element_name\n
+                 *   : IDENT\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    token;\n
+\n
+                if (tokenStream.match(Tokens.IDENT)){\n
+                    token = tokenStream.token();\n
+                    return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol);\n
+\n
+                } else {\n
+                    return null;\n
+                }\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _namespace_prefix: function(){\n
+                /*\n
+                 * namespace_prefix\n
+                 *   : [ IDENT | \'*\' ]? \'|\'\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    value       = "";\n
+\n
+                //verify that this is a namespace prefix\n
+                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){\n
+\n
+                    if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){\n
+                        value += tokenStream.token().value;\n
+                    }\n
+\n
+                    tokenStream.mustMatch(Tokens.PIPE);\n
+                    value += "|";\n
+\n
+                }\n
+\n
+                return value.length ? value : null;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _universal: function(){\n
+                /*\n
+                 * universal\n
+                 *   : [ namespace_prefix ]? \'*\'\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    value       = "",\n
+                    ns;\n
+\n
+                ns = this._namespace_prefix();\n
+                if(ns){\n
+                    value += ns;\n
+                }\n
+\n
+                if(tokenStream.match(Tokens.STAR)){\n
+                    value += "*";\n
+                }\n
+\n
+                return value.length ? value : null;\n
+\n
+           },\n
+\n
+            //CSS3 Selectors\n
+            _attrib: function(){\n
+                /*\n
+                 * attrib\n
+                 *   : \'[\' S* [ namespace_prefix ]? IDENT S*\n
+                 *         [ [ PREFIXMATCH |\n
+                 *             SUFFIXMATCH |\n
+                 *             SUBSTRINGMATCH |\n
+                 *             \'=\' |\n
+                 *             INCLUDES |\n
+                 *             DASHMATCH ] S* [ IDENT | STRING ] S*\n
+                 *         ]? \']\'\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    value       = null,\n
+                    ns,\n
+                    token;\n
+\n
+                if (tokenStream.match(Tokens.LBRACKET)){\n
+                    token = tokenStream.token();\n
+                    value = token.value;\n
+                    value += this._readWhitespace();\n
+\n
+                    ns = this._namespace_prefix();\n
+\n
+                    if (ns){\n
+                        value += ns;\n
+                    }\n
+\n
+                    tokenStream.mustMatch(Tokens.IDENT);\n
+                    value += tokenStream.token().value;\n
+                    value += this._readWhitespace();\n
+\n
+                    if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,\n
+                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){\n
+\n
+                        value += tokenStream.token().value;\n
+                        value += this._readWhitespace();\n
+\n
+                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n
+                        value += tokenStream.token().value;\n
+                        value += this._readWhitespace();\n
+                    }\n
+\n
+                    tokenStream.mustMatch(Tokens.RBRACKET);\n
+\n
+                    return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol);\n
+                } else {\n
+                    return null;\n
+                }\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _pseudo: function(){\n
+\n
+                /*\n
+                 * pseudo\n
+                 *   : \':\' \':\'? [ IDENT | functional_pseudo ]\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    pseudo      = null,\n
+                    colons      = ":",\n
+                    line,\n
+                    col;\n
+\n
+                if (tokenStream.match(Tokens.COLON)){\n
+\n
+                    if (tokenStream.match(Tokens.COLON)){\n
+                        colons += ":";\n
+                    }\n
+\n
+                    if (tokenStream.match(Tokens.IDENT)){\n
+                        pseudo = tokenStream.token().value;\n
+                        line = tokenStream.token().startLine;\n
+                        col = tokenStream.token().startCol - colons.length;\n
+                    } else if (tokenStream.peek() == Tokens.FUNCTION){\n
+                        line = tokenStream.LT(1).startLine;\n
+                        col = tokenStream.LT(1).startCol - colons.length;\n
+                        pseudo = this._functional_pseudo();\n
+                    }\n
+\n
+                    if (pseudo){\n
+                        pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col);\n
+                    }\n
+                }\n
+\n
+                return pseudo;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _functional_pseudo: function(){\n
+                /*\n
+                 * functional_pseudo\n
+                 *   : FUNCTION S* expression \')\'\n
+                 *   ;\n
+                */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    value = null;\n
+\n
+                if(tokenStream.match(Tokens.FUNCTION)){\n
+                    value = tokenStream.token().value;\n
+                    value += this._readWhitespace();\n
+                    value += this._expression();\n
+                    tokenStream.mustMatch(Tokens.RPAREN);\n
+                    value += ")";\n
+                }\n
+\n
+                return value;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _expression: function(){\n
+                /*\n
+                 * expression\n
+                 *   : [ [ PLUS | \'-\' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    value       = "";\n
+\n
+                while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,\n
+                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,\n
+                        Tokens.FREQ, Tokens.ANGLE, Tokens.TIME,\n
+                        Tokens.RESOLUTION, Tokens.SLASH])){\n
+\n
+                    value += tokenStream.token().value;\n
+                    value += this._readWhitespace();\n
+                }\n
+\n
+                return value.length ? value : null;\n
+\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _negation: function(){\n
+                /*\n
+                 * negation\n
+                 *   : NOT S* negation_arg S* \')\'\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    line,\n
+                    col,\n
+                    value       = "",\n
+                    arg,\n
+                    subpart     = null;\n
+\n
+                if (tokenStream.match(Tokens.NOT)){\n
+                    value = tokenStream.token().value;\n
+                    line = tokenStream.token().startLine;\n
+                    col = tokenStream.token().startCol;\n
+                    value += this._readWhitespace();\n
+                    arg = this._negation_arg();\n
+                    value += arg;\n
+                    value += this._readWhitespace();\n
+                    tokenStream.match(Tokens.RPAREN);\n
+                    value += tokenStream.token().value;\n
+\n
+                    subpart = new SelectorSubPart(value, "not", line, col);\n
+                    subpart.args.push(arg);\n
+                }\n
+\n
+                return subpart;\n
+            },\n
+\n
+            //CSS3 Selectors\n
+            _negation_arg: function(){\n
+                /*\n
+                 * negation_arg\n
+                 *   : type_selector | universal | HASH | class | attrib | pseudo\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    args        = [\n
+                        this._type_selector,\n
+                        this._universal,\n
+                        function(){\n
+                            return tokenStream.match(Tokens.HASH) ?\n
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :\n
+                                    null;\n
+                        },\n
+                        this._class,\n
+                        this._attrib,\n
+                        this._pseudo\n
+                    ],\n
+                    arg         = null,\n
+                    i           = 0,\n
+                    len         = args.length,\n
+                    elementName,\n
+                    line,\n
+                    col,\n
+                    part;\n
+\n
+                line = tokenStream.LT(1).startLine;\n
+                col = tokenStream.LT(1).startCol;\n
+\n
+                while(i < len && arg === null){\n
+\n
+                    arg = args[i].call(this);\n
+                    i++;\n
+                }\n
+\n
+                //must be a negation arg\n
+                if (arg === null){\n
+                    this._unexpectedToken(tokenStream.LT(1));\n
+                }\n
+\n
+                //it\'s an element name\n
+                if (arg.type == "elementName"){\n
+                    part = new SelectorPart(arg, [], arg.toString(), line, col);\n
+                } else {\n
+                    part = new SelectorPart(null, [arg], arg.toString(), line, col);\n
+                }\n
+\n
+                return part;\n
+            },\n
+\n
+            _declaration: function(){\n
+\n
+                /*\n
+                 * declaration\n
+                 *   : property \':\' S* expr prio?\n
+                 *   | /( empty )/\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    property    = null,\n
+                    expr        = null,\n
+                    prio        = null,\n
+                    error       = null,\n
+                    invalid     = null,\n
+                    propertyName= "";\n
+\n
+                property = this._property();\n
+                if (property !== null){\n
+\n
+                    tokenStream.mustMatch(Tokens.COLON);\n
+                    this._readWhitespace();\n
+\n
+                    expr = this._expr();\n
+\n
+                    //if there\'s no parts for the value, it\'s an error\n
+                    if (!expr || expr.length === 0){\n
+                        this._unexpectedToken(tokenStream.LT(1));\n
+                    }\n
+\n
+                    prio = this._prio();\n
+\n
+                    /*\n
+                     * If hacks should be allowed, then only check the root\n
+                     * property. If hacks should not be allowed, treat\n
+                     * _property or *property as invalid properties.\n
+                     */\n
+                    propertyName = property.toString();\n
+                    if (this.options.starHack && property.hack == "*" ||\n
+                            this.options.underscoreHack && property.hack == "_") {\n
+\n
+                        propertyName = property.text;\n
+                    }\n
+\n
+                    try {\n
+                        this._validateProperty(propertyName, expr);\n
+                    } catch (ex) {\n
+                        invalid = ex;\n
+                    }\n
+\n
+                    this.fire({\n
+                        type:       "property",\n
+                        property:   property,\n
+                        value:      expr,\n
+                        important:  prio,\n
+                        line:       property.line,\n
+                        col:        property.col,\n
+                        invalid:    invalid\n
+                    });\n
+\n
+                    return true;\n
+                } else {\n
+                    return false;\n
+                }\n
+            },\n
+\n
+            _prio: function(){\n
+                /*\n
+                 * prio\n
+                 *   : IMPORTANT_SYM S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);\n
+\n
+                this._readWhitespace();\n
+                return result;\n
+            },\n
+\n
+            _expr: function(inFunction){\n
+                /*\n
+                 * expr\n
+                 *   : term [ operator term ]*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    values      = [],\n
+                    //valueParts    = [],\n
+                    value       = null,\n
+                    operator    = null;\n
+\n
+                value = this._term();\n
+                if (value !== null){\n
+\n
+                    values.push(value);\n
+\n
+                    do {\n
+                        operator = this._operator(inFunction);\n
+\n
+                        //if there\'s an operator, keep building up the value parts\n
+                        if (operator){\n
+                            values.push(operator);\n
+                        } /*else {\n
+                            //if there\'s not an operator, you have a full value\n
+                            values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n
+                            valueParts = [];\n
+                        }*/\n
+\n
+                        value = this._term();\n
+\n
+                        if (value === null){\n
+                            break;\n
+                        } else {\n
+                            values.push(value);\n
+                        }\n
+                    } while(true);\n
+                }\n
+\n
+                //cleanup\n
+                /*if (valueParts.length){\n
+                    values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n
+                }*/\n
+\n
+                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;\n
+            },\n
+\n
+            _term: function(){\n
+\n
+                /*\n
+                 * term\n
+                 *   : unary_operator?\n
+                 *     [ NUMBER S* | PERCENTAGE S* | LENGTH S* | ANGLE S* |\n
+                 *       TIME S* | FREQ S* | function | ie_function ]\n
+                 *   | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    unary       = null,\n
+                    value       = null,\n
+                    token,\n
+                    line,\n
+                    col;\n
+\n
+                //returns the operator or null\n
+                unary = this._unary_operator();\n
+                if (unary !== null){\n
+                    line = tokenStream.token().startLine;\n
+                    col = tokenStream.token().startCol;\n
+                }\n
+\n
+                //exception for IE filters\n
+                if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){\n
+\n
+                    value = this._ie_function();\n
+                    if (unary === null){\n
+                        line = tokenStream.token().startLine;\n
+                        col = tokenStream.token().startCol;\n
+                    }\n
+\n
+                //see if there\'s a simple match\n
+                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,\n
+                        Tokens.ANGLE, Tokens.TIME,\n
+                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){\n
+\n
+                    value = tokenStream.token().value;\n
+                    if (unary === null){\n
+                        line = tokenStream.token().startLine;\n
+                        col = tokenStream.token().startCol;\n
+                    }\n
+                    this._readWhitespace();\n
+                } else {\n
+\n
+                    //see if it\'s a color\n
+                    token = this._hexcolor();\n
+                    if (token === null){\n
+\n
+                        //if there\'s no unary, get the start of the next token for line/col info\n
+                        if (unary === null){\n
+                            line = tokenStream.LT(1).startLine;\n
+                            col = tokenStream.LT(1).startCol;\n
+                        }\n
+\n
+                        //has to be a function\n
+                        if (value === null){\n
+\n
+                            /*\n
+                             * This checks for alpha(opacity=0) style of IE\n
+                             * functions. IE_FUNCTION only presents progid: style.\n
+                             */\n
+                            if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){\n
+                                value = this._ie_function();\n
+                            } else {\n
+                                value = this._function();\n
+                            }\n
+                        }\n
+\n
+                        /*if (value === null){\n
+                            return null;\n
+                            //throw new Error("Expected identifier at line " + tokenStream.token().startLine + ", character " +  tokenStream.token().startCol + ".");\n
+                        }*/\n
+\n
+                    } else {\n
+                        value = token.value;\n
+                        if (unary === null){\n
+                            line = token.startLine;\n
+                            col = token.startCol;\n
+                        }\n
+                    }\n
+\n
+                }\n
+\n
+                return value !== null ?\n
+                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :\n
+                        null;\n
+\n
+            },\n
+\n
+            _function: function(){\n
+\n
+                /*\n
+                 * function\n
+                 *   : FUNCTION S* expr \')\' S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    functionText = null,\n
+                    expr        = null,\n
+                    lt;\n
+\n
+                if (tokenStream.match(Tokens.FUNCTION)){\n
+                    functionText = tokenStream.token().value;\n
+                    this._readWhitespace();\n
+                    expr = this._expr(true);\n
+                    functionText += expr;\n
+\n
+                    //START: Horrible hack in case it\'s an IE filter\n
+                    if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){\n
+                        do {\n
+\n
+                            if (this._readWhitespace()){\n
+                                functionText += tokenStream.token().value;\n
+                            }\n
+\n
+                            //might be second time in the loop\n
+                            if (tokenStream.LA(0) == Tokens.COMMA){\n
+                                functionText += tokenStream.token().value;\n
+                            }\n
+\n
+                            tokenStream.match(Tokens.IDENT);\n
+                            functionText += tokenStream.token().value;\n
+\n
+                            tokenStream.match(Tokens.EQUALS);\n
+                            functionText += tokenStream.token().value;\n
+\n
+                            //functionText += this._term();\n
+                            lt = tokenStream.peek();\n
+                            while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n
+                                tokenStream.get();\n
+                                functionText += tokenStream.token().value;\n
+                                lt = tokenStream.peek();\n
+                            }\n
+                        } while(tokenStream.match([Tokens.COMMA, Tokens.S]));\n
+                    }\n
+\n
+                    //END: Horrible Hack\n
+\n
+                    tokenStream.match(Tokens.RPAREN);\n
+                    functionText += ")";\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return functionText;\n
+            },\n
+\n
+            _ie_function: function(){\n
+\n
+                /* (My own extension)\n
+                 * ie_function\n
+                 *   : IE_FUNCTION S* IDENT \'=\' term [S* \',\'? IDENT \'=\' term]+ \')\' S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    functionText = null,\n
+                    expr        = null,\n
+                    lt;\n
+\n
+                //IE function can begin like a regular function, too\n
+                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){\n
+                    functionText = tokenStream.token().value;\n
+\n
+                    do {\n
+\n
+                        if (this._readWhitespace()){\n
+                            functionText += tokenStream.token().value;\n
+                        }\n
+\n
+                        //might be second time in the loop\n
+                        if (tokenStream.LA(0) == Tokens.COMMA){\n
+                            functionText += tokenStream.token().value;\n
+                        }\n
+\n
+                        tokenStream.match(Tokens.IDENT);\n
+                        functionText += tokenStream.token().value;\n
+\n
+                        tokenStream.match(Tokens.EQUALS);\n
+                        functionText += tokenStream.token().value;\n
+\n
+                        //functionText += this._term();\n
+                        lt = tokenStream.peek();\n
+                        while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n
+                            tokenStream.get();\n
+                            functionText += tokenStream.token().value;\n
+                            lt = tokenStream.peek();\n
+                        }\n
+                    } while(tokenStream.match([Tokens.COMMA, Tokens.S]));\n
+\n
+                    tokenStream.match(Tokens.RPAREN);\n
+                    functionText += ")";\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return functionText;\n
+            },\n
+\n
+            _hexcolor: function(){\n
+                /*\n
+                 * There is a constraint on the color that it must\n
+                 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])\n
+                 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.\n
+                 *\n
+                 * hexcolor\n
+                 *   : HASH S*\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    token = null,\n
+                    color;\n
+\n
+                if(tokenStream.match(Tokens.HASH)){\n
+\n
+                    //need to do some validation here\n
+\n
+                    token = tokenStream.token();\n
+                    color = token.value;\n
+                    if (!/#[a-f0-9]{3,6}/i.test(color)){\n
+                        throw new SyntaxError("Expected a hex color but found \'" + color + "\' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);\n
+                    }\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return token;\n
+            },\n
+\n
+            //-----------------------------------------------------------------\n
+            // Animations methods\n
+            //-----------------------------------------------------------------\n
+\n
+            _keyframes: function(){\n
+\n
+                /*\n
+                 * keyframes:\n
+                 *   : KEYFRAMES_SYM S* keyframe_name S* \'{\' S* keyframe_rule* \'}\' {\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    token,\n
+                    tt,\n
+                    name,\n
+                    prefix = "";\n
+\n
+                tokenStream.mustMatch(Tokens.KEYFRAMES_SYM);\n
+                token = tokenStream.token();\n
+                if (/^@\\-([^\\-]+)\\-/.test(token.value)) {\n
+                    prefix = RegExp.$1;\n
+                }\n
+\n
+                this._readWhitespace();\n
+                name = this._keyframe_name();\n
+\n
+                this._readWhitespace();\n
+                tokenStream.mustMatch(Tokens.LBRACE);\n
+\n
+                this.fire({\n
+                    type:   "startkeyframes",\n
+                    name:   name,\n
+                    prefix: prefix,\n
+                    line:   token.startLine,\n
+                    col:    token.startCol\n
+                });\n
+\n
+                this._readWhitespace();\n
+                tt = tokenStream.peek();\n
+\n
+                //check for key\n
+                while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) {\n
+                    this._keyframe_rule();\n
+                    this._readWhitespace();\n
+                    tt = tokenStream.peek();\n
+                }\n
+\n
+                this.fire({\n
+                    type:   "endkeyframes",\n
+                    name:   name,\n
+                    prefix: prefix,\n
+                    line:   token.startLine,\n
+                    col:    token.startCol\n
+                });\n
+\n
+                this._readWhitespace();\n
+                tokenStream.mustMatch(Tokens.RBRACE);\n
+\n
+            },\n
+\n
+            _keyframe_name: function(){\n
+\n
+                /*\n
+                 * keyframe_name:\n
+                 *   : IDENT\n
+                 *   | STRING\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    token;\n
+\n
+                tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n
+                return SyntaxUnit.fromToken(tokenStream.token());\n
+            },\n
+\n
+            _keyframe_rule: function(){\n
+\n
+                /*\n
+                 * keyframe_rule:\n
+                 *   : key_list S*\n
+                 *     \'{\' S* declaration [ \';\' S* declaration ]* \'}\' S*\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    token,\n
+                    keyList = this._key_list();\n
+\n
+                this.fire({\n
+                    type:   "startkeyframerule",\n
+                    keys:   keyList,\n
+                    line:   keyList[0].line,\n
+                    col:    keyList[0].col\n
+                });\n
+\n
+                this._readDeclarations(true);\n
+\n
+                this.fire({\n
+                    type:   "endkeyframerule",\n
+                    keys:   keyList,\n
+                    line:   keyList[0].line,\n
+                    col:    keyList[0].col\n
+                });\n
+\n
+            },\n
+\n
+            _key_list: function(){\n
+\n
+                /*\n
+                 * key_list:\n
+                 *   : key [ S* \',\' S* key]*\n
+                 *   ;\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    token,\n
+                    key,\n
+                    keyList = [];\n
+\n
+                //must be least one key\n
+                keyList.push(this._key());\n
+\n
+                this._readWhitespace();\n
+\n
+                while(tokenStream.match(Tokens.COMMA)){\n
+                    this._readWhitespace();\n
+                    keyList.push(this._key());\n
+                    this._readWhitespace();\n
+                }\n
+\n
+                return keyList;\n
+            },\n
+\n
+            _key: function(){\n
+                /*\n
+                 * There is a restriction that IDENT can be only "from" or "to".\n
+                 *\n
+                 * key\n
+                 *   : PERCENTAGE\n
+                 *   | IDENT\n
+                 *   ;\n
+                 */\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    token;\n
+\n
+                if (tokenStream.match(Tokens.PERCENTAGE)){\n
+                    return SyntaxUnit.fromToken(tokenStream.token());\n
+                } else if (tokenStream.match(Tokens.IDENT)){\n
+                    token = tokenStream.token();\n
+\n
+                    if (/from|to/i.test(token.value)){\n
+                        return SyntaxUnit.fromToken(token);\n
+                    }\n
+\n
+                    tokenStream.unget();\n
+                }\n
+\n
+                //if it gets here, there wasn\'t a valid token, so time to explode\n
+                this._unexpectedToken(tokenStream.LT(1));\n
+            },\n
+\n
+            //-----------------------------------------------------------------\n
+            // Helper methods\n
+            //-----------------------------------------------------------------\n
+\n
+            /**\n
+             * Not part of CSS grammar, but useful for skipping over\n
+             * combination of white space and HTML-style comments.\n
+             * @return {void}\n
+             * @method _skipCruft\n
+             * @private\n
+             */\n
+            _skipCruft: function(){\n
+                while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){\n
+                    //noop\n
+                }\n
+            },\n
+\n
+            /**\n
+             * Not part of CSS grammar, but this pattern occurs frequently\n
+             * in the official CSS grammar. Split out here to eliminate\n
+             * duplicate code.\n
+             * @param {Boolean} checkStart Indicates if the rule should check\n
+             *      for the left brace at the beginning.\n
+             * @param {Boolean} readMargins Indicates if the rule should check\n
+             *      for margin patterns.\n
+             * @return {void}\n
+             * @method _readDeclarations\n
+             * @private\n
+             */\n
+            _readDeclarations: function(checkStart, readMargins){\n
+                /*\n
+                 * Reads the pattern\n
+                 * S* \'{\' S* declaration [ \';\' S* declaration ]* \'}\' S*\n
+                 * or\n
+                 * S* \'{\' S* [ declaration | margin ]? [ \';\' S* [ declaration | margin ]? ]* \'}\' S*\n
+                 * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect.\n
+                 * A semicolon is only necessary following a declaration is there\'s another declaration\n
+                 * or margin afterwards.\n
+                 */\n
+                var tokenStream = this._tokenStream,\n
+                    tt;\n
+\n
+\n
+                this._readWhitespace();\n
+\n
+                if (checkStart){\n
+                    tokenStream.mustMatch(Tokens.LBRACE);\n
+                }\n
+\n
+                this._readWhitespace();\n
+\n
+                try {\n
+\n
+                    while(true){\n
+\n
+                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){\n
+            
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+                //noop\n
+                        } else if (this._declaration()){\n
+                            if (!tokenStream.match(Tokens.SEMICOLON)){\n
+                                break;\n
+                            }\n
+                        } else {\n
+                            break;\n
+                        }\n
+\n
+                        //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){\n
+                        //    break;\n
+                        //}\n
+                        this._readWhitespace();\n
+                    }\n
+\n
+                    tokenStream.mustMatch(Tokens.RBRACE);\n
+                    this._readWhitespace();\n
+\n
+                } catch (ex) {\n
+                    if (ex instanceof SyntaxError && !this.options.strict){\n
+\n
+                        //fire error event\n
+                        this.fire({\n
+                            type:       "error",\n
+                            error:      ex,\n
+                            message:    ex.message,\n
+                            line:       ex.line,\n
+                            col:        ex.col\n
+                        });\n
+\n
+                        //see if there\'s another declaration\n
+                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);\n
+                        if (tt == Tokens.SEMICOLON){\n
+                            //if there\'s a semicolon, then there might be another declaration\n
+                            this._readDeclarations(false, readMargins);\n
+                        } else if (tt != Tokens.RBRACE){\n
+                            //if there\'s a right brace, the rule is finished so don\'t do anything\n
+                            //otherwise, rethrow the error because it wasn\'t handled properly\n
+                            throw ex;\n
+                        }\n
+\n
+                    } else {\n
+                        //not a syntax error, rethrow it\n
+                        throw ex;\n
+                    }\n
+                }\n
+\n
+            },\n
+\n
+            /**\n
+             * In some cases, you can end up with two white space tokens in a\n
+             * row. Instead of making a change in every function that looks for\n
+             * white space, this function is used to match as much white space\n
+             * as necessary.\n
+             * @method _readWhitespace\n
+             * @return {String} The white space if found, empty string if not.\n
+             * @private\n
+             */\n
+            _readWhitespace: function(){\n
+\n
+                var tokenStream = this._tokenStream,\n
+                    ws = "";\n
+\n
+                while(tokenStream.match(Tokens.S)){\n
+                    ws += tokenStream.token().value;\n
+                }\n
+\n
+                return ws;\n
+            },\n
+\n
+\n
+            /**\n
+             * Throws an error when an unexpected token is found.\n
+             * @param {Object} token The token that was found.\n
+             * @method _unexpectedToken\n
+             * @return {void}\n
+             * @private\n
+             */\n
+            _unexpectedToken: function(token){\n
+                throw new SyntaxError("Unexpected token \'" + token.value + "\' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);\n
+            },\n
+\n
+            /**\n
+             * Helper method used for parsing subparts of a style sheet.\n
+             * @return {void}\n
+             * @method _verifyEnd\n
+             * @private\n
+             */\n
+            _verifyEnd: function(){\n
+                if (this._tokenStream.LA(1) != Tokens.EOF){\n
+                    this._unexpectedToken(this._tokenStream.LT(1));\n
+                }\n
+            },\n
+\n
+            //-----------------------------------------------------------------\n
+            // Validation methods\n
+            //-----------------------------------------------------------------\n
+            _validateProperty: function(property, value){\n
+                Validation.validate(property, value);\n
+            },\n
+\n
+            //-----------------------------------------------------------------\n
+            // Parsing methods\n
+            //-----------------------------------------------------------------\n
+\n
+            parse: function(input){\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+                this._stylesheet();\n
+            },\n
+\n
+            parseStyleSheet: function(input){\n
+                //just passthrough\n
+                return this.parse(input);\n
+            },\n
+\n
+            parseMediaQuery: function(input){\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+                var result = this._media_query();\n
+\n
+                //if there\'s anything more, then it\'s an invalid selector\n
+                this._verifyEnd();\n
+\n
+                //otherwise return result\n
+                return result;\n
+            },\n
+\n
+            /**\n
+             * Parses a property value (everything after the semicolon).\n
+             * @return {parserlib.css.PropertyValue} The property value.\n
+             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n
+             * @method parserPropertyValue\n
+             */\n
+            parsePropertyValue: function(input){\n
+\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+                this._readWhitespace();\n
+\n
+                var result = this._expr();\n
+\n
+                //okay to have a trailing white space\n
+                this._readWhitespace();\n
+\n
+                //if there\'s anything more, then it\'s an invalid selector\n
+                this._verifyEnd();\n
+\n
+                //otherwise return result\n
+                return result;\n
+            },\n
+\n
+            /**\n
+             * Parses a complete CSS rule, including selectors and\n
+             * properties.\n
+             * @param {String} input The text to parser.\n
+             * @return {Boolean} True if the parse completed successfully, false if not.\n
+             * @method parseRule\n
+             */\n
+            parseRule: function(input){\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+\n
+                //skip any leading white space\n
+                this._readWhitespace();\n
+\n
+                var result = this._ruleset();\n
+\n
+                //skip any trailing white space\n
+                this._readWhitespace();\n
+\n
+                //if there\'s anything more, then it\'s an invalid selector\n
+                this._verifyEnd();\n
+\n
+                //otherwise return result\n
+                return result;\n
+            },\n
+\n
+            /**\n
+             * Parses a single CSS selector (no comma)\n
+             * @param {String} input The text to parse as a CSS selector.\n
+             * @return {Selector} An object representing the selector.\n
+             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n
+             * @method parseSelector\n
+             */\n
+            parseSelector: function(input){\n
+\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+\n
+                //skip any leading white space\n
+                this._readWhitespace();\n
+\n
+                var result = this._selector();\n
+\n
+                //skip any trailing white space\n
+                this._readWhitespace();\n
+\n
+                //if there\'s anything more, then it\'s an invalid selector\n
+                this._verifyEnd();\n
+\n
+                //otherwise return result\n
+                return result;\n
+            },\n
+\n
+            /**\n
+             * Parses an HTML style attribute: a set of CSS declarations\n
+             * separated by semicolons.\n
+             * @param {String} input The text to parse as a style attribute\n
+             * @return {void}\n
+             * @method parseStyleAttribute\n
+             */\n
+            parseStyleAttribute: function(input){\n
+                input += "}"; // for error recovery in _readDeclarations()\n
+                this._tokenStream = new TokenStream(input, Tokens);\n
+                this._readDeclarations();\n
+            }\n
+        };\n
+\n
+    //copy over onto prototype\n
+    for (prop in additions){\n
+        if (additions.hasOwnProperty(prop)){\n
+            proto[prop] = additions[prop];\n
+        }\n
+    }\n
+\n
+    return proto;\n
+}();\n
+\n
+\n
+/*\n
+nth\n
+  : S* [ [\'-\'|\'+\']? INTEGER? {N} [ S* [\'-\'|\'+\'] S* INTEGER ]? |\n
+         [\'-\'|\'+\']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*\n
+  ;\n
+*/\n
+\n
+/*global Validation, ValidationTypes, ValidationError*/\n
+var Properties = {\n
+\n
+    //A\n
+    "alignment-adjust"              : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>",\n
+    "alignment-baseline"            : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",\n
+    "animation"                     : 1,\n
+    "animation-delay"               : { multi: "<time>", comma: true },\n
+    "animation-direction"           : { multi: "normal | alternate", comma: true },\n
+    "animation-duration"            : { multi: "<time>", comma: true },\n
+    "animation-iteration-count"     : { multi: "<number> | infinite", comma: true },\n
+    "animation-name"                : { multi: "none | <ident>", comma: true },\n
+    "animation-play-state"          : { multi: "running | paused", comma: true },\n
+    "animation-timing-function"     : 1,\n
+\n
+    //vendor prefixed\n
+    "-moz-animation-delay"               : { multi: "<time>", comma: true },\n
+    "-moz-animation-direction"           : { multi: "normal | alternate", comma: true },\n
+    "-moz-animation-duration"            : { multi: "<time>", comma: true },\n
+    "-moz-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },\n
+    "-moz-animation-name"                : { multi: "none | <ident>", comma: true },\n
+    "-moz-animation-play-state"          : { multi: "running | paused", comma: true },\n
+\n
+    "-ms-animation-delay"               : { multi: "<time>", comma: true },\n
+    "-ms-animation-direction"           : { multi: "normal | alternate", comma: true },\n
+    "-ms-animation-duration"            : { multi: "<time>", comma: true },\n
+    "-ms-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },\n
+    "-ms-animation-name"                : { multi: "none | <ident>", comma: true },\n
+    "-ms-animation-play-state"          : { multi: "running | paused", comma: true },\n
+\n
+    "-webkit-animation-delay"               : { multi: "<time>", comma: true },\n
+    "-webkit-animation-direction"           : { multi: "normal | alternate", comma: true },\n
+    "-webkit-animation-duration"            : { multi: "<time>", comma: true },\n
+    "-webkit-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },\n
+    "-webkit-animation-name"                : { multi: "none | <ident>", comma: true },\n
+    "-webkit-animation-play-state"          : { multi: "running | paused", comma: true },\n
+\n
+    "-o-animation-delay"               : { multi: "<time>", comma: true },\n
+    "-o-animation-direction"           : { multi: "normal | alternate", comma: true },\n
+    "-o-animation-duration"            : { multi: "<time>", comma: true },\n
+    "-o-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },\n
+    "-o-animation-name"                : { multi: "none | <ident>", comma: true },\n
+    "-o-animation-play-state"          : { multi: "running | paused", comma: true },\n
+\n
+    "appearance"                    : "icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | none | inherit",\n
+    "azimuth"                       : function (expression) {\n
+        var simple      = "<angle> | leftwards | rightwards | inherit",\n
+            direction   = "left-side | far-left | left | center-left | center | center-right | right | far-right | right-side",\n
+            behind      = false,\n
+            valid       = false,\n
+            part;\n
+\n
+        if (!ValidationTypes.isAny(expression, simple)) {\n
+            if (ValidationTypes.isAny(expression, "behind")) {\n
+                behind = true;\n
+                valid = true;\n
+            }\n
+\n
+            if (ValidationTypes.isAny(expression, direction)) {\n
+                valid = true;\n
+                if (!behind) {\n
+                    ValidationTypes.isAny(expression, "behind");\n
+                }\n
+            }\n
+        }\n
+\n
+        if (expression.hasNext()) {\n
+            part = expression.next();\n
+            if (valid) {\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                throw new ValidationError("Expected (<\'azimuth\'>) but found \'" + part + "\'.", part.line, part.col);\n
+            }\n
+        }\n
+    },\n
+\n
+    //B\n
+    "backface-visibility"           : "visible | hidden",\n
+    "background"                    : 1,\n
+    "background-attachment"         : { multi: "<attachment>", comma: true },\n
+    "background-clip"               : { multi: "<box>", comma: true },\n
+    "background-color"              : "<color> | inherit",\n
+    "background-image"              : { multi: "<bg-image>", comma: true },\n
+    "background-origin"             : { multi: "<box>", comma: true },\n
+    "background-position"           : { multi: "<bg-position>", comma: true },\n
+    "background-repeat"             : { multi: "<repeat-style>" },\n
+    "background-size"               : { multi: "<bg-size>", comma: true },\n
+    "baseline-shift"                : "baseline | sub | super | <percentage> | <length>",\n
+    "behavior"                      : 1,\n
+    "binding"                       : 1,\n
+    "bleed"                         : "<length>",\n
+    "bookmark-label"                : "<content> | <attr> | <string>",\n
+    "bookmark-level"                : "none | <integer>",\n
+    "bookmark-state"                : "open | closed",\n
+    "bookmark-target"               : "none | <uri> | <attr>",\n
+    "border"                        : "<border-width> || <border-style> || <color>",\n
+    "border-bottom"                 : "<border-width> || <border-style> || <color>",\n
+    "border-bottom-color"           : "<color> | inherit",\n
+    "border-bottom-left-radius"     :  "<x-one-radius>",\n
+    "border-bottom-right-radius"    :  "<x-one-radius>",\n
+    "border-bottom-style"           : "<border-style>",\n
+    "border-bottom-width"           : "<border-width>",\n
+    "border-collapse"               : "collapse | separate | inherit",\n
+    "border-color"                  : { multi: "<color> | inherit", max: 4 },\n
+    "border-image"                  : 1,\n
+    "border-image-outset"           : { multi: "<length> | <number>", max: 4 },\n
+    "border-image-repeat"           : { multi: "stretch | repeat | round", max: 2 },\n
+    "border-image-slice"            : function(expression) {\n
+\n
+        var valid   = false,\n
+            numeric = "<number> | <percentage>",\n
+            fill    = false,\n
+            count   = 0,\n
+            max     = 4,\n
+            part;\n
+\n
+        if (ValidationTypes.isAny(expression, "fill")) {\n
+            fill = true;\n
+            valid = true;\n
+        }\n
+\n
+        while (expression.hasNext() && count < max) {\n
+            valid = ValidationTypes.isAny(expression, numeric);\n
+            if (!valid) {\n
+                break;\n
+            }\n
+            count++;\n
+        }\n
+\n
+\n
+        if (!fill) {\n
+            ValidationTypes.isAny(expression, "fill");\n
+        } else {\n
+            valid = true;\n
+        }\n
+\n
+        if (expression.hasNext()) {\n
+            part = expression.next();\n
+            if (valid) {\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                throw new ValidationError("Expected ([<number> | <percentage>]{1,4} && fill?) but found \'" + part + "\'.", part.line, part.col);\n
+            }\n
+        }\n
+    },\n
+    "border-image-source"           : "<image> | none",\n
+    "border-image-width"            : { multi: "<length> | <percentage> | <number> | auto", max: 4 },\n
+    "border-left"                   : "<border-width> || <border-style> || <color>",\n
+    "border-left-color"             : "<color> | inherit",\n
+    "border-left-style"             : "<border-style>",\n
+    "border-left-width"             : "<border-width>",\n
+    "border-radius"                 : function(expression) {\n
+\n
+        var valid   = false,\n
+            simple = "<length> | <percentage> | inherit",\n
+            slash   = false,\n
+            fill    = false,\n
+            count   = 0,\n
+            max     = 8,\n
+            part;\n
+\n
+        while (expression.hasNext() && count < max) {\n
+            valid = ValidationTypes.isAny(expression, simple);\n
+            if (!valid) {\n
+\n
+                if (expression.peek() == "/" && count > 0 && !slash) {\n
+                    slash = true;\n
+                    max = count + 5;\n
+                    expression.next();\n
+                } else {\n
+                    break;\n
+                }\n
+            }\n
+            count++;\n
+        }\n
+\n
+        if (expression.hasNext()) {\n
+            part = expression.next();\n
+            if (valid) {\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                throw new ValidationError("Expected (<\'border-radius\'>) but found \'" + part + "\'.", part.line, part.col);\n
+            }\n
+        }\n
+    },\n
+    "border-right"                  : "<border-width> || <border-style> || <color>",\n
+    "border-right-color"            : "<color> | inherit",\n
+    "border-right-style"            : "<border-style>",\n
+    "border-right-width"            : "<border-width>",\n
+    "border-spacing"                : { multi: "<length> | inherit", max: 2 },\n
+    "border-style"                  : { multi: "<border-style>", max: 4 },\n
+    "border-top"                    : "<border-width> || <border-style> || <color>",\n
+    "border-top-color"              : "<color> | inherit",\n
+    "border-top-left-radius"        : "<x-one-radius>",\n
+    "border-top-right-radius"       : "<x-one-radius>",\n
+    "border-top-style"              : "<border-style>",\n
+    "border-top-width"              : "<border-width>",\n
+    "border-width"                  : { multi: "<border-width>", max: 4 },\n
+    "bottom"                        : "<margin-width> | inherit",\n
+    "box-align"                     : "start | end | center | baseline | stretch",        //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/\n
+    "box-decoration-break"          : "slice |clone",\n
+    "box-direction"                 : "normal | reverse | inherit",\n
+    "box-flex"                      : "<number>",\n
+    "box-flex-group"                : "<integer>",\n
+    "box-lines"                     : "single | multiple",\n
+    "box-ordinal-group"             : "<integer>",\n
+    "box-orient"                    : "horizontal | vertical | inline-axis | block-axis | inherit",\n
+    "box-pack"                      : "start | end | center | justify",\n
+    "box-shadow"                    : function (expression) {\n
+        var result      = false,\n
+            part;\n
+\n
+        if (!ValidationTypes.isAny(expression, "none")) {\n
+            Validation.multiProperty("<shadow>", expression, true, Infinity);\n
+        } else {\n
+            if (expression.hasNext()) {\n
+                part = expression.next();\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            }\n
+        }\n
+    },\n
+    "box-sizing"                    : "content-box | border-box | inherit",\n
+    "break-after"                   : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",\n
+    "break-before"                  : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",\n
+    "break-inside"                  : "auto | avoid | avoid-page | avoid-column",\n
+\n
+    //C\n
+    "caption-side"                  : "top | bottom | inherit",\n
+    "clear"                         : "none | right | left | both | inherit",\n
+    "clip"                          : 1,\n
+    "color"                         : "<color> | inherit",\n
+    "color-profile"                 : 1,\n
+    "column-count"                  : "<integer> | auto",                      //http://www.w3.org/TR/css3-multicol/\n
+    "column-fill"                   : "auto | balance",\n
+    "column-gap"                    : "<length> | normal",\n
+    "column-rule"                   : "<border-width> || <border-style> || <color>",\n
+    "column-rule-color"             : "<color>",\n
+    "column-rule-style"             : "<border-style>",\n
+    "column-rule-width"             : "<border-width>",\n
+    "column-span"                   : "none | all",\n
+    "column-width"                  : "<length> | auto",\n
+    "columns"                       : 1,\n
+    "content"                       : 1,\n
+    "counter-increment"             : 1,\n
+    "counter-reset"                 : 1,\n
+    "crop"                          : "<shape> | auto",\n
+    "cue"                           : "cue-after | cue-before | inherit",\n
+    "cue-after"                     : 1,\n
+    "cue-before"                    : 1,\n
+    "cursor"                        : 1,\n
+\n
+    //D\n
+    "direction"                     : "ltr | rtl | inherit",\n
+    "display"                       : "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit | -moz-box | -moz-inline-block | -moz-inline-box | -moz-inline-grid | -moz-inline-stack | -moz-inline-table | -moz-grid | -moz-grid-group | -moz-grid-line | -moz-groupbox | -moz-deck | -moz-popup | -moz-stack | -moz-marker | -webkit-box | -webkit-inline-box",\n
+    "dominant-baseline"             : 1,\n
+    "drop-initial-after-adjust"     : "central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>",\n
+    "drop-initial-after-align"      : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",\n
+    "drop-initial-before-adjust"    : "before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>",\n
+    "drop-initial-before-align"     : "caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",\n
+    "drop-initial-size"             : "auto | line | <length> | <percentage>",\n
+    "drop-initial-value"            : "initial | <integer>",\n
+\n
+    //E\n
+    "elevation"                     : "<angle> | below | level | above | higher | lower | inherit",\n
+    "empty-cells"                   : "show | hide | inherit",\n
+\n
+    //F\n
+    "filter"                        : 1,\n
+    "fit"                           : "fill | hidden | meet | slice",\n
+    "fit-position"                  : 1,\n
+    "float"                         : "left | right | none | inherit",\n
+    "float-offset"                  : 1,\n
+    "font"                          : 1,\n
+    "font-family"                   : 1,\n
+    "font-size"                     : "<absolute-size> | <relative-size> | <length> | <percentage> | inherit",\n
+    "font-size-adjust"              : "<number> | none | inherit",\n
+    "font-stretch"                  : "normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit",\n
+    "font-style"                    : "normal | italic | oblique | inherit",\n
+    "font-variant"                  : "normal | small-caps | inherit",\n
+    "font-weight"                   : "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit",\n
+\n
+    //G\n
+    "grid-cell-stacking"            : "columns | rows | layer",\n
+    "grid-column"                   : 1,\n
+    "grid-columns"                  : 1,\n
+    "grid-column-align"             : "start | end | center | stretch",\n
+    "grid-column-sizing"            : 1,\n
+    "grid-column-span"              : "<integer>",\n
+    "grid-flow"                     : "none | rows | columns",\n
+    "grid-layer"                    : "<integer>",\n
+    "grid-row"                      : 1,\n
+    "grid-rows"                     : 1,\n
+    "grid-row-align"                : "start | end | center | stretch",\n
+    "grid-row-span"                 : "<integer>",\n
+    "grid-row-sizing"               : 1,\n
+\n
+    //H\n
+    "hanging-punctuation"           : 1,\n
+    "height"                        : "<margin-width> | inherit",\n
+    "hyphenate-after"               : "<integer> | auto",\n
+    "hyphenate-before"              : "<integer> | auto",\n
+    "hyphenate-character"           : "<string> | auto",\n
+    "hyphenate-lines"               : "no-limit | <integer>",\n
+    "hyphenate-resource"            : 1,\n
+    "hyphens"                       : "none | manual | auto",\n
+\n
+    //I\n
+    "icon"                          : 1,\n
+    "image-orientation"             : "angle | auto",\n
+    "image-rendering"               : 1,\n
+    "image-resolution"              : 1,\n
+    "inline-box-align"              : "initial | last | <integer>",\n
+\n
+    //L\n
+    "left"                          : "<margin-width> | inherit",\n
+    "letter-spacing"                : "<length> | normal | inherit",\n
+    "line-height"                   : "<number> | <length> | <percentage> | normal | inherit",\n
+    "line-break"                    : "auto | loose | normal | strict",\n
+    "line-stacking"                 : 1,\n
+    "line-stacking-ruby"            : "exclude-ruby | include-ruby",\n
+    "line-stacking-shift"           : "consider-shifts | disregard-shifts",\n
+    "line-stacking-strategy"        : "inline-line-height | block-line-height | max-height | grid-height",\n
+    "list-style"                    : 1,\n
+    "list-style-image"              : "<uri> | none | inherit",\n
+    "list-style-position"           : "inside | outside | inherit",\n
+    "list-style-type"               : "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit",\n
+\n
+    //M\n
+    "margin"                        : { multi: "<margin-width> | inherit", max: 4 },\n
+    "margin-bottom"                 : "<margin-width> | inherit",\n
+    "margin-left"                   : "<margin-width> | inherit",\n
+    "margin-right"                  : "<margin-width> | inherit",\n
+    "margin-top"                    : "<margin-width> | inherit",\n
+    "mark"                          : 1,\n
+    "mark-after"                    : 1,\n
+    "mark-before"                   : 1,\n
+    "marks"                         : 1,\n
+    "marquee-direction"             : 1,\n
+    "marquee-play-count"            : 1,\n
+    "marquee-speed"                 : 1,\n
+    "marquee-style"                 : 1,\n
+    "max-height"                    : "<length> | <percentage> | none | inherit",\n
+    "max-width"                     : "<length> | <percentage> | none | inherit",\n
+    "min-height"                    : "<length> | <percentage> | inherit",\n
+    "min-width"                     : "<length> | <percentage> | inherit",\n
+    "move-to"                       : 1,\n
+\n
+    //N\n
+    "nav-down"                      : 1,\n
+    "nav-index"                     : 1,\n
+    "nav-left"                      : 1,\n
+    "nav-right"                     : 1,\n
+    "nav-up"                        : 1,\n
+\n
+    //O\n
+    "opacity"                       : "<number> | inherit",\n
+    "orphans"                       : "<integer> | inherit",\n
+    "outline"                       : 1,\n
+    "outline-color"                 : "<color> | invert | inherit",\n
+    "outline-offset"                : 1,\n
+    "outline-style"                 : "<border-style> | inherit",\n
+    "outline-width"                 : "<border-width> | inherit",\n
+    "overflow"                      : "visible | hidden | scroll | auto | inherit",\n
+    "overflow-style"                : 1,\n
+    "overflow-x"                    : 1,\n
+    "overflow-y"                    : 1,\n
+\n
+    //P\n
+    "padding"                       : { multi: "<padding-width> | inherit", max: 4 },\n
+    "padding-bottom"                : "<padding-width> | inherit",\n
+    "padding-left"                  : "<padding-width> | inherit",\n
+    "padding-right"                 : "<padding-width> | inherit",\n
+    "padding-top"                   : "<padding-width> | inherit",\n
+    "page"                          : 1,\n
+    "page-break-after"              : "auto | always | avoid | left | right | inherit",\n
+    "page-break-before"             : "auto | always | avoid | left | right | inherit",\n
+    "page-break-inside"             : "auto | avoid | inherit",\n
+    "page-policy"                   : 1,\n
+    "pause"                         : 1,\n
+    "pause-after"                   : 1,\n
+    "pause-before"                  : 1,\n
+    "perspective"                   : 1,\n
+    "perspective-origin"            : 1,\n
+    "phonemes"                      : 1,\n
+    "pitch"                         : 1,\n
+    "pitch-range"                   : 1,\n
+    "play-during"                   : 1,\n
+    "pointer-events"                : "auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit",\n
+    "position"                      : "static | relative | absolute | fixed | inherit",\n
+    "presentation-level"            : 1,\n
+    "punctuation-trim"              : 1,\n
+\n
+    //Q\n
+    "quotes"                        : 1,\n
+\n
+    //R\n
+    "rendering-intent"              : 1,\n
+    "resize"                        : 1,\n
+    "rest"                          : 1,\n
+    "rest-after"                    : 1,\n
+    "rest-before"                   : 1,\n
+    "richness"                      : 1,\n
+    "right"                         : "<margin-width> | inherit",\n
+    "rotation"                      : 1,\n
+    "rotation-point"                : 1,\n
+    "ruby-align"                    : 1,\n
+    "ruby-overhang"                 : 1,\n
+    "ruby-position"                 : 1,\n
+    "ruby-span"                     : 1,\n
+\n
+    //S\n
+    "size"                          : 1,\n
+    "speak"                         : "normal | none | spell-out | inherit",\n
+    "speak-header"                  : "once | always | inherit",\n
+    "speak-numeral"                 : "digits | continuous | inherit",\n
+    "speak-punctuation"             : "code | none | inherit",\n
+    "speech-rate"                   : 1,\n
+    "src"                           : 1,\n
+    "stress"                        : 1,\n
+    "string-set"                    : 1,\n
+\n
+    "table-layout"                  : "auto | fixed | inherit",\n
+    "tab-size"                      : "<integer> | <length>",\n
+    "target"                        : 1,\n
+    "target-name"                   : 1,\n
+    "target-new"                    : 1,\n
+    "target-position"               : 1,\n
+    "text-align"                    : "left | right | center | justify | inherit" ,\n
+    "text-align-last"               : 1,\n
+    "text-decoration"               : 1,\n
+    "text-emphasis"                 : 1,\n
+    "text-height"                   : 1,\n
+    "text-indent"                   : "<length> | <percentage> | inherit",\n
+    "text-justify"                  : "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida",\n
+    "text-outline"                  : 1,\n
+    "text-overflow"                 : 1,\n
+    "text-rendering"                : "auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit",\n
+    "text-shadow"                   : 1,\n
+    "text-transform"                : "capitalize | uppercase | lowercase | none | inherit",\n
+    "text-wrap"                     : "normal | none | avoid",\n
+    "top"                           : "<margin-width> | inherit",\n
+    "transform"                     : 1,\n
+    "transform-origin"              : 1,\n
+    "transform-style"               : 1,\n
+    "transition"                    : 1,\n
+    "transition-delay"              : 1,\n
+    "transition-duration"           : 1,\n
+    "transition-property"           : 1,\n
+    "transition-timing-function"    : 1,\n
+\n
+    //U\n
+    "unicode-bidi"                  : "normal | embed | bidi-override | inherit",\n
+    "user-modify"                   : "read-only | read-write | write-only | inherit",\n
+    "user-select"                   : "none | text | toggle | element | elements | all | inherit",\n
+\n
+    //V\n
+    "vertical-align"                : "auto | use-script | baseline | sub | super | top | text-top | central | middle | bottom | text-bottom | <percentage> | <length>",\n
+    "visibility"                    : "visible | hidden | collapse | inherit",\n
+    "voice-balance"                 : 1,\n
+    "voice-duration"                : 1,\n
+    "voice-family"                  : 1,\n
+    "voice-pitch"                   : 1,\n
+    "voice-pitch-range"             : 1,\n
+    "voice-rate"                    : 1,\n
+    "voice-stress"                  : 1,\n
+    "voice-volume"                  : 1,\n
+    "volume"                        : 1,\n
+\n
+    //W\n
+    "white-space"                   : "normal | pre | nowrap | pre-wrap | pre-line | inherit | -pre-wrap | -o-pre-wrap | -moz-pre-wrap | -hp-pre-wrap", //http://perishablepress.com/wrapping-content/\n
+    "white-space-collapse"          : 1,\n
+    "widows"                        : "<integer> | inherit",\n
+    "width"                         : "<length> | <percentage> | auto | inherit" ,\n
+    "word-break"                    : "normal | keep-all | break-all",\n
+    "word-spacing"                  : "<length> | normal | inherit",\n
+    "word-wrap"                     : 1,\n
+\n
+    //Z\n
+    "z-index"                       : "<integer> | auto | inherit",\n
+    "zoom"                          : "<number> | <percentage> | normal"\n
+};\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a selector combinator (whitespace, +, >).\n
+ * @namespace parserlib.css\n
+ * @class PropertyName\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {String} text The text representation of the unit.\n
+ * @param {String} hack The type of IE hack applied ("*", "_", or null).\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function PropertyName(text, hack, line, col){\n
+\n
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);\n
+\n
+    /**\n
+     * The type of IE hack applied ("*", "_", or null).\n
+     * @type String\n
+     * @property hack\n
+     */\n
+    this.hack = hack;\n
+\n
+}\n
+\n
+PropertyName.prototype = new SyntaxUnit();\n
+PropertyName.prototype.constructor = PropertyName;\n
+PropertyName.prototype.toString = function(){\n
+    return (this.hack ? this.hack : "") + this.text;\n
+};\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a single part of a CSS property value, meaning that it represents\n
+ * just everything single part between ":" and ";". If there are multiple values\n
+ * separated by commas, this type represents just one of the values.\n
+ * @param {String[]} parts An array of value parts making up this value.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ * @namespace parserlib.css\n
+ * @class PropertyValue\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ */\n
+function PropertyValue(parts, line, col){\n
+\n
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE);\n
+\n
+    /**\n
+     * The parts that make up the selector.\n
+     * @type Array\n
+     * @property parts\n
+     */\n
+    this.parts = parts;\n
+\n
+}\n
+\n
+PropertyValue.prototype = new SyntaxUnit();\n
+PropertyValue.prototype.constructor = PropertyValue;\n
+\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * A utility class that allows for easy iteration over the various parts of a\n
+ * property value.\n
+ * @param {parserlib.css.PropertyValue} value The property value to iterate over.\n
+ * @namespace parserlib.css\n
+ * @class PropertyValueIterator\n
+ * @constructor\n
+ */\n
+function PropertyValueIterator(value){\n
+\n
+    /**\n
+     * Iterator value\n
+     * @type int\n
+     * @property _i\n
+     * @private\n
+     */\n
+    this._i = 0;\n
+\n
+    /**\n
+     * The parts that make up the value.\n
+     * @type Array\n
+     * @property _parts\n
+     * @private\n
+     */\n
+    this._parts = value.parts;\n
+\n
+    /**\n
+     * Keeps track of bookmarks along the way.\n
+     * @type Array\n
+     * @property _marks\n
+     * @private\n
+     */\n
+    this._marks = [];\n
+\n
+    /**\n
+     * Holds the original property value.\n
+     * @type parserlib.css.PropertyValue\n
+     * @property value\n
+     */\n
+    this.value = value;\n
+\n
+}\n
+\n
+/**\n
+ * Returns the total number of parts in the value.\n
+ * @return {int} The total number of parts in the value.\n
+ * @method count\n
+ */\n
+PropertyValueIterator.prototype.count = function(){\n
+    return this._parts.length;\n
+};\n
+\n
+/**\n
+ * Indicates if the iterator is positioned at the first item.\n
+ * @return {Boolean} True if positioned at first item, false if not.\n
+ * @method isFirst\n
+ */\n
+PropertyValueIterator.prototype.isFirst = function(){\n
+    return this._i === 0;\n
+};\n
+\n
+/**\n
+ * Indicates if there are more parts of the property value.\n
+ * @return {Boolean} True if there are more parts, false if not.\n
+ * @method hasNext\n
+ */\n
+PropertyValueIterator.prototype.hasNext = function(){\n
+    return (this._i < this._parts.length);\n
+};\n
+\n
+/**\n
+ * Marks the current spot in the iteration so it can be restored to\n
+ * later on.\n
+ * @return {void}\n
+ * @method mark\n
+ */\n
+PropertyValueIterator.prototype.mark = function(){\n
+    this._marks.push(this._i);\n
+};\n
+\n
+/**\n
+ * Returns the next part of the property value or null if there is no next\n
+ * part. Does not move the internal counter forward.\n
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n
+ * part.\n
+ * @method peek\n
+ */\n
+PropertyValueIterator.prototype.peek = function(count){\n
+    return this.hasNext() ? this._parts[this._i + (count || 0)] : null;\n
+};\n
+\n
+/**\n
+ * Returns the next part of the property value or null if there is no next\n
+ * part.\n
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n
+ * part.\n
+ * @method next\n
+ */\n
+PropertyValueIterator.prototype.next = function(){\n
+    return this.hasNext() ? this._parts[this._i++] : null;\n
+};\n
+\n
+/**\n
+ * Returns the previous part of the property value or null if there is no\n
+ * previous part.\n
+ * @return {parserlib.css.PropertyValuePart} The previous part of the\n
+ * property value or null if there is no next part.\n
+ * @method previous\n
+ */\n
+PropertyValueIterator.prototype.previous = function(){\n
+    return this._i > 0 ? this._parts[--this._i] : null;\n
+};\n
+\n
+/**\n
+ * Restores the last saved bookmark.\n
+ * @return {void}\n
+ * @method restore\n
+ */\n
+PropertyValueIterator.prototype.restore = function(){\n
+    if (this._marks.length){\n
+        this._i = this._marks.pop();\n
+    }\n
+};\n
+\n
+\n
+/*global SyntaxUnit, Parser, Colors*/\n
+/**\n
+ * Represents a single part of a CSS property value, meaning that it represents\n
+ * just one part of the data between ":" and ";".\n
+ * @param {String} text The text representation of the unit.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ * @namespace parserlib.css\n
+ * @class PropertyValuePart\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ */\n
+function PropertyValuePart(text, line, col){\n
+\n
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE);\n
+\n
+    /**\n
+     * Indicates the type of value unit.\n
+     * @type String\n
+     * @property type\n
+     */\n
+    this.type = "unknown";\n
+\n
+    //figure out what type of data it is\n
+\n
+    var temp;\n
+\n
+    //it is a measurement?\n
+    if (/^([+\\-]?[\\d\\.]+)([a-z]+)$/i.test(text)){  //dimension\n
+        this.type = "dimension";\n
+        this.value = +RegExp.$1;\n
+        this.units = RegExp.$2;\n
+\n
+        //try to narrow down\n
+        switch(this.units.toLowerCase()){\n
+\n
+            case "em":\n
+            case "rem":\n
+            case "ex":\n
+            case "px":\n
+            case "cm":\n
+            case "mm":\n
+            case "in":\n
+            case "pt":\n
+            case "pc":\n
+            case "ch":\n
+            case "vh":\n
+            case "vw":\n
+            case "vm":\n
+                this.type = "length";\n
+                break;\n
+\n
+            case "deg":\n
+            case "rad":\n
+            case "grad":\n
+                this.type = "angle";\n
+                break;\n
+\n
+            case "ms":\n
+            case "s":\n
+                this.type = "time";\n
+                break;\n
+\n
+            case "hz":\n
+            case "khz":\n
+                this.type = "frequency";\n
+                break;\n
+\n
+            case "dpi":\n
+            case "dpcm":\n
+                this.type = "resolution";\n
+                break;\n
+\n
+            //default\n
+\n
+        }\n
+\n
+    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n
+        this.type = "percentage";\n
+        this.value = +RegExp.$1;\n
+    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n
+        this.type = "percentage";\n
+        this.value = +RegExp.$1;\n
+    } else if (/^([+\\-]?\\d+)$/i.test(text)){  //integer\n
+        this.type = "integer";\n
+        this.value = +RegExp.$1;\n
+    } else if (/^([+\\-]?[\\d\\.]+)$/i.test(text)){  //number\n
+        this.type = "number";\n
+        this.value = +RegExp.$1;\n
+\n
+    } else if (/^#([a-f0-9]{3,6})/i.test(text)){  //hexcolor\n
+        this.type = "color";\n
+        temp = RegExp.$1;\n
+        if (temp.length == 3){\n
+            this.red    = parseInt(temp.charAt(0)+temp.charAt(0),16);\n
+            this.green  = parseInt(temp.charAt(1)+temp.charAt(1),16);\n
+            this.blue   = parseInt(temp.charAt(2)+temp.charAt(2),16);\n
+        } else {\n
+            this.red    = parseInt(temp.substring(0,2),16);\n
+            this.green  = parseInt(temp.substring(2,4),16);\n
+            this.blue   = parseInt(temp.substring(4,6),16);\n
+        }\n
+    } else if (/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/i.test(text)){ //rgb() color with absolute numbers\n
+        this.type   = "color";\n
+        this.red    = +RegExp.$1;\n
+        this.green  = +RegExp.$2;\n
+        this.blue   = +RegExp.$3;\n
+    } else if (/^rgb\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //rgb() color with percentages\n
+        this.type   = "color";\n
+        this.red    = +RegExp.$1 * 255 / 100;\n
+        this.green  = +RegExp.$2 * 255 / 100;\n
+        this.blue   = +RegExp.$3 * 255 / 100;\n
+    } else if (/^rgba\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with absolute numbers\n
+        this.type   = "color";\n
+        this.red    = +RegExp.$1;\n
+        this.green  = +RegExp.$2;\n
+        this.blue   = +RegExp.$3;\n
+        this.alpha  = +RegExp.$4;\n
+    } else if (/^rgba\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with percentages\n
+        this.type   = "color";\n
+        this.red    = +RegExp.$1 * 255 / 100;\n
+        this.green  = +RegExp.$2 * 255 / 100;\n
+        this.blue   = +RegExp.$3 * 255 / 100;\n
+        this.alpha  = +RegExp.$4;\n
+    } else if (/^hsl\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //hsl()\n
+        this.type   = "color";\n
+        this.hue    = +RegExp.$1;\n
+        this.saturation = +RegExp.$2 / 100;\n
+        this.lightness  = +RegExp.$3 / 100;\n
+    } else if (/^hsla\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //hsla() color with percentages\n
+        this.type   = "color";\n
+        this.hue    = +RegExp.$1;\n
+        this.saturation = +RegExp.$2 / 100;\n
+        this.lightness  = +RegExp.$3 / 100;\n
+        this.alpha  = +RegExp.$4;\n
+    } else if (/^url\\(["\']?([^\\)"\']+)["\']?\\)/i.test(text)){ //URI\n
+        this.type   = "uri";\n
+        this.uri    = RegExp.$1;\n
+    } else if (/^([^\\(]+)\\(/i.test(text)){\n
+        this.type   = "function";\n
+        this.name   = RegExp.$1;\n
+        this.value  = text;\n
+    } else if (/^["\'][^"\']*["\']/.test(text)){    //string\n
+        this.type   = "string";\n
+        this.value  = eval(text);\n
+    } else if (Colors[text.toLowerCase()]){  //named color\n
+        this.type   = "color";\n
+        temp        = Colors[text.toLowerCase()].substring(1);\n
+        this.red    = parseInt(temp.substring(0,2),16);\n
+        this.green  = parseInt(temp.substring(2,4),16);\n
+        this.blue   = parseInt(temp.substring(4,6),16);\n
+    } else if (/^[\\,\\/]$/.test(text)){\n
+        this.type   = "operator";\n
+        this.value  = text;\n
+    } else if (/^[a-z\\-\\u0080-\\uFFFF][a-z0-9\\-\\u0080-\\uFFFF]*$/i.test(text)){\n
+        this.type   = "identifier";\n
+        this.value  = text;\n
+    }\n
+\n
+}\n
+\n
+PropertyValuePart.prototype = new SyntaxUnit();\n
+PropertyValuePart.prototype.constructor = PropertyValuePart;\n
+\n
+/**\n
+ * Create a new syntax unit based solely on the given token.\n
+ * Convenience method for creating a new syntax unit when\n
+ * it represents a single token instead of multiple.\n
+ * @param {Object} token The token object to represent.\n
+ * @return {parserlib.css.PropertyValuePart} The object representing the token.\n
+ * @static\n
+ * @method fromToken\n
+ */\n
+PropertyValuePart.fromToken = function(token){\n
+    return new PropertyValuePart(token.value, token.startLine, token.startCol);\n
+};\n
+var Pseudos = {\n
+    ":first-letter": 1,\n
+    ":first-line":   1,\n
+    ":before":       1,\n
+    ":after":        1\n
+};\n
+\n
+Pseudos.ELEMENT = 1;\n
+Pseudos.CLASS = 2;\n
+\n
+Pseudos.isElement = function(pseudo){\n
+    return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT;\n
+};\n
+/*global SyntaxUnit, Parser, Specificity*/\n
+/**\n
+ * Represents an entire single selector, including all parts but not\n
+ * including multiple selectors (those separated by commas).\n
+ * @namespace parserlib.css\n
+ * @class Selector\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {Array} parts Array of selectors parts making up this selector.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function Selector(parts, line, col){\n
+\n
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE);\n
+\n
+    /**\n
+     * The parts that make up the selector.\n
+     * @type Array\n
+     * @property parts\n
+     */\n
+    this.parts = parts;\n
+\n
+    /**\n
+     * The specificity of the selector.\n
+     * @type parserlib.css.Specificity\n
+     * @property specificity\n
+     */\n
+    this.specificity = Specificity.calculate(this);\n
+\n
+}\n
+\n
+Selector.prototype = new SyntaxUnit();\n
+Selector.prototype.constructor = Selector;\n
+\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a single part of a selector string, meaning a single set of\n
+ * element name and modifiers. This does not include combinators such as\n
+ * spaces, +, >, etc.\n
+ * @namespace parserlib.css\n
+ * @class SelectorPart\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {String} elementName The element name in the selector or null\n
+ *      if there is no element name.\n
+ * @param {Array} modifiers Array of individual modifiers for the element.\n
+ *      May be empty if there are none.\n
+ * @param {String} text The text representation of the unit.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function SelectorPart(elementName, modifiers, text, line, col){\n
+\n
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);\n
+\n
+    /**\n
+     * The tag name of the element to which this part\n
+     * of the selector affects.\n
+     * @type String\n
+     * @property elementName\n
+     */\n
+    this.elementName = elementName;\n
+\n
+    /**\n
+     * The parts that come after the element name, such as class names, IDs,\n
+     * pseudo classes/elements, etc.\n
+     * @type Array\n
+     * @property modifiers\n
+     */\n
+    this.modifiers = modifiers;\n
+\n
+}\n
+\n
+SelectorPart.prototype = new SyntaxUnit();\n
+SelectorPart.prototype.constructor = SelectorPart;\n
+\n
+\n
+/*global SyntaxUnit, Parser*/\n
+/**\n
+ * Represents a selector modifier string, meaning a class name, element name,\n
+ * element ID, pseudo rule, etc.\n
+ * @namespace parserlib.css\n
+ * @class SelectorSubPart\n
+ * @extends parserlib.util.SyntaxUnit\n
+ * @constructor\n
+ * @param {String} text The text representation of the unit.\n
+ * @param {String} type The type of selector modifier.\n
+ * @param {int} line The line of text on which the unit resides.\n
+ * @param {int} col The column of text on which the unit resides.\n
+ */\n
+function SelectorSubPart(text, type, line, col){\n
+\n
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);\n
+\n
+    /**\n
+     * The type of modifier.\n
+     * @type String\n
+     * @property type\n
+     */\n
+    this.type = type;\n
+\n
+    /**\n
+     * Some subparts have arguments, this represents them.\n
+     * @type Array\n
+     * @property args\n
+     */\n
+    this.args = [];\n
+\n
+}\n
+\n
+SelectorSubPart.prototype = new SyntaxUnit();\n
+SelectorSubPart.prototype.constructor = SelectorSubPart;\n
+\n
+\n
+/*global Pseudos, SelectorPart*/\n
+/**\n
+ * Represents a selector\'s specificity.\n
+ * @namespace parserlib.css\n
+ * @class Specificity\n
+ * @constructor\n
+ * @param {int} a Should be 1 for inline styles, zero for stylesheet styles\n
+ * @param {int} b Number of ID selectors\n
+ * @param {int} c Number of classes and pseudo classes\n
+ * @param {int} d Number of element names and pseudo elements\n
+ */\n
+function Specificity(a, b, c, d){\n
+    this.a = a;\n
+    this.b = b;\n
+    this.c = c;\n
+    this.d = d;\n
+}\n
+\n
+Specificity.prototype = {\n
+    constructor: Specificity,\n
+\n
+    /**\n
+     * Compare this specificity to another.\n
+     * @param {Specificity} other The other specificity to compare to.\n
+     * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal.\n
+     * @method compare\n
+     */\n
+    compare: function(other){\n
+        var comps = ["a", "b", "c", "d"],\n
+            i, len;\n
+\n
+        for (i=0, len=comps.length; i < len; i++){\n
+            if (this[comps[i]] < other[comps[i]]){\n
+                return -1;\n
+            } else if (this[comps[i]] > other[comps[i]]){\n
+                return 1;\n
+            }\n
+        }\n
+\n
+        return 0;\n
+    },\n
+\n
+    /**\n
+     * Creates a numeric value for the specificity.\n
+     * @return {int} The numeric value for the specificity.\n
+     * @method valueOf\n
+     */\n
+    valueOf: function(){\n
+        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;\n
+    },\n
+\n
+    /**\n
+     * Returns a string representation for specificity.\n
+     * @return {String} The string representation of specificity.\n
+     * @method toString\n
+     */\n
+    toString: function(){\n
+        return this.a + "," + this.b + "," + this.c + "," + this.d;\n
+    }\n
+\n
+};\n
+\n
+/**\n
+ * Calculates the specificity of the given selector.\n
+ * @param {parserlib.css.Selector} The selector to calculate specificity for.\n
+ * @return {parserlib.css.Specificity} The specificity of the selector.\n
+ * @static\n
+ * @method calculate\n
+ */\n
+Specificity.calculate = function(selector){\n
+\n
+    var i, len,\n
+        part,\n
+        b=0, c=0, d=0;\n
+\n
+    function updateValues(part){\n
+\n
+        var i, j, len, num,\n
+            elementName = part.elementName ? part.elementName.text : "",\n
+            modifier;\n
+\n
+        if (elementName && elementName.charAt(elementName.length-1) != "*") {\n
+            d++;\n
+        }\n
+\n
+        for (i=0, len=part.modifiers.length; i < len; i++){\n
+            modifier = part.modifiers[i];\n
+            switch(modifier.type){\n
+                case "class":\n
+                case "attribute":\n
+                    c++;\n
+                    break;\n
+\n
+                case "id":\n
+                    b++;\n
+                    break;\n
+\n
+                case "pseudo":\n
+                    if (Pseudos.isElement(modifier.text)){\n
+                        d++;\n
+                    } else {\n
+                        c++;\n
+                    }\n
+                    break;\n
+\n
+                case "not":\n
+                    for (j=0, num=modifier.args.length; j < num; j++){\n
+                        updateValues(modifier.args[j]);\n
+                    }\n
+            }\n
+         }\n
+    }\n
+\n
+    for (i=0, len=selector.parts.length; i < len; i++){\n
+        part = selector.parts[i];\n
+\n
+        if (part instanceof SelectorPart){\n
+            updateValues(part);\n
+        }\n
+    }\n
+\n
+    return new Specificity(0, b, c, d);\n
+};\n
+\n
+/*global Tokens, TokenStreamBase*/\n
+\n
+var h = /^[0-9a-fA-F]$/,\n
+    nonascii = /^[\\u0080-\\uFFFF]$/,\n
+    nl = /\\n|\\r\\n|\\r|\\f/;\n
+\n
+//-----------------------------------------------------------------------------\n
+// Helper functions\n
+//-----------------------------------------------------------------------------\n
+\n
+\n
+function isHexDigit(c){\n
+    return c !== null && h.test(c);\n
+}\n
+\n
+function isDigit(c){\n
+    return c !== null && /\\d/.test(c);\n
+}\n
+\n
+function isWhitespace(c){\n
+    return c !== null && /\\s/.test(c);\n
+}\n
+\n
+function isNewLine(c){\n
+    return c !== null && nl.test(c);\n
+}\n
+\n
+function isNameStart(c){\n
+    return c !== null && (/[a-z_\\u0080-\\uFFFF\\\\]/i.test(c));\n
+}\n
+\n
+function isNameChar(c){\n
+    return c !== null && (isNameStart(c) || /[0-9\\-\\\\]/.test(c));\n
+}\n
+\n
+function isIdentStart(c){\n
+    return c !== null && (isNameStart(c) || /\\-\\\\/.test(c));\n
+}\n
+\n
+function mix(receiver, supplier){\n
+    for (var prop in supplier){\n
+        if (supplier.hasOwnProperty(prop)){\n
+            receiver[prop] = supplier[prop];\n
+        }\n
+    }\n
+    return receiver;\n
+}\n
+\n
+//-----------------------------------------------------------------------------\n
+// CSS Token Stream\n
+//-----------------------------------------------------------------------------\n
+\n
+\n
+/**\n
+ * A token stream that produces CSS tokens.\n
+ * @param {String|Reader} input The source of text to tokenize.\n
+ * @constructor\n
+ * @class TokenStream\n
+ * @namespace parserlib.css\n
+ */\n
+function TokenStream(input){\n
+    TokenStreamBase.call(this, input, Tokens);\n
+}\n
+\n
+TokenStream.prototype = mix(new TokenStreamBase(), {\n
+\n
+    /**\n
+     * Overrides the TokenStreamBase method of the same name\n
+     * to produce CSS tokens.\n
+     * @param {variant} channel The name of the channel to use\n
+     *      for the next token.\n
+     * @return {Object} A token object representing the next token.\n
+     * @method _getToken\n
+     * @private\n
+     */\n
+    _getToken: function(channel){\n
+\n
+        var c,\n
+            reader = this._reader,\n
+            token   = null,\n
+            startLine   = reader.getLine(),\n
+            startCol    = reader.getCol();\n
+\n
+        c = reader.read();\n
+\n
+\n
+        while(c){\n
+            switch(c){\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - COMMENT\n
+                 * - SLASH\n
+                 * - CHAR\n
+                 */\n
+                case "/":\n
+\n
+                    if(reader.peek() == "*"){\n
+                        token = this.commentToken(c, startLine, startCol);\n
+                    } else {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - DASHMATCH\n
+                 * - INCLUDES\n
+                 * - PREFIXMATCH\n
+                 * - SUFFIXMATCH\n
+                 * - SUBSTRINGMATCH\n
+                 * - CHAR\n
+                 */\n
+                case "|":\n
+                case "~":\n
+                case "^":\n
+                case "$":\n
+                case "*":\n
+                    if(reader.peek() == "="){\n
+                        token = this.comparisonToken(c, startLine, startCol);\n
+                    } else {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - STRING\n
+                 * - INVALID\n
+                 */\n
+                case "\\"":\n
+                case "\'":\n
+                    token = this.stringToken(c, startLine, startCol);\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - HASH\n
+                 * - CHAR\n
+                 */\n
+                case "#":\n
+                    if (isNameChar(reader.peek())){\n
+                        token = this.hashToken(c, startLine, startCol);\n
+                    } else {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - DOT\n
+                 * - NUMBER\n
+                 * - DIMENSION\n
+                 * - PERCENTAGE\n
+                 */\n
+                case ".":\n
+                    if (isDigit(reader.peek())){\n
+                        token = this.numberToken(c, startLine, startCol);\n
+                    } else {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - CDC\n
+                 * - MINUS\n
+                 * - NUMBER\n
+                 * - DIMENSION\n
+                 * - PERCENTAGE\n
+                 */\n
+                case "-":\n
+                    if (reader.peek() == "-"){  //could be closing HTML-style comment\n
+                        token = this.htmlCommentEndToken(c, startLine, startCol);\n
+                    } else if (isNameStart(reader.peek())){\n
+                        token = this.identOrFunctionToken(c, startLine, startCol);\n
+                    } else {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - IMPORTANT_SYM\n
+                 * - CHAR\n
+                 */\n
+                case "!":\n
+                    token = this.importantToken(c, startLine, startCol);\n
+                    break;\n
+\n
+                /*\n
+                 * Any at-keyword or CHAR\n
+                 */\n
+                case "@":\n
+                    token = this.atRuleToken(c, startLine, startCol);\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - NOT\n
+                 * - CHAR\n
+                 */\n
+                case ":":\n
+                    token = this.notToken(c, startLine, startCol);\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - CDO\n
+                 * - CHAR\n
+                 */\n
+                case "<":\n
+                    token = this.htmlCommentStartToken(c, startLine, startCol);\n
+                    break;\n
+\n
+                /*\n
+                 * Potential tokens:\n
+                 * - UNICODE_RANGE\n
+                 * - URL\n
+                 * - CHAR\n
+                 */\n
+                case "U":\n
+                case "u":\n
+                    if (reader.peek() == "+"){\n
+                        token = this.unicodeRangeToken(c, startLine, startCol);\n
+                        break;\n
+                    }\n
+                    /* falls through */\n
+                default:\n
+\n
+                    /*\n
+                     * Potential tokens:\n
+                     * - NUMBER\n
+                     * - DIMENSION\n
+                     * - LENGTH\n
+                     * - FREQ\n
+                     * - TIME\n
+                     * - EMS\n
+                     * - EXS\n
+                     * - ANGLE\n
+                     */\n
+                    if (isDigit(c)){\n
+                        token = this.numberToken(c, startLine, startCol);\n
+                    } else\n
+\n
+                    /*\n
+                     * Potential tokens:\n
+                     * - S\n
+                     */\n
+                    if (isWhitespace(c)){\n
+                        token = this.whitespaceToken(c, startLine, startCol);\n
+                    } else\n
+\n
+                    /*\n
+                     * Potential tokens:\n
+                     * - IDENT\n
+                     */\n
+                    if (isIdentStart(c)){\n
+                        token = this.identOrFunctionToken(c, startLine, startCol);\n
+                    } else\n
+\n
+                    /*\n
+                     * Potential tokens:\n
+                     * - CHAR\n
+                     * - PLUS\n
+                     */\n
+                    {\n
+                        token = this.charToken(c, startLine, startCol);\n
+                    }\n
+\n
+\n
+\n
+\n
+\n
+\n
+            }\n
+\n
+            //make sure this token is wanted\n
+            //TODO: check channel\n
+            break;\n
+        }\n
+\n
+        if (!token && c === null){\n
+            token = this.createToken(Tokens.EOF,null,startLine,startCol);\n
+        }\n
+\n
+        return token;\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Methods to create tokens\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Produces a token based on available data and the current\n
+     * reader position information. This method is called by other\n
+     * private methods to create tokens and is never called directly.\n
+     * @param {int} tt The token type.\n
+     * @param {String} value The text value of the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @param {Object} options (Optional) Specifies a channel property\n
+     *      to indicate that a different channel should be scanned\n
+     *      and/or a hide property indicating that the token should\n
+     *      be hidden.\n
+     * @return {Object} A token object.\n
+     * @method createToken\n
+     */\n
+    createToken: function(tt, value, startLine, startCol, options){\n
+        var reader = this._reader;\n
+        options = options || {};\n
+\n
+        return {\n
+            value:      value,\n
+            type:       tt,\n
+            channel:    options.channel,\n
+            hide:       options.hide || false,\n
+            startLine:  startLine,\n
+            startCol:   startCol,\n
+            endLine:    reader.getLine(),\n
+            endCol:     reader.getCol()\n
+        };\n
+    },\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Methods to create specific tokens\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Produces a token for any at-rule. If the at-rule is unknown, then\n
+     * the token is for a single "@" character.\n
+     * @param {String} first The first character for the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method atRuleToken\n
+     */\n
+    atRuleToken: function(first, startLine, startCol){\n
+        var rule    = first,\n
+            reader  = this._reader,\n
+            tt      = Tokens.CHAR,\n
+            valid   = false,\n
+            ident,\n
+            c;\n
+\n
+        /*\n
+         * First, mark where we are. There are only four @ rules,\n
+         * so anything else is really just an invalid token.\n
+         * Basically, if this doesn\'t match one of the known @\n
+         * rules, just return \'@\' as an unknown token and allow\n
+         * parsing to continue after that point.\n
+         */\n
+        reader.mark();\n
+\n
+        //try to find the at-keyword\n
+        ident = this.readName();\n
+        rule = first + ident;\n
+        tt = Tokens.type(rule.toLowerCase());\n
+\n
+        //if it\'s not valid, use the first character only and reset the reader\n
+        if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){\n
+            if (rule.length > 1){\n
+                tt = Tokens.UNKNOWN_SYM;\n
+            } else {\n
+                tt = Tokens.CHAR;\n
+                rule = first;\n
+                reader.reset();\n
+            }\n
+        }\n
+\n
+        return this.createToken(tt, rule, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a character token based on the given character\n
+     * and location in the stream. If there\'s a special (non-standard)\n
+     * token name, this is used; otherwise CHAR is used.\n
+     * @param {String} c The character for the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method charToken\n
+     */\n
+    charToken: function(c, startLine, startCol){\n
+        var tt = Tokens.type(c);\n
+\n
+        if (tt == -1){\n
+            tt = Tokens.CHAR;\n
+        }\n
+\n
+        return this.createToken(tt, c, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a character token based on the given character\n
+     * and location in the stream. If there\'s a special (non-standard)\n
+     * token name, this is used; otherwise CHAR is used.\n
+     * @param {String} first The first character for the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method commentToken\n
+     */\n
+    commentToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            comment = this.readComment(first);\n
+\n
+        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a comparison token based on the given character\n
+     * and location in the stream. The next character must be\n
+     * read and is already known to be an equals sign.\n
+     * @param {String} c The character for the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method comparisonToken\n
+     */\n
+    comparisonToken: function(c, startLine, startCol){\n
+        var reader  = this._reader,\n
+            comparison  = c + reader.read(),\n
+            tt      = Tokens.type(comparison) || Tokens.CHAR;\n
+\n
+        return this.createToken(tt, comparison, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a hash token based on the specified information. The\n
+     * first character provided is the pound sign (#) and then this\n
+     * method reads a name afterward.\n
+     * @param {String} first The first character (#) in the hash nam
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+e.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method hashToken\n
+     */\n
+    hashToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            name    = this.readName(first);\n
+\n
+        return this.createToken(Tokens.HASH, name, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a CDO or CHAR token based on the specified information. The\n
+     * first character is provided and the rest is read by the function to determine\n
+     * the correct token to create.\n
+     * @param {String} first The first character in the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method htmlCommentStartToken\n
+     */\n
+    htmlCommentStartToken: function(first, startLine, startCol){\n
+        var reader      = this._reader,\n
+            text        = first;\n
+\n
+        reader.mark();\n
+        text += reader.readCount(3);\n
+\n
+        if (text == "<!--"){\n
+            return this.createToken(Tokens.CDO, text, startLine, startCol);\n
+        } else {\n
+            reader.reset();\n
+            return this.charToken(first, startLine, startCol);\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Produces a CDC or CHAR token based on the specified information. The\n
+     * first character is provided and the rest is read by the function to determine\n
+     * the correct token to create.\n
+     * @param {String} first The first character in the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method htmlCommentEndToken\n
+     */\n
+    htmlCommentEndToken: function(first, startLine, startCol){\n
+        var reader      = this._reader,\n
+            text        = first;\n
+\n
+        reader.mark();\n
+        text += reader.readCount(2);\n
+\n
+        if (text == "-->"){\n
+            return this.createToken(Tokens.CDC, text, startLine, startCol);\n
+        } else {\n
+            reader.reset();\n
+            return this.charToken(first, startLine, startCol);\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Produces an IDENT or FUNCTION token based on the specified information. The\n
+     * first character is provided and the rest is read by the function to determine\n
+     * the correct token to create.\n
+     * @param {String} first The first character in the identifier.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method identOrFunctionToken\n
+     */\n
+    identOrFunctionToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            ident   = this.readName(first),\n
+            tt      = Tokens.IDENT;\n
+\n
+        //if there\'s a left paren immediately after, it\'s a URI or function\n
+        if (reader.peek() == "("){\n
+            ident += reader.read();\n
+            if (ident.toLowerCase() == "url("){\n
+                tt = Tokens.URI;\n
+                ident = this.readURI(ident);\n
+\n
+                //didn\'t find a valid URL or there\'s no closing paren\n
+                if (ident.toLowerCase() == "url("){\n
+                    tt = Tokens.FUNCTION;\n
+                }\n
+            } else {\n
+                tt = Tokens.FUNCTION;\n
+            }\n
+        } else if (reader.peek() == ":"){  //might be an IE function\n
+\n
+            //IE-specific functions always being with progid:\n
+            if (ident.toLowerCase() == "progid"){\n
+                ident += reader.readTo("(");\n
+                tt = Tokens.IE_FUNCTION;\n
+            }\n
+        }\n
+\n
+        return this.createToken(tt, ident, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The\n
+     * first character is provided and the rest is read by the function to determine\n
+     * the correct token to create.\n
+     * @param {String} first The first character in the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method importantToken\n
+     */\n
+    importantToken: function(first, startLine, startCol){\n
+        var reader      = this._reader,\n
+            important   = first,\n
+            tt          = Tokens.CHAR,\n
+            temp,\n
+            c;\n
+\n
+        reader.mark();\n
+        c = reader.read();\n
+\n
+        while(c){\n
+\n
+            //there can be a comment in here\n
+            if (c == "/"){\n
+\n
+                //if the next character isn\'t a star, then this isn\'t a valid !important token\n
+                if (reader.peek() != "*"){\n
+                    break;\n
+                } else {\n
+                    temp = this.readComment(c);\n
+                    if (temp === ""){    //broken!\n
+                        break;\n
+                    }\n
+                }\n
+            } else if (isWhitespace(c)){\n
+                important += c + this.readWhitespace();\n
+            } else if (/i/i.test(c)){\n
+                temp = reader.readCount(8);\n
+                if (/mportant/i.test(temp)){\n
+                    important += c + temp;\n
+                    tt = Tokens.IMPORTANT_SYM;\n
+\n
+                }\n
+                break;  //we\'re done\n
+            } else {\n
+                break;\n
+            }\n
+\n
+            c = reader.read();\n
+        }\n
+\n
+        if (tt == Tokens.CHAR){\n
+            reader.reset();\n
+            return this.charToken(first, startLine, startCol);\n
+        } else {\n
+            return this.createToken(tt, important, startLine, startCol);\n
+        }\n
+\n
+\n
+    },\n
+\n
+    /**\n
+     * Produces a NOT or CHAR token based on the specified information. The\n
+     * first character is provided and the rest is read by the function to determine\n
+     * the correct token to create.\n
+     * @param {String} first The first character in the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method notToken\n
+     */\n
+    notToken: function(first, startLine, startCol){\n
+        var reader      = this._reader,\n
+            text        = first;\n
+\n
+        reader.mark();\n
+        text += reader.readCount(4);\n
+\n
+        if (text.toLowerCase() == ":not("){\n
+            return this.createToken(Tokens.NOT, text, startLine, startCol);\n
+        } else {\n
+            reader.reset();\n
+            return this.charToken(first, startLine, startCol);\n
+        }\n
+    },\n
+\n
+    /**\n
+     * Produces a number token based on the given character\n
+     * and location in the stream. This may return a token of\n
+     * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION,\n
+     * or PERCENTAGE.\n
+     * @param {String} first The first character for the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method numberToken\n
+     */\n
+    numberToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            value   = this.readNumber(first),\n
+            ident,\n
+            tt      = Tokens.NUMBER,\n
+            c       = reader.peek();\n
+\n
+        if (isIdentStart(c)){\n
+            ident = this.readName(reader.read());\n
+            value += ident;\n
+\n
+            if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)){\n
+                tt = Tokens.LENGTH;\n
+            } else if (/^deg|^rad$|^grad$/i.test(ident)){\n
+                tt = Tokens.ANGLE;\n
+            } else if (/^ms$|^s$/i.test(ident)){\n
+                tt = Tokens.TIME;\n
+            } else if (/^hz$|^khz$/i.test(ident)){\n
+                tt = Tokens.FREQ;\n
+            } else if (/^dpi$|^dpcm$/i.test(ident)){\n
+                tt = Tokens.RESOLUTION;\n
+            } else {\n
+                tt = Tokens.DIMENSION;\n
+            }\n
+\n
+        } else if (c == "%"){\n
+            value += reader.read();\n
+            tt = Tokens.PERCENTAGE;\n
+        }\n
+\n
+        return this.createToken(tt, value, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a string token based on the given character\n
+     * and location in the stream. Since strings may be indicated\n
+     * by single or double quotes, a failure to match starting\n
+     * and ending quotes results in an INVALID token being generated.\n
+     * The first character in the string is passed in and then\n
+     * the rest are read up to and including the final quotation mark.\n
+     * @param {String} first The first character in the string.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method stringToken\n
+     */\n
+    stringToken: function(first, startLine, startCol){\n
+        var delim   = first,\n
+            string  = first,\n
+            reader  = this._reader,\n
+            prev    = first,\n
+            tt      = Tokens.STRING,\n
+            c       = reader.read();\n
+\n
+        while(c){\n
+            string += c;\n
+\n
+            //if the delimiter is found with an escapement, we\'re done.\n
+            if (c == delim && prev != "\\\\"){\n
+                break;\n
+            }\n
+\n
+            //if there\'s a newline without an escapement, it\'s an invalid string\n
+            if (isNewLine(reader.peek()) && c != "\\\\"){\n
+                tt = Tokens.INVALID;\n
+                break;\n
+            }\n
+\n
+            //save previous and get next\n
+            prev = c;\n
+            c = reader.read();\n
+        }\n
+\n
+        //if c is null, that means we\'re out of input and the string was never closed\n
+        if (c === null){\n
+            tt = Tokens.INVALID;\n
+        }\n
+\n
+        return this.createToken(tt, string, startLine, startCol);\n
+    },\n
+\n
+    unicodeRangeToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            value   = first,\n
+            temp,\n
+            tt      = Tokens.CHAR;\n
+\n
+        //then it should be a unicode range\n
+        if (reader.peek() == "+"){\n
+            reader.mark();\n
+            value += reader.read();\n
+            value += this.readUnicodeRangePart(true);\n
+\n
+            //ensure there\'s an actual unicode range here\n
+            if (value.length == 2){\n
+                reader.reset();\n
+            } else {\n
+\n
+                tt = Tokens.UNICODE_RANGE;\n
+\n
+                //if there\'s a ? in the first part, there can\'t be a second part\n
+                if (value.indexOf("?") == -1){\n
+\n
+                    if (reader.peek() == "-"){\n
+                        reader.mark();\n
+                        temp = reader.read();\n
+                        temp += this.readUnicodeRangePart(false);\n
+\n
+                        //if there\'s not another value, back up and just take the first\n
+                        if (temp.length == 1){\n
+                            reader.reset();\n
+                        } else {\n
+                            value += temp;\n
+                        }\n
+                    }\n
+\n
+                }\n
+            }\n
+        }\n
+\n
+        return this.createToken(tt, value, startLine, startCol);\n
+    },\n
+\n
+    /**\n
+     * Produces a S token based on the specified information. Since whitespace\n
+     * may have multiple characters, this consumes all whitespace characters\n
+     * into a single token.\n
+     * @param {String} first The first character in the token.\n
+     * @param {int} startLine The beginning line for the character.\n
+     * @param {int} startCol The beginning column for the character.\n
+     * @return {Object} A token object.\n
+     * @method whitespaceToken\n
+     */\n
+    whitespaceToken: function(first, startLine, startCol){\n
+        var reader  = this._reader,\n
+            value   = first + this.readWhitespace();\n
+        return this.createToken(Tokens.S, value, startLine, startCol);\n
+    },\n
+\n
+\n
+\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Methods to read values from the string stream\n
+    //-------------------------------------------------------------------------\n
+\n
+    readUnicodeRangePart: function(allowQuestionMark){\n
+        var reader  = this._reader,\n
+            part = "",\n
+            c       = reader.peek();\n
+\n
+        //first read hex digits\n
+        while(isHexDigit(c) && part.length < 6){\n
+            reader.read();\n
+            part += c;\n
+            c = reader.peek();\n
+        }\n
+\n
+        //then read question marks if allowed\n
+        if (allowQuestionMark){\n
+            while(c == "?" && part.length < 6){\n
+                reader.read();\n
+                part += c;\n
+                c = reader.peek();\n
+            }\n
+        }\n
+\n
+        //there can\'t be any other characters after this point\n
+\n
+        return part;\n
+    },\n
+\n
+    readWhitespace: function(){\n
+        var reader  = this._reader,\n
+            whitespace = "",\n
+            c       = reader.peek();\n
+\n
+        while(isWhitespace(c)){\n
+            reader.read();\n
+            whitespace += c;\n
+            c = reader.peek();\n
+        }\n
+\n
+        return whitespace;\n
+    },\n
+    readNumber: function(first){\n
+        var reader  = this._reader,\n
+            number  = first,\n
+            hasDot  = (first == "."),\n
+            c       = reader.peek();\n
+\n
+\n
+        while(c){\n
+            if (isDigit(c)){\n
+                number += reader.read();\n
+            } else if (c == "."){\n
+                if (hasDot){\n
+                    break;\n
+                } else {\n
+                    hasDot = true;\n
+                    number += reader.read();\n
+                }\n
+            } else {\n
+                break;\n
+            }\n
+\n
+            c = reader.peek();\n
+        }\n
+\n
+        return number;\n
+    },\n
+    readString: function(){\n
+        var reader  = this._reader,\n
+            delim   = reader.read(),\n
+            string  = delim,\n
+            prev    = delim,\n
+            c       = reader.peek();\n
+\n
+        while(c){\n
+            c = reader.read();\n
+            string += c;\n
+\n
+            //if the delimiter is found with an escapement, we\'re done.\n
+            if (c == delim && prev != "\\\\"){\n
+                break;\n
+            }\n
+\n
+            //if there\'s a newline without an escapement, it\'s an invalid string\n
+            if (isNewLine(reader.peek()) && c != "\\\\"){\n
+                string = "";\n
+                break;\n
+            }\n
+\n
+            //save previous and get next\n
+            prev = c;\n
+            c = reader.peek();\n
+        }\n
+\n
+        //if c is null, that means we\'re out of input and the string was never closed\n
+        if (c === null){\n
+            string = "";\n
+        }\n
+\n
+        return string;\n
+    },\n
+    readURI: function(first){\n
+        var reader  = this._reader,\n
+            uri     = first,\n
+            inner   = "",\n
+            c       = reader.peek();\n
+\n
+        reader.mark();\n
+\n
+        //skip whitespace before\n
+        while(c && isWhitespace(c)){\n
+            reader.read();\n
+            c = reader.peek();\n
+        }\n
+\n
+        //it\'s a string\n
+        if (c == "\'" || c == "\\""){\n
+            inner = this.readString();\n
+        } else {\n
+            inner = this.readURL();\n
+        }\n
+\n
+        c = reader.peek();\n
+\n
+        //skip whitespace after\n
+        while(c && isWhitespace(c)){\n
+            reader.read();\n
+            c = reader.peek();\n
+        }\n
+\n
+        //if there was no inner value or the next character isn\'t closing paren, it\'s not a URI\n
+        if (inner === "" || c != ")"){\n
+            uri = first;\n
+            reader.reset();\n
+        } else {\n
+            uri += inner + reader.read();\n
+        }\n
+\n
+        return uri;\n
+    },\n
+    readURL: function(){\n
+        var reader  = this._reader,\n
+            url     = "",\n
+            c       = reader.peek();\n
+\n
+        //TODO: Check for escape and nonascii\n
+        while (/^[!#$%&\\\\*-~]$/.test(c)){\n
+            url += reader.read();\n
+            c = reader.peek();\n
+        }\n
+\n
+        return url;\n
+\n
+    },\n
+    readName: function(first){\n
+        var reader  = this._reader,\n
+            ident   = first || "",\n
+            c       = reader.peek();\n
+\n
+        while(true){\n
+            if (c == "\\\\"){\n
+                ident += this.readEscape(reader.read());\n
+                c = reader.peek();\n
+            } else if(c && isNameChar(c)){\n
+                ident += reader.read();\n
+                c = reader.peek();\n
+            } else {\n
+                break;\n
+            }\n
+        }\n
+\n
+        return ident;\n
+    },\n
+\n
+    readEscape: function(first){\n
+        var reader  = this._reader,\n
+            cssEscape = first || "",\n
+            i       = 0,\n
+            c       = reader.peek();\n
+\n
+        if (isHexDigit(c)){\n
+            do {\n
+                cssEscape += reader.read();\n
+                c = reader.peek();\n
+            } while(c && isHexDigit(c) && ++i < 6);\n
+        }\n
+\n
+        if (cssEscape.length == 3 && /\\s/.test(c) ||\n
+            cssEscape.length == 7 || cssEscape.length == 1){\n
+                reader.read();\n
+        } else {\n
+            c = "";\n
+        }\n
+\n
+        return cssEscape + c;\n
+    },\n
+\n
+    readComment: function(first){\n
+        var reader  = this._reader,\n
+            comment = first || "",\n
+            c       = reader.read();\n
+\n
+        if (c == "*"){\n
+            while(c){\n
+                comment += c;\n
+\n
+                //look for end of comment\n
+                if (comment.length > 2 && c == "*" && reader.peek() == "/"){\n
+                    comment += reader.read();\n
+                    break;\n
+                }\n
+\n
+                c = reader.read();\n
+            }\n
+\n
+            return comment;\n
+        } else {\n
+            return "";\n
+        }\n
+\n
+    }\n
+});\n
+\n
+\n
+var Tokens  = [\n
+\n
+    /*\n
+     * The following token names are defined in CSS3 Grammar: http://www.w3.org/TR/css3-syntax/#lexical\n
+     */\n
+\n
+    //HTML-style comments\n
+    { name: "CDO"},\n
+    { name: "CDC"},\n
+\n
+    //ignorables\n
+    { name: "S", whitespace: true/*, channel: "ws"*/},\n
+    { name: "COMMENT", comment: true, hide: true, channel: "comment" },\n
+\n
+    //attribute equality\n
+    { name: "INCLUDES", text: "~="},\n
+    { name: "DASHMATCH", text: "|="},\n
+    { name: "PREFIXMATCH", text: "^="},\n
+    { name: "SUFFIXMATCH", text: "$="},\n
+    { name: "SUBSTRINGMATCH", text: "*="},\n
+\n
+    //identifier types\n
+    { name: "STRING"},\n
+    { name: "IDENT"},\n
+    { name: "HASH"},\n
+\n
+    //at-keywords\n
+    { name: "IMPORT_SYM", text: "@import"},\n
+    { name: "PAGE_SYM", text: "@page"},\n
+    { name: "MEDIA_SYM", text: "@media"},\n
+    { name: "FONT_FACE_SYM", text: "@font-face"},\n
+    { name: "CHARSET_SYM", text: "@charset"},\n
+    { name: "NAMESPACE_SYM", text: "@namespace"},\n
+    { name: "VIEWPORT_SYM", text: "@viewport"},\n
+    { name: "UNKNOWN_SYM" },\n
+    //{ name: "ATKEYWORD"},\n
+\n
+    //CSS3 animations\n
+    { name: "KEYFRAMES_SYM", text: [ "@keyframes", "@-webkit-keyframes", "@-moz-keyframes", "@-o-keyframes" ] },\n
+\n
+    //important symbol\n
+    { name: "IMPORTANT_SYM"},\n
+\n
+    //measurements\n
+    { name: "LENGTH"},\n
+    { name: "ANGLE"},\n
+    { name: "TIME"},\n
+    { name: "FREQ"},\n
+    { name: "DIMENSION"},\n
+    { name: "PERCENTAGE"},\n
+    { name: "NUMBER"},\n
+\n
+    //functions\n
+    { name: "URI"},\n
+    { name: "FUNCTION"},\n
+\n
+    //Unicode ranges\n
+    { name: "UNICODE_RANGE"},\n
+\n
+    /*\n
+     * The following token names are defined in CSS3 Selectors: http://www.w3.org/TR/css3-selectors/#selector-syntax\n
+     */\n
+\n
+    //invalid string\n
+    { name: "INVALID"},\n
+\n
+    //combinators\n
+    { name: "PLUS", text: "+" },\n
+    { name: "GREATER", text: ">"},\n
+    { name: "COMMA", text: ","},\n
+    { name: "TILDE", text: "~"},\n
+\n
+    //modifier\n
+    { name: "NOT"},\n
+\n
+    /*\n
+     * Defined in CSS3 Paged Media\n
+     */\n
+    { name: "TOPLEFTCORNER_SYM", text: "@top-left-corner"},\n
+    { name: "TOPLEFT_SYM", text: "@top-left"},\n
+    { name: "TOPCENTER_SYM", text: "@top-center"},\n
+    { name: "TOPRIGHT_SYM", text: "@top-right"},\n
+    { name: "TOPRIGHTCORNER_SYM", text: "@top-right-corner"},\n
+    { name: "BOTTOMLEFTCORNER_SYM", text: "@bottom-left-corner"},\n
+    { name: "BOTTOMLEFT_SYM", text: "@bottom-left"},\n
+    { name: "BOTTOMCENTER_SYM", text: "@bottom-center"},\n
+    { name: "BOTTOMRIGHT_SYM", text: "@bottom-right"},\n
+    { name: "BOTTOMRIGHTCORNER_SYM", text: "@bottom-right-corner"},\n
+    { name: "LEFTTOP_SYM", text: "@left-top"},\n
+    { name: "LEFTMIDDLE_SYM", text: "@left-middle"},\n
+    { name: "LEFTBOTTOM_SYM", text: "@left-bottom"},\n
+    { name: "RIGHTTOP_SYM", text: "@right-top"},\n
+    { name: "RIGHTMIDDLE_SYM", text: "@right-middle"},\n
+    { name: "RIGHTBOTTOM_SYM", text: "@right-bottom"},\n
+\n
+    /*\n
+     * The following token names are defined in CSS3 Media Queries: http://www.w3.org/TR/css3-mediaqueries/#syntax\n
+     */\n
+    /*{ name: "MEDIA_ONLY", state: "media"},\n
+    { name: "MEDIA_NOT", state: "media"},\n
+    { name: "MEDIA_AND", state: "media"},*/\n
+    { name: "RESOLUTION", state: "media"},\n
+\n
+    /*\n
+     * The following token names are not defined in any CSS specification but are used by the lexer.\n
+     */\n
+\n
+    //not a real token, but useful for stupid IE filters\n
+    { name: "IE_FUNCTION" },\n
+\n
+    //part of CSS3 grammar but not the Flex code\n
+    { name: "CHAR" },\n
+\n
+    //TODO: Needed?\n
+    //Not defined as tokens, but might as well be\n
+    {\n
+        name: "PIPE",\n
+        text: "|"\n
+    },\n
+    {\n
+        name: "SLASH",\n
+        text: "/"\n
+    },\n
+    {\n
+        name: "MINUS",\n
+        text: "-"\n
+    },\n
+    {\n
+        name: "STAR",\n
+        text: "*"\n
+    },\n
+\n
+    {\n
+        name: "LBRACE",\n
+        text: "{"\n
+    },\n
+    {\n
+        name: "RBRACE",\n
+        text: "}"\n
+    },\n
+    {\n
+        name: "LBRACKET",\n
+        text: "["\n
+    },\n
+    {\n
+        name: "RBRACKET",\n
+        text: "]"\n
+    },\n
+    {\n
+        name: "EQUALS",\n
+        text: "="\n
+    },\n
+    {\n
+        name: "COLON",\n
+        text: ":"\n
+    },\n
+    {\n
+        name: "SEMICOLON",\n
+        text: ";"\n
+    },\n
+\n
+    {\n
+        name: "LPAREN",\n
+        text: "("\n
+    },\n
+    {\n
+        name: "RPAREN",\n
+        text: ")"\n
+    },\n
+    {\n
+        name: "DOT",\n
+        text: "."\n
+    }\n
+];\n
+\n
+(function(){\n
+\n
+    var nameMap = [],\n
+        typeMap = {};\n
+\n
+    Tokens.UNKNOWN = -1;\n
+    Tokens.unshift({name:"EOF"});\n
+    for (var i=0, len = Tokens.length; i < len; i++){\n
+        nameMap.push(Tokens[i].name);\n
+        Tokens[Tokens[i].name] = i;\n
+        if (Tokens[i].text){\n
+            if (Tokens[i].text instanceof Array){\n
+                for (var j=0; j < Tokens[i].text.length; j++){\n
+                    typeMap[Tokens[i].text[j]] = i;\n
+                }\n
+            } else {\n
+                typeMap[Tokens[i].text] = i;\n
+            }\n
+        }\n
+    }\n
+\n
+    Tokens.name = function(tt){\n
+        return nameMap[tt];\n
+    };\n
+\n
+    Tokens.type = function(c){\n
+        return typeMap[c] || -1;\n
+    };\n
+\n
+})();\n
+\n
+\n
+\n
+\n
+//This file will likely change a lot! Very experimental!\n
+/*global Properties, ValidationTypes, ValidationError, PropertyValueIterator */\n
+var Validation = {\n
+\n
+    validate: function(property, value){\n
+\n
+        //normalize name\n
+        var name        = property.toString().toLowerCase(),\n
+            parts       = value.parts,\n
+            expression  = new PropertyValueIterator(value),\n
+            spec        = Properties[name],\n
+            part,\n
+            valid,\n
+            j, count,\n
+            msg,\n
+            types,\n
+            last,\n
+            literals,\n
+            max, multi, group;\n
+\n
+        if (!spec) {\n
+            if (name.indexOf("-") !== 0){    //vendor prefixed are ok\n
+                throw new ValidationError("Unknown property \'" + property + "\'.", property.line, property.col);\n
+            }\n
+        } else if (typeof spec != "number"){\n
+\n
+            //initialization\n
+            if (typeof spec == "string"){\n
+                if (spec.indexOf("||") > -1) {\n
+                    this.groupProperty(spec, expression);\n
+                } else {\n
+                    this.singleProperty(spec, expression, 1);\n
+                }\n
+\n
+            } else if (spec.multi) {\n
+                this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);\n
+            } else if (typeof spec == "function") {\n
+                spec(expression);\n
+            }\n
+\n
+        }\n
+\n
+    },\n
+\n
+    singleProperty: function(types, expression, max, partial) {\n
+\n
+        var result      = false,\n
+            value       = expression.value,\n
+            count       = 0,\n
+            part;\n
+\n
+        while (expression.hasNext() && count < max) {\n
+            result = ValidationTypes.isAny(expression, types);\n
+            if (!result) {\n
+                break;\n
+            }\n
+            count++;\n
+        }\n
+\n
+        if (!result) {\n
+            if (expression.hasNext() && !expression.isFirst()) {\n
+                part = expression.peek();\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                 throw new ValidationError("Expected (" + types + ") but found \'" + value + "\'.", value.line, value.col);\n
+            }\n
+        } else if (expression.hasNext()) {\n
+            part = expression.next();\n
+            throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+        }\n
+\n
+    },\n
+\n
+    multiProperty: function (types, expression, comma, max) {\n
+\n
+        var result      = false,\n
+            value       = expression.value,\n
+            count       = 0,\n
+            sep         = false,\n
+            part;\n
+\n
+        while(expression.hasNext() && !result && count < max) {\n
+            if (ValidationTypes.isAny(expression, types)) {\n
+                count++;\n
+                if (!expression.hasNext()) {\n
+                    result = true;\n
+\n
+                } else if (comma) {\n
+                    if (expression.peek() == ",") {\n
+                        part = expression.next();\n
+                    } else {\n
+                        break;\n
+                    }\n
+                }\n
+            } else {\n
+                break;\n
+\n
+            }\n
+        }\n
+\n
+        if (!result) {\n
+            if (expression.hasNext() && !expression.isFirst()) {\n
+                part = expression.peek();\n
+                throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                part = expression.previous();\n
+                if (comma && part == ",") {\n
+                    throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+                } else {\n
+                    throw new ValidationError("Expected (" + types + ") but found \'" + value + "\'.", value.line, value.col);\n
+                }\n
+            }\n
+\n
+        } else if (expression.hasNext()) {\n
+            part = expression.next();\n
+            throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+        }\n
+\n
+    },\n
+\n
+    groupProperty: function (types, expression, comma) {\n
+\n
+        var result      = false,\n
+            value       = expression.value,\n
+            typeCount   = types.split("||").length,\n
+            groups      = { count: 0 },\n
+            partial     = false,\n
+            name,\n
+            part;\n
+\n
+        while(expression.hasNext() && !result) {\n
+            name = ValidationTypes.isAnyOfGroup(expression, types);\n
+            if (name) {\n
+\n
+                //no dupes\n
+                if (groups[name]) {\n
+                    break;\n
+                } else {\n
+                    groups[name] = 1;\n
+                    groups.count++;\n
+                    partial = true;\n
+\n
+                    if (groups.count == typeCount || !expression.hasNext()) {\n
+                        result = true;\n
+                    }\n
+                }\n
+            } else {\n
+                break;\n
+            }\n
+        }\n
+\n
+        if (!result) {\n
+            if (partial && expression.hasNext()) {\n
+                    part = expression.peek();\n
+                    throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+            } else {\n
+                throw new ValidationError("Expected (" + types + ") but found \'" + value + "\'.", value.line, value.col);\n
+            }\n
+        } else if (expression.hasNext()) {\n
+            part = expression.next();\n
+            throw new ValidationError("Expected end of value but found \'" + part + "\'.", part.line, part.col);\n
+        }\n
+    }\n
+\n
+\n
+\n
+};\n
+/**\n
+ * Type to use when a validation error occurs.\n
+ * @class ValidationError\n
+ * @namespace parserlib.util\n
+ * @constructor\n
+ * @param {String} message The error message.\n
+ * @param {int} line The line at which the error occurred.\n
+ * @param {int} col The column at which the error occurred.\n
+ */\n
+function ValidationError(message, line, col){\n
+\n
+    /**\n
+     * The column at which the error occurred.\n
+     * @type int\n
+     * @property col\n
+     */\n
+    this.col = col;\n
+\n
+    /**\n
+     * The line at which the error occurred.\n
+     * @type int\n
+     * @property line\n
+     */\n
+    this.line = line;\n
+\n
+    /**\n
+     * The text representation of the unit.\n
+     * @type String\n
+     * @property text\n
+     */\n
+    this.message = message;\n
+\n
+}\n
+\n
+//inherit from Error\n
+ValidationError.prototype = new Error();\n
+//This file will likely change a lot! Very experimental!\n
+/*global Properties, Validation, ValidationError, PropertyValueIterator, console*/\n
+var ValidationTypes = {\n
+\n
+    isLiteral: function (part, literals) {\n
+        var text = part.text.toString().toLowerCase(),\n
+            args = literals.split(" | "),\n
+            i, len, found = false;\n
+\n
+        for (i=0,len=args.length; i < len && !found; i++){\n
+            if (text == args[i].toLowerCase()){\n
+                found = true;\n
+            }\n
+        }\n
+\n
+        return found;\n
+    },\n
+\n
+    isSimple: function(type) {\n
+        return !!this.simple[type];\n
+    },\n
+\n
+    isComplex: function(type) {\n
+        return !!this.complex[type];\n
+    },\n
+\n
+    /**\n
+     * Determines if the next part(s) of the given expression\n
+     * are any of the given types.\n
+     */\n
+    isAny: function (expression, types) {\n
+        var args = types.split(" | "),\n
+            i, len, found = false;\n
+\n
+        for (i=0,len=args.length; i < len && !found && expression.hasNext(); i++){\n
+            found = this.isType(expression, args[i]);\n
+        }\n
+\n
+        return found;\n
+    },\n
+\n
+    /**\n
+     * Determines if the next part(s) of the given expression\n
+     * are one of a group.\n
+     */\n
+    isAnyOfGroup: function(expression, types) {\n
+        var args = types.split(" || "),\n
+            i, len, found = false;\n
+\n
+        for (i=0,len=args.length; i < len && !found; i++){\n
+            found = this.isType(expression, args[i]);\n
+        }\n
+\n
+        return found ? args[i-1] : false;\n
+    },\n
+\n
+    /**\n
+     * Determines if the next part(s) of the given expression\n
+     * are of a given type.\n
+     */\n
+    isType: function (expression, type) {\n
+        var part = expression.peek(),\n
+            result = false;\n
+\n
+        if (type.charAt(0) != "<") {\n
+            result = this.isLiteral(part, type);\n
+            if (result) {\n
+                expression.next();\n
+            }\n
+        } else if (this.simple[type]) {\n
+            result = this.simple[type](part);\n
+            if (result) {\n
+                expression.next();\n
+            }\n
+        } else {\n
+            result = this.complex[type](expression);\n
+        }\n
+\n
+        return result;\n
+    },\n
+\n
+\n
+\n
+    simple: {\n
+\n
+        "<absolute-size>": function(part){\n
+            return ValidationTypes.isLiteral(part, "xx-small | x-small | small | medium | large | x-large | xx-large");\n
+        },\n
+\n
+        "<attachment>": function(part){\n
+            return ValidationTypes.isLiteral(part, "scroll | fixed | local");\n
+        },\n
+\n
+        "<attr>": function(part){\n
+            return part.type == "function" && part.name == "attr";\n
+        },\n
+\n
+        "<bg-image>": function(part){\n
+            return this["<image>"](part) || this["<gradient>"](part) ||  part == "none";\n
+        },\n
+\n
+        "<gradient>": function(part) {\n
+            return part.type == "function" && /^(?:\\-(?:ms|moz|o|webkit)\\-)?(?:repeating\\-)?(?:radial\\-|linear\\-)?gradient/i.test(part);\n
+        },\n
+\n
+        "<box>": function(part){\n
+            return ValidationTypes.isLiteral(part, "padding-box | border-box | content-box");\n
+        },\n
+\n
+        "<content>": function(part){\n
+            return part.type == "function" && part.name == "content";\n
+        },\n
+\n
+        "<relative-size>": function(part){\n
+            return ValidationTypes.isLiteral(part, "smaller | larger");\n
+        },\n
+\n
+        //any identifier\n
+        "<ident>": function(part){\n
+            return part.type == "identifier";\n
+        },\n
+\n
+        "<length>": function(part){\n
+            if (part.type == "function" && /^(?:\\-(?:ms|moz|o|webkit)\\-)?calc/i.test(part)){\n
+                return true;\n
+            }else{\n
+                return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0";\n
+            }\n
+        },\n
+\n
+        "<color>": function(part){\n
+            return part.type == "color" || part == "transparent";\n
+        },\n
+\n
+        "<number>": function(part){\n
+            return part.type == "number" || this["<integer>"](part);\n
+        },\n
+\n
+        "<integer>": function(part){\n
+            return part.type == "integer";\n
+        },\n
+\n
+        "<line>": function(part){\n
+            return part.type == "integer";\n
+        },\n
+\n
+        "<angle>": function(part){\n
+            return part.type == "angle";\n
+        },\n
+\n
+        "<uri>": function(part){\n
+            return part.type == "uri";\n
+        },\n
+\n
+        "<image>": function(part){\n
+            return this["<uri>"](part);\n
+        },\n
+\n
+        "<percentage>": function(part){\n
+            return part.type == "percentage" || part == "0";\n
+        },\n
+\n
+        "<border-width>": function(part){\n
+            return this["<length>"](part) || ValidationTypes.isLiteral(part, "thin | medium | thick");\n
+        },\n
+\n
+        "<border-style>": function(part){\n
+            return ValidationTypes.isLiteral(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset");\n
+        },\n
+\n
+        "<margin-width>": function(part){\n
+            return this["<length>"](part) || this["<percentage>"](part) || ValidationTypes.isLiteral(part, "auto");\n
+        },\n
+\n
+        "<padding-width>": function(part){\n
+            return this["<length>"](part) || this["<percentage>"](part);\n
+        },\n
+\n
+        "<shape>": function(part){\n
+            return part.type == "function" && (part.name == "rect" || part.name == "inset-rect");\n
+        },\n
+\n
+        "<time>": function(part) {\n
+            return part.type == "time";\n
+        }\n
+    },\n
+\n
+    complex: {\n
+\n
+        "<bg-position>": function(expression){\n
+            var types   = this,\n
+                result  = false,\n
+                numeric = "<percentage> | <length>",\n
+                xDir    = "left | right",\n
+                yDir    = "top | bottom",\n
+                count = 0,\n
+                hasNext = function() {\n
+                    return expression.hasNext() && expression.peek() != ",";\n
+                };\n
+\n
+            while (expression.peek(count) && expression.peek(count) != ",") {\n
+                count++;\n
+            }\n
+\n
+/*\n
+<position> = [\n
+  [ left | center | right | top | bottom | <percentage> | <length> ]\n
+|\n
+  [ left | center | right | <percentage> | <length> ]\n
+  [ top | center | bottom | <percentage> | <length> ]\n
+|\n
+  [ center | [ left | right ] [ <percentage> | <length> ]? ] &&\n
+  [ center | [ top | bottom ] [ <percentage> | <length> ]? ]\n
+]\n
+*/\n
+\n
+            if (count < 3) {\n
+                if (ValidationTypes.isAny(expression, xDir + " | center | " + numeric)) {\n
+                        result = true;\n
+                        ValidationTypes.isAny(expression, yDir + " | center | " + numeric);\n
+                } else if (ValidationTypes.isAny(expression, yDir)) {\n
+                        result = true;\n
+                        ValidationTypes.isAny(expression, xDir + " | center");\n
+                }\n
+            } else {\n
+                if (ValidationTypes.isAny(expression, xDir)) {\n
+                    if (ValidationTypes.isAny(expression, yDir)) {\n
+                        result = true;\n
+                        ValidationTypes.isAny(expression, numeric);\n
+                    } else if (ValidationTypes.isAny(expression, numeric)) {\n
+                        if (ValidationTypes.isAny(expression, yDir)) {\n
+                            result = true;\n
+                            ValidationTypes.isAny(expression, numeric);\n
+                        } else if (ValidationTypes.isAny(expression, "center")) {\n
+                            result = true;\n
+                        }\n
+                    }\n
+                } else if (ValidationTypes.isAny(expression, yDir)) {\n
+                    if (ValidationTypes.isAny(expression, xDir)) {\n
+                        result = true;\n
+                        ValidationTypes.isAny(expression, numeric);\n
+                    } else if (ValidationTypes.isAny(expression, numeric)) {\n
+                        if (ValidationTypes.isAny(expression, xDir)) {\n
+                                result = true;\n
+                                ValidationTypes.isAny(expression, numeric);\n
+                        } else if (ValidationTypes.isAny(expression, "center")) {\n
+                            result = true;\n
+                        }\n
+                    }\n
+                } else if (ValidationTypes.isAny(expression, "center")) {\n
+                    if (ValidationTypes.isAny(expression, xDir + " | " + yDir)) {\n
+                        result = true;\n
+                        ValidationTypes.isAny(expression, numeric);\n
+                    }\n
+                }\n
+            }\n
+\n
+            return result;\n
+        },\n
+\n
+        "<bg-size>": function(expression){\n
+            //<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain\n
+            var types   = this,\n
+                result  = false,\n
+                numeric = "<percentage> | <length> | auto",\n
+                part,\n
+                i, len;\n
+\n
+            if (ValidationTypes.isAny(expression, "cover | contain")) {\n
+                result = true;\n
+            } else if (ValidationTypes.isAny(expression, numeric)) {\n
+                result = true;\n
+                ValidationTypes.isAny(expression, numeric);\n
+            }\n
+\n
+            return result;\n
+        },\n
+\n
+        "<repeat-style>": function(expression){\n
+            //repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}\n
+            var result  = false,\n
+                values  = "repeat | space | round | no-repeat",\n
+                part;\n
+\n
+            if (expression.hasNext()){\n
+                part = expression.next();\n
+\n
+                if (ValidationTypes.isLiteral(part, "repeat-x | repeat-y")) {\n
+                    result = true;\n
+                } else if (ValidationTypes.isLiteral(part, values)) {\n
+                    result = true;\n
+\n
+                    if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {\n
+                        expression.next();\n
+                    }\n
+                }\n
+            }\n
+\n
+            return result;\n
+\n
+        },\n
+\n
+        "<shadow>": function(expression) {\n
+            //inset? && [ <length>{2,4} && <color>? ]\n
+            var result  = false,\n
+                count   = 0,\n
+                inset   = false,\n
+                color   = false,\n
+                part;\n
+\n
+            if (expression.hasNext()) {\n
+\n
+                if (ValidationTypes.isAny(expression, "inset")){\n
+                    inset = true;\n
+                }\n
+\n
+                if (ValidationTypes.isAny(expression, "<color>")) {\n
+                    color = true;\n
+                }\n
+\n
+                while (ValidationTypes.isAny(expression, "<length>") && count < 4) {\n
+                    count++;\n
+                }\n
+\n
+\n
+                if (expression.hasNext()) {\n
+                    if (!color) {\n
+                        ValidationTypes.isAny(expression, "<color>");\n
+                    }\n
+\n
+                    if (!inset) {\n
+                        ValidationTypes.isAny(expression, "inset");\n
+                    }\n
+\n
+                }\n
+\n
+                result = (count >= 2 && count <= 4);\n
+\n
+            }\n
+\n
+            return result;\n
+        },\n
+\n
+        "<x-one-radius>": function(expression) {\n
+            //[ <length> | <percentage> ] [ <length> | <percentage> ]?\n
+            var result  = false,\n
+                simple = "<length> | <percentage> | inherit";\n
+\n
+            if (ValidationTypes.isAny(expression, simple)){\n
+                result = true;\n
+                ValidationTypes.isAny(expression, simple);\n
+            }\n
+\n
+            return result;\n
+        }\n
+    }\n
+};\n
+\n
+\n
+\n
+parserlib.css = {\n
+Colors              :Colors,\n
+Combinator          :Combinator,\n
+Parser              :Parser,\n
+PropertyName        :PropertyName,\n
+PropertyValue       :PropertyValue,\n
+PropertyValuePart   :PropertyValuePart,\n
+MediaFeature        :MediaFeature,\n
+MediaQuery          :MediaQuery,\n
+Selector            :Selector,\n
+SelectorPart        :SelectorPart,\n
+SelectorSubPart     :SelectorSubPart,\n
+Specificity         :Specificity,\n
+TokenStream         :TokenStream,\n
+Tokens              :Tokens,\n
+ValidationError     :ValidationError\n
+};\n
+})();\n
+\n
+\n
+\n
+\n
+(function(){\n
+for(var prop in parserlib){\n
+exports[prop] = parserlib[prop];\n
+}\n
+})();\n
+\n
+\n
+/**\n
+ * Main CSSLint object.\n
+ * @class CSSLint\n
+ * @static\n
+ * @extends parserlib.util.EventTarget\n
+ */\n
+/*global parserlib, Reporter*/\n
+var CSSLint = (function(){\n
+\n
+    var rules           = [],\n
+        formatters      = [],\n
+        embeddedRuleset = /\\/\\*csslint([^\\*]*)\\*\\//,\n
+        api             = new parserlib.util.EventTarget();\n
+\n
+    api.version = "0.10.0";\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Rule Management\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Adds a new rule to the engine.\n
+     * @param {Object} rule The rule to add.\n
+     * @method addRule\n
+     */\n
+    api.addRule = function(rule){\n
+        rules.push(rule);\n
+        rules[rule.id] = rule;\n
+    };\n
+\n
+    /**\n
+     * Clears all rule from the engine.\n
+     * @method clearRules\n
+     */\n
+    api.clearRules = function(){\n
+        rules = [];\n
+    };\n
+\n
+    /**\n
+     * Returns the rule objects.\n
+     * @return An array of rule objects.\n
+     * @method getRules\n
+     */\n
+    api.getRules = function(){\n
+        return [].concat(rules).sort(function(a,b){\n
+            return a.id > b.id ? 1 : 0;\n
+        });\n
+    };\n
+\n
+    /**\n
+     * Returns a ruleset configuration object with all current rules.\n
+     * @return A ruleset object.\n
+     * @method getRuleset\n
+     */\n
+    api.getRuleset = function() {\n
+        var ruleset = {},\n
+            i = 0,\n
+            len = rules.length;\n
+\n
+        while (i < len){\n
+            ruleset[rules[i++].id] = 1;    //by default, everything is a warning\n
+        }\n
+\n
+        return ruleset;\n
+    };\n
+\n
+    /**\n
+     * Returns a ruleset object based on embedded rules.\n
+     * @param {String} text A string of css containing embedded rules.\n
+     * @param {Object} ruleset A ruleset object to modify.\n
+     * @return {Object} A ruleset object.\n
+     * @method getEmbeddedRuleset\n
+     */\n
+    function applyEmbeddedRuleset(text, ruleset){\n
+        var valueMap,\n
+            embedded = text && text.match(embeddedRuleset),\n
+            rules = embedded && embedded[1];\n
+\n
+        if (rules) {\n
+            valueMap = {\n
+                "true": 2,  // true is error\n
+                "": 1,      // blank is warning\n
+                "false": 0, // false is ignore\n
+\n
+                "2": 2,     // explicit error\n
+                "1": 1,     // explicit warning\n
+                "0": 0      // explicit ignore\n
+            };\n
+\n
+            rules.toLowerCase().split(",").forEach(function(rule){\n
+                var pair = rule.split(":"),\n
+                    property = pair[0] || "",\n
+                    value = pair[1] || "";\n
+\n
+                ruleset[property.trim()] = valueMap[value.trim()];\n
+            });\n
+        }\n
+\n
+        return ruleset;\n
+    }\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Formatters\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Adds a new formatter to the engine.\n
+     * @param {Object} formatter The formatter to add.\n
+     * @method addFormatter\n
+     */\n
+    api.addFormatter = function(formatter) {\n
+        // formatters.push(formatter);\n
+        formatters[formatter.id] = formatter;\n
+    };\n
+\n
+    /**\n
+     * Retrieves a formatter for use.\n
+     * @param {String} formatId The name of the format to retrieve.\n
+     * @return {Object} The formatter or undefined.\n
+     * @method getFormatter\n
+     */\n
+    api.getFormatter = function(formatId){\n
+        return formatters[formatId];\n
+    };\n
+\n
+    /**\n
+     * Formats the results in a particular format for a single file.\n
+     * @param {Object} result The results returned from CSSLint.verify().\n
+     * @param {String} filename The filename for which the results apply.\n
+     * @param {String} formatId The name of the formatter to use.\n
+     * @param {Object} options (Optional) for special output handling.\n
+     * @return {String} A formatted string for the results.\n
+     * @method format\n
+     */\n
+    api.format = function(results, filename, formatId, options) {\n
+        var formatter = this.getFormatter(formatId),\n
+            result = null;\n
+\n
+        if (formatter){\n
+            result = formatter.startFormat();\n
+            result += formatter.formatResults(results, filename, options || {});\n
+            result += formatter.endFormat();\n
+        }\n
+\n
+        return result;\n
+    };\n
+\n
+    /**\n
+     * Indicates if the given format is supported.\n
+     * @param {String} formatId The ID of the format to check.\n
+     * @return {Boolean} True if the format exists, false if not.\n
+     * @method hasFormat\n
+     */\n
+    api.hasFormat = function(formatId){\n
+        return formatters.hasOwnProperty(formatId);\n
+    };\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Verification\n
+    //-------------------------------------------------------------------------\n
+\n
+    /**\n
+     * Starts the verification process for the given CSS text.\n
+     * @param {String} text The CSS text to verify.\n
+     * @param {Object} ruleset (Optional) List of rules to apply. If null, then\n
+     *      all rules are used. If a rule has a value of 1 then it\'s a warning,\n
+     *      a value of 2 means it\'s an error.\n
+     * @return {Object} Results of the verification.\n
+     * @method verify\n
+     */\n
+    api.verify = function(text, ruleset){\n
+\n
+        var i       = 0,\n
+            len     = rules.length,\n
+            reporter,\n
+            lines,\n
+            report,\n
+            parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,\n
+                                                underscoreHack: true, strict: false });\n
+\n
+        // normalize line endings\n
+        lines = text.replace(/\\n\\r?/g, "$split$").split(\'$split$\');\n
+\n
+        if (!ruleset){\n
+            ruleset = this.getRuleset();\n
+        }\n
+\n
+        if (embeddedRuleset.test(text)){\n
+            ruleset = applyEmbeddedRuleset(text, ruleset);\n
+        }\n
+\n
+        reporter = new Reporter(lines, ruleset);\n
+\n
+        ruleset.errors = 2;       //always report parsing errors as errors\n
+        for (i in ruleset){\n
+            if(ruleset.hasOwnProperty(i) && ruleset[i]){\n
+                if (rules[i]){\n
+                    rules[i].init(parser, reporter);\n
+                }\n
+            }\n
+        }\n
+\n
+\n
+        //capture most horrible error type\n
+        try {\n
+            parser.parse(text);\n
+        } catch (ex) {\n
+            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});\n
+        }\n
+\n
+        report = {\n
+            messages    : reporter.messages,\n
+            stats       : reporter.stats,\n
+            ruleset     : reporter.ruleset\n
+        };\n
+\n
+        //sort by line numbers, rollups at the bottom\n
+        report.messages.sort(function (a, b){\n
+            if (a.rollup && !b.rollup){\n
+                return 1;\n
+            } else if (!a.rollup && b.rollup){\n
+                return -1;\n
+            } else {\n
+                return a.line - b.line;\n
+            }\n
+        });\n
+\n
+        return report;\n
+    };\n
+\n
+    //-------------------------------------------------------------------------\n
+    // Publish the API\n
+    //-------------------------------------------------------------------------\n
+\n
+    return api;\n
+\n
+})();\n
+\n
+/*global CSSLint*/\n
+/**\n
+ * An instance of Report is used to report results of the\n
+ * verification back to the main API.\n
+ * @class Reporter\n
+ * @constructor\n
+ * @param {String[]} lines The text lines of the source.\n
+ * @param {Object} ruleset The set of rules to work with, including if\n
+ *      they are errors or warnings.\n
+ */\n
+function Reporter(lines, ruleset){\n
+\n
+    /**\n
+     * List of messages being reported.\n
+     * @property messages\n
+     * @type String[]\n
+     */\n
+    this.messages = [];\n
+\n
+    /**\n
+     * List of statistics being reported.\n
+     * @property stats\n
+     * @type String[]\n
+     */\n
+    this.stats = [];\n
+\n
+    /**\n
+     * Lines of code being reported on. Used to provide contextual information\n
+     * for messages.\n
+     * @property lines\n
+     * @type String[]\n
+     */\n
+    this.lines = lines;\n
+\n
+    /**\n
+     * Information about the rules. Used to determine whether an issue is an\n
+     * error or warning.\n
+     * @property ruleset\n
+     * @type Object\n
+     */\n
+    this.ruleset = ruleset;\n
+}\n
+\n
+Reporter.prototype = {\n
+\n
+    //restore constructor\n
+    constructor: Reporter,\n
+\n
+    /**\n
+     * Report an error.\n
+     * @param {String} message The message to store.\n
+     * @param {int} line The line number.\n
+     * @param {int} col The column number.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method error\n
+     */\n
+    error: function(message, line, col, rule){\n
+        this.messages.push({\n
+            type    : "error",\n
+            line    : line,\n
+            col     : col,\n
+            message : message,\n
+            evidence: this.lines[line-1],\n
+            rule    : rule || {}\n
+        });\n
+    },\n
+\n
+    /**\n
+     * Report an warning.\n
+     * @param {String} message The message to store.\n
+     * @param {int} line The line number.\n
+     * @param {int} col The column number.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method warn\n
+     * @deprecated Use report instead.\n
+     */\n
+    warn: function(message, line, col, rule){\n
+        this.report(message, line, col, rule);\n
+    },\n
+\n
+    /**\n
+     * Report an issue.\n
+     * @param {String} message The message to store.\n
+     * @param {int} line The line number.\n
+     * @param {int} col The column number.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method report\n
+     */\n
+    report: function(message, line, col, rule){\n
+        this.messages.push({\n
+            type    : this.ruleset[rule.id] == 2 ? "error" : "warning",\n
+            line    : line,\n
+            col     : col,\n
+            message : message,\n
+            evidence: this.lines[line-1],\n
+            rule    : rule\n
+        });\n
+    },\n
+\n
+    /**\n
+     * Report some informational text.\n
+     * @param {String} message The message to store.\n
+     * @param {int} line The line number.\n
+     * @param {int} col The column number.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method info\n
+     */\n
+    info: function(message, line, col, rule){\n
+        this.messages.push({\n
+            type    : "info",\n
+            line    : line,\n
+            col     : col,\n
+            message : message,\n
+            evidence: this.lines[line-1],\n
+            rule    : rule\n
+        });\n
+    },\n
+\n
+    /**\n
+     * Report some rollup error information.\n
+     * @param {String} message The message to store.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method rollupError\n
+     */\n
+    rollupError: function(message, rule){\n
+        this.messages.push({\n
+            type    : "error",\n
+            rollup  : true,\n
+            message : message,\n
+            rule    : rule\n
+        });\n
+    },\n
+\n
+    /**\n
+     * Report some rollup warning information.\n
+     * @param {String} message The message to store.\n
+     * @param {Object} rule The rule this message relates to.\n
+     * @method rollupWarn\n
+     */\n
+    rollupWarn: function(message, rule){\n
+        this.messages.push({\n
+            type    : "warning",\n
+            rollup  : true,\n
+            message : message,\n
+            rule    : rule\n
+        });\n
+    },\n
+\n
+    /**\n
+     * Report a statistic.\n
+     * @param {String} name The name of the stat to store.\n
+     * @param {Variant} value The value of the stat.\n
+     * @method stat\n
+     */\n
+    stat: function(name, value){\n
+        this.stats[name] = value;\n
+    }\n
+};\n
+\n
+//expose for testing purposes\n
+CSSLint._Reporter = Reporter;\n
+\n
+/*global CSSLint*/\n
+\n
+/*\n
+ * Utility functions that make life easier.\n
+ */\n
+CSSLint.Util = {\n
+    /*\n
+     * Adds all properties from supplier onto receiver,\n
+     * overwriting if the same name already exists on\n
+     * reciever.\n
+     * @param {Object} The object to receive the properties.\n
+     * @param {Object} The object to provide the properties.\n
+     * @return {Object} The receiver\n
+     */\n
+    mix: function(receiver, supplier){\n
+        var prop;\n
+\n
+        for (prop in supplier){\n
+            if (supplier.hasOwnProperty(prop)){\n
+                receiver[prop] = supplier[prop];\n
+            }\n
+        }\n
+\n
+        return prop;\n
+    },\n
+\n
+    /*\n
+     * Polyfill for array indexOf() method.\n
+     * @param {Array} values The array to search.\n
+     * @param {Variant} value The value to search for.\n
+     * @return {int} The index of the value if found, -1 if not.\n
+     */\n
+    indexOf: function(values, value){\n
+        if (values.indexOf){\n
+            return values.indexOf(value);\n
+        } else {\n
+            for (var i=0, len=values.length; i < len; i++){\n
+                if (values[i] === value){\n
+                    return i;\n
+                }\n
+            }\n
+            return -1;\n
+        }\n
+    },\n
+\n
+    /*\n
+     * Polyfill for array forEach() method.\n
+     * @param {Array} values The array to operate on.\n
+     * @param {Function} func The function to call on each item.\n
+     * @return {void}\n
+     */\n
+    forEach: function(values, func) {\n
+        if (values.forEach){\n
+            return values.forEach(func);\n
+        } else {\n
+            for (var i=0, len=values.length; i < len; i++){\n
+                func(values[i], i, values);\n
+            }\n
+        }\n
+    }\n
+};\n
+/*global CSSLint*/\n
+/*\n
+ * Rule: Don\'t use adjoining classes (.foo.bar).\n
+ */\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "adjoining-classes",\n
+    name: "Disallow adjoining classes",\n
+    desc: "Don\'t use adjoining classes.",\n
+    browsers: "IE6",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                classCount,\n
+                i, j, k;\n
+\n
+            for (i=0; i < selectors.length; i++){\n
+                selector = selectors[i];\n
+                for (j=0; j < selector.parts.length; j++){\n
+                    part = selector.parts[j];\n
+                    if (part.type == parser.SELECTOR_PART_TYPE){\n
+                        classCount = 0;\n
+                        for (k=0; k < part.modifiers.length; k++){\n
+                            modifier = part.modifiers[k];\n
+                            if (modifier.type == "class"){\n
+                                classCount++;\n
+                            }\n
+                            if (classCount > 1){\n
+                                reporter.report("Don\'t use adjoining classes.", part.line, part.col, rule);\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*global CSSLint*/\n
+\n
+/*\n
+ * Rule: Don\'t use width or height when using padding or border.\n
+ */\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "box-model",\n
+    name: "Beware of broken box size",\n
+    desc: "Don\'t use width or height when using padding or border.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            widthProperties = {\n
+                border: 1,\n
+                "border-left": 1,\n
+                "border-right": 1,\n
+                padding: 1,\n
+                "padding-left": 1,\n
+                "padding-right": 1\n
+            },\n
+            heightProperties = {\n
+                border: 1,\n
+                "border-bottom": 1,\n
+                "border-top": 1,\n
+                padding: 1,\n
+                "padding-bottom": 1,\n
+                "padding-top": 1\n
+            },\n
+            properties,\n
+            boxSizing = false;\n
+\n
+        function startRule(){\n
+            properties = {};\n
+            boxSizing = false;\n
+        }\n
+\n
+        function endRule(){\n
+            var prop, value;\n
+\n
+            if (!boxSizing) {\n
+                if (properties.height){\n
+                    for (prop in heightProperties){\n
+                        if (heightProperties.hasOwnProperty(prop) && properties[prop]){\n
+                            value = properties[prop].value;\n
+                            //special case for padding\n
+                            if (!(prop == "padding" && value.parts.length === 2 && value.parts[0].value === 0)){\n
+                                reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+\n
+                if (properties.width){\n
+                    for (prop in widthProperties){\n
+                        if (widthProperties.hasOwnProperty(prop) && properties[prop]){\n
+                            value = properties[prop].value;\n
+\n
+                            if (!(prop == "padding" && value.parts.length === 2 && value.parts[1].value === 0)){\n
+                                reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startpage", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase();\n
+\n
+            if (heightProperties[name] || widthProperties[name]){\n
+                if (!/^0\\S*$/.test(event.value) && !(name == "border" && event.value == "none")){\n
+                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };\n
+                }\n
+            } else {\n
+                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)){\n
+                    properties[name] = 1;\n
+                } else if (name == "box-sizing") {\n
+                    boxSizing = true;\n
+                }\n
+            }\n
+\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+        parser.addListener("endpage", endRule);\n
+        parser.addListener("endpagemargin", endRule);\n
+        parser.addListener("endkeyframerule", endRule);\n
+    }\n
+\n
+});\n
+/*global CSSLint*/\n
+\n
+/*\n
+ * Rule: box-sizing doesn\'t work in IE6 and IE7.\n
+ */\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "box-sizing",\n
+    name: "Disallow use of box-sizing",\n
+    desc: "The box-sizing properties isn\'t supported in IE6 and IE7.",\n
+    browsers: "IE6, IE7",\n
+    tags: ["Compatibility"],\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase();\n
+\n
+            if (name == "box-sizing"){\n
+                reporter.report("The box-sizing property isn\'t supported in IE6 and IE7.", event.line, event.col, rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Use the bulletproof @font-face syntax to avoid 404\'s in old IE\n
+ * (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax)\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "bulletproof-font-face",\n
+    name: "Use the bulletproof @font-face syntax",\n
+    desc: "Use the bulletproof @font-face syntax to avoid 404\'s in old IE (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax).",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0,\n
+            fontFaceRule = false,\n
+            firstSrc     = true,\n
+            ruleFailed    = false,\n
+            line, col;\n
+\n
+        // Mark the start of a @font-face declaration so we only test properties inside it\n
+        parser.addListener("startfontface", function(event){\n
+            fontFaceRule = true;\n
+        });\n
+\n
+        parser.addListener("property", function(event){\n
+            // If we aren\'t inside an @font-face declaration then just return\n
+            if (!fontFaceRule) {\n
+                return;\n
+            }\n
+\n
+            var propertyName = event.property.toString().toLowerCase(),\n
+                value        = event.value.toString();\n
+\n
+            // Set the line and col numbers for use in the endfontface listener\n
+            line = event.line;\n
+            col  = event.col;\n
+\n
+            // This is the property that we care about, we can ignore the rest\n
+            if (propertyName === \'src\') {\n
+                var regex = /^\\s?url\\([\'"].+\\.eot\\?.*[\'"]\\)\\s*format\\([\'"]embedded-opentype[\'"]\\).*$/i;\n
+\n
+                // We need to handle the advanced syntax with two src properties\n
+                if (!value.match(regex) && firstSrc) {\n
+                    ruleFailed = true;\n
+                    firstSrc = false;\n
+                } else if (value.match(regex) && !firstSrc) {\n
+                    ruleFailed = false;\n
+                }\n
+            }\n
+\n
+\n
+        });\n
+\n
+        // Back to normal rules that we don\'t need to test\n
+        parser.addListener("endfontface", function(event){\n
+            fontFaceRule = false;\n
+\n
+            if (ruleFailed) {\n
+                reporter.report("@font-face declaration doesn\'t follow the fontspring bulletproof syntax.", line, col, rule);\n
+            }\n
+        });\n
+    }\n
+});\n
+/*\n
+ * Rule: Include all compatible vendor prefixes to reach a wider\n
+ * range of users.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "compatible-vendor-prefixes",\n
+    name: "Require compatible vendor prefixes",\n
+    desc: "Include all compatible vendor prefixes to reach a wider range of users.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function (parser, reporter) {\n
+        var rule = this,\n
+            compatiblePrefixes,\n
+            properties,\n
+            prop,\n
+            variations,\n
+            prefixed,\n
+            i,\n
+            len,\n
+            inKeyFrame = false,\n
+            arrayPush = Array.prototype.push,\n
+            applyTo = [];\n
+\n
+        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details\n
+        compatiblePrefixes = {\n
+            "animation"                  : "webkit moz",\n
+            "animation-delay"            : "webkit moz",\n
+            "animation-direction"        : "webkit moz",\n
+            "animation-duration"         : "webkit moz",\n
+            "animation-fill-mode"        : "webkit moz",\n
+            "animation-iteration-count"  : "webkit moz",\n
+            "animation-name"             : "webkit moz",\n
+            "animation-play-state"       : "webkit moz",\n
+            "animation-timing-function"  : "webkit moz",\n
+            "appearance"                 : "webkit moz",\n
+            "border-end"                 : "webkit moz",\n
+            "border-end-color"           : "webkit moz",\n
+            "border-end-style"           : "webkit moz",\n
+            "border-end-width"           : "webkit moz",\n
+            "border-image"               : "webkit moz o",\n
+            "border-radius"              : "webkit",\n
+            "border-start"               : "webkit moz",\n
+            "border-start-color"         : "webkit moz",\n
+            "border-start-style"         : "webkit moz",\n
+            "border-start-width"         : "webkit moz",\n
+            "box-align"                  : "webkit moz ms",\n
+            "box-direction"              : "webkit moz ms",\n
+            "box-flex"                   : "webkit moz ms",\n
+            "box-lines"                  : "webkit ms",\n
+            "box-ordinal-group"          : "webkit moz ms",\n
+            "box-orient"                 : "webkit moz ms",\n
+            "box-pack"                   : "webkit moz ms",\n
+            "box-sizing"                 : "webkit moz",\n
+            "box-shadow"                 : "webkit moz",\n
+            "column-count"               : "webkit moz ms",\n
+            "column-gap"                 : "webkit moz ms",\n
+            "column-rule"                : "webkit moz ms",\n
+            "column-rule-color"          : "webkit moz ms",\n
+            "column-rule-style"          : "webkit moz ms",\n
+            "column-rule-width"          : "webkit moz ms",\n
+            "column-width"               : "webkit moz ms",\n
+            "hyphens"                    : "epub moz",\n
+            "line-break"                 : "webkit ms",\n
+            "margin-end"                 : "webkit moz",\n
+            "margin-start"               : "webkit moz",\n
+            "marquee-speed"              : "webkit wap",\n
+            "marquee-style"              : "webkit wap",\n
+            "padding-end"                : "webkit moz",\n
+            "padding-start"              : "webkit moz",\n
+            "tab-size"                   : "moz o",\n
+            "text-size-adjust"           : "webkit ms",\n
+            "transform"                  
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>: "webkit moz ms o",\n
+            "transform-origin"           : "webkit moz ms o",\n
+            "transition"                 : "webkit moz o",\n
+            "transition-delay"           : "webkit moz o",\n
+            "transition-duration"        : "webkit moz o",\n
+            "transition-property"        : "webkit moz o",\n
+            "transition-timing-function" : "webkit moz o",\n
+            "user-modify"                : "webkit moz",\n
+            "user-select"                : "webkit moz ms",\n
+            "word-break"                 : "epub ms",\n
+            "writing-mode"               : "epub ms"\n
+        };\n
+\n
+\n
+        for (prop in compatiblePrefixes) {\n
+            if (compatiblePrefixes.hasOwnProperty(prop)) {\n
+                variations = [];\n
+                prefixed = compatiblePrefixes[prop].split(\' \');\n
+                for (i = 0, len = prefixed.length; i \074 len; i++) {\n
+                    variations.push(\'-\' + prefixed[i] + \'-\' + prop);\n
+                }\n
+                compatiblePrefixes[prop] = variations;\n
+                arrayPush.apply(applyTo, variations);\n
+            }\n
+        }\n
+\n
+        parser.addListener("startrule", function () {\n
+            properties = [];\n
+        });\n
+\n
+        parser.addListener("startkeyframes", function (event) {\n
+            inKeyFrame = event.prefix || true;\n
+        });\n
+\n
+        parser.addListener("endkeyframes", function (event) {\n
+            inKeyFrame = false;\n
+        });\n
+\n
+        parser.addListener("property", function (event) {\n
+            var name = event.property;\n
+            if (CSSLint.Util.indexOf(applyTo, name.text) \076 -1) {\n
+\n
+                // e.g., -moz-transform is okay to be alone in @-moz-keyframes\n
+                if (!inKeyFrame || typeof inKeyFrame != "string" ||\n
+                        name.text.indexOf("-" + inKeyFrame + "-") !== 0) {\n
+                    properties.push(name);\n
+                }\n
+            }\n
+        });\n
+\n
+        parser.addListener("endrule", function (event) {\n
+            if (!properties.length) {\n
+                return;\n
+            }\n
+\n
+            var propertyGroups = {},\n
+                i,\n
+                len,\n
+                name,\n
+                prop,\n
+                variations,\n
+                value,\n
+                full,\n
+                actual,\n
+                item,\n
+                propertiesSpecified;\n
+\n
+            for (i = 0, len = properties.length; i \074 len; i++) {\n
+                name = properties[i];\n
+\n
+                for (prop in compatiblePrefixes) {\n
+                    if (compatiblePrefixes.hasOwnProperty(prop)) {\n
+                        variations = compatiblePrefixes[prop];\n
+                        if (CSSLint.Util.indexOf(variations, name.text) \076 -1) {\n
+                            if (!propertyGroups[prop]) {\n
+                                propertyGroups[prop] = {\n
+                                    full : variations.slice(0),\n
+                                    actual : [],\n
+                                    actualNodes: []\n
+                                };\n
+                            }\n
+                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {\n
+                                propertyGroups[prop].actual.push(name.text);\n
+                                propertyGroups[prop].actualNodes.push(name);\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+\n
+            for (prop in propertyGroups) {\n
+                if (propertyGroups.hasOwnProperty(prop)) {\n
+                    value = propertyGroups[prop];\n
+                    full = value.full;\n
+                    actual = value.actual;\n
+\n
+                    if (full.length \076 actual.length) {\n
+                        for (i = 0, len = full.length; i \074 len; i++) {\n
+                            item = full[i];\n
+                            if (CSSLint.Util.indexOf(actual, item) === -1) {\n
+                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(" and ") : actual.join(", ");\n
+                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule);\n
+                            }\n
+                        }\n
+\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+});\n
+/*\n
+ * Rule: Certain properties don\'t play well with certain display values.\n
+ * - float should not be used with inline-block\n
+ * - height, width, margin-top, margin-bottom, float should not be used with inline\n
+ * - vertical-align should not be used with block\n
+ * - margin, float should not be used with table-*\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "display-property-grouping",\n
+    name: "Require properties appropriate for display",\n
+    desc: "Certain properties shouldn\'t be used with certain display property values.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        var propertiesToCheck = {\n
+                display: 1,\n
+                "float": "none",\n
+                height: 1,\n
+                width: 1,\n
+                margin: 1,\n
+                "margin-left": 1,\n
+                "margin-right": 1,\n
+                "margin-bottom": 1,\n
+                "margin-top": 1,\n
+                padding: 1,\n
+                "padding-left": 1,\n
+                "padding-right": 1,\n
+                "padding-bottom": 1,\n
+                "padding-top": 1,\n
+                "vertical-align": 1\n
+            },\n
+            properties;\n
+\n
+        function reportProperty(name, display, msg){\n
+            if (properties[name]){\n
+                if (typeof propertiesToCheck[name] != "string" || properties[name].value.toLowerCase() != propertiesToCheck[name]){\n
+                    reporter.report(msg || name + " can\'t be used with display: " + display + ".", properties[name].line, properties[name].col, rule);\n
+                }\n
+            }\n
+        }\n
+\n
+        function startRule(){\n
+            properties = {};\n
+        }\n
+\n
+        function endRule(){\n
+\n
+            var display = properties.display ? properties.display.value : null;\n
+            if (display){\n
+                switch(display){\n
+\n
+                    case "inline":\n
+                        //height, width, margin-top, margin-bottom, float should not be used with inline\n
+                        reportProperty("height", display);\n
+                        reportProperty("width", display);\n
+                        reportProperty("margin", display);\n
+                        reportProperty("margin-top", display);\n
+                        reportProperty("margin-bottom", display);\n
+                        reportProperty("float", display, "display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");\n
+                        break;\n
+\n
+                    case "block":\n
+                        //vertical-align should not be used with block\n
+                        reportProperty("vertical-align", display);\n
+                        break;\n
+\n
+                    case "inline-block":\n
+                        //float should not be used with inline-block\n
+                        reportProperty("float", display);\n
+                        break;\n
+\n
+                    default:\n
+                        //margin, float should not be used with table\n
+                        if (display.indexOf("table-") === 0){\n
+                            reportProperty("margin", display);\n
+                            reportProperty("margin-left", display);\n
+                            reportProperty("margin-right", display);\n
+                            reportProperty("margin-top", display);\n
+                            reportProperty("margin-bottom", display);\n
+                            reportProperty("float", display);\n
+                        }\n
+\n
+                        //otherwise do nothing\n
+                }\n
+            }\n
+\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startpage", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase();\n
+\n
+            if (propertiesToCheck[name]){\n
+                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };\n
+            }\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+        parser.addListener("endkeyframerule", endRule);\n
+        parser.addListener("endpagemargin", endRule);\n
+        parser.addListener("endpage", endRule);\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Disallow duplicate background-images (using url).\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "duplicate-background-images",\n
+    name: "Disallow duplicate background images",\n
+    desc: "Every background-image should be unique. Use a common class for e.g. sprites.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            stack = {};\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text,\n
+                value = event.value,\n
+                i, len;\n
+\n
+            if (name.match(/background/i)) {\n
+                for (i=0, len=value.parts.length; i \074 len; i++) {\n
+                    if (value.parts[i].type == \'uri\') {\n
+                        if (typeof stack[value.parts[i].uri] === \'undefined\') {\n
+                            stack[value.parts[i].uri] = event;\n
+                        }\n
+                        else {\n
+                            reporter.report("Background image \'" + value.parts[i].uri + "\' was used multiple times, first declared at line " + stack[value.parts[i].uri].line + ", col " + stack[value.parts[i].uri].col + ".", event.line, event.col, rule);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+});\n
+/*\n
+ * Rule: Duplicate properties must appear one after the other. If an already-defined\n
+ * property appears somewhere else in the rule, then it\'s likely an error.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "duplicate-properties",\n
+    name: "Disallow duplicate properties",\n
+    desc: "Duplicate properties must appear one after the other.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            properties,\n
+            lastProperty;\n
+\n
+        function startRule(event){\n
+            properties = {};\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startpage", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var property = event.property,\n
+                name = property.text.toLowerCase();\n
+\n
+            if (properties[name] \046\046 (lastProperty != name || properties[name] == event.value.text)){\n
+                reporter.report("Duplicate property \'" + event.property + "\' found.", event.line, event.col, rule);\n
+            }\n
+\n
+            properties[name] = event.value.text;\n
+            lastProperty = name;\n
+\n
+        });\n
+\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Style rules without any properties defined should be removed.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "empty-rules",\n
+    name: "Disallow empty rules",\n
+    desc: "Rules without any properties specified should be removed.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0;\n
+\n
+        parser.addListener("startrule", function(){\n
+            count=0;\n
+        });\n
+\n
+        parser.addListener("property", function(){\n
+            count++;\n
+        });\n
+\n
+        parser.addListener("endrule", function(event){\n
+            var selectors = event.selectors;\n
+            if (count === 0){\n
+                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: There should be no syntax errors. (Duh.)\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "errors",\n
+    name: "Parsing Errors",\n
+    desc: "This rule looks for recoverable syntax errors.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("error", function(event){\n
+            reporter.error(event.message, event.line, event.col, rule);\n
+        });\n
+\n
+    }\n
+\n
+});\n
+\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "fallback-colors",\n
+    name: "Require fallback colors",\n
+    desc: "For older browsers that don\'t support RGBA, HSL, or HSLA, provide a fallback color.",\n
+    browsers: "IE6,IE7,IE8",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            lastProperty,\n
+            propertiesToCheck = {\n
+                color: 1,\n
+                background: 1,\n
+                "border-color": 1,\n
+                "border-top-color": 1,\n
+                "border-right-color": 1,\n
+                "border-bottom-color": 1,\n
+                "border-left-color": 1,\n
+                border: 1,\n
+                "border-top": 1,\n
+                "border-right": 1,\n
+                "border-bottom": 1,\n
+                "border-left": 1,\n
+                "background-color": 1\n
+            },\n
+            properties;\n
+\n
+        function startRule(event){\n
+            properties = {};\n
+            lastProperty = null;\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startpage", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var property = event.property,\n
+                name = property.text.toLowerCase(),\n
+                parts = event.value.parts,\n
+                i = 0,\n
+                colorType = "",\n
+                len = parts.length;\n
+\n
+            if(propertiesToCheck[name]){\n
+                while(i \074 len){\n
+                    if (parts[i].type == "color"){\n
+                        if ("alpha" in parts[i] || "hue" in parts[i]){\n
+\n
+                            if (/([^\\)]+)\\(/.test(parts[i])){\n
+                                colorType = RegExp.$1.toUpperCase();\n
+                            }\n
+\n
+                            if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != "compat")){\n
+                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);\n
+                            }\n
+                        } else {\n
+                            event.colorType = "compat";\n
+                        }\n
+                    }\n
+\n
+                    i++;\n
+                }\n
+            }\n
+\n
+            lastProperty = event;\n
+        });\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: You shouldn\'t use more than 10 floats. If you do, there\'s probably\n
+ * room for some abstraction.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "floats",\n
+    name: "Disallow too many floats",\n
+    desc: "This rule tests if the float property is used too many times",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+        var count = 0;\n
+\n
+        //count how many times "float" is used\n
+        parser.addListener("property", function(event){\n
+            if (event.property.text.toLowerCase() == "float" \046\046\n
+                    event.value.text.toLowerCase() != "none"){\n
+                count++;\n
+            }\n
+        });\n
+\n
+        //report the results\n
+        parser.addListener("endstylesheet", function(){\n
+            reporter.stat("floats", count);\n
+            if (count \076= 10){\n
+                reporter.rollupWarn("Too many floats (" + count + "), you\'re probably using them for layout. Consider using a grid system instead.", rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Avoid too many @font-face declarations in the same stylesheet.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "font-faces",\n
+    name: "Don\'t use too many web fonts",\n
+    desc: "Too many different web fonts in the same stylesheet.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0;\n
+\n
+\n
+        parser.addListener("startfontface", function(){\n
+            count++;\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function(){\n
+            if (count \076 5){\n
+                reporter.rollupWarn("Too many @font-face declarations (" + count + ").", rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: You shouldn\'t need more than 9 font-size declarations.\n
+ */\n
+\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "font-sizes",\n
+    name: "Disallow too many font sizes",\n
+    desc: "Checks the number of font-size declarations.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0;\n
+\n
+        //check for use of "font-size"\n
+        parser.addListener("property", function(event){\n
+            if (event.property == "font-size"){\n
+                count++;\n
+            }\n
+        });\n
+\n
+        //report the results\n
+        parser.addListener("endstylesheet", function(){\n
+            reporter.stat("font-sizes", count);\n
+            if (count \076= 10){\n
+                reporter.rollupWarn("Too many font-size declarations (" + count + "), abstraction needed.", rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: When using a vendor-prefixed gradient, make sure to use them all.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "gradients",\n
+    name: "Require all gradient definitions",\n
+    desc: "When using a vendor-prefixed gradient, make sure to use them all.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            gradients;\n
+\n
+        parser.addListener("startrule", function(){\n
+            gradients = {\n
+                moz: 0,\n
+                webkit: 0,\n
+                oldWebkit: 0,\n
+                o: 0\n
+            };\n
+        });\n
+\n
+        parser.addListener("property", function(event){\n
+\n
+            if (/\\-(moz|o|webkit)(?:\\-(?:linear|radial))\\-gradient/i.test(event.value)){\n
+                gradients[RegExp.$1] = 1;\n
+            } else if (/\\-webkit\\-gradient/i.test(event.value)){\n
+                gradients.oldWebkit = 1;\n
+            }\n
+\n
+        });\n
+\n
+        parser.addListener("endrule", function(event){\n
+            var missing = [];\n
+\n
+            if (!gradients.moz){\n
+                missing.push("Firefox 3.6+");\n
+            }\n
+\n
+            if (!gradients.webkit){\n
+                missing.push("Webkit (Safari 5+, Chrome)");\n
+            }\n
+\n
+            if (!gradients.oldWebkit){\n
+                missing.push("Old Webkit (Safari 4+, Chrome)");\n
+            }\n
+\n
+            if (!gradients.o){\n
+                missing.push("Opera 11.1+");\n
+            }\n
+\n
+            if (missing.length \046\046 missing.length \074 4){\n
+                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule);\n
+            }\n
+\n
+        });\n
+\n
+    }\n
+\n
+});\n
+\n
+/*\n
+ * Rule: Don\'t use IDs for selectors.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "ids",\n
+    name: "Disallow IDs in selectors",\n
+    desc: "Selectors should not contain IDs.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                idCount,\n
+                i, j, k;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+                idCount = 0;\n
+\n
+                for (j=0; j \074 selector.parts.length; j++){\n
+                    part = selector.parts[j];\n
+                    if (part.type == parser.SELECTOR_PART_TYPE){\n
+                        for (k=0; k \074 part.modifiers.length; k++){\n
+                            modifier = part.modifiers[k];\n
+                            if (modifier.type == "id"){\n
+                                idCount++;\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+\n
+                if (idCount == 1){\n
+                    reporter.report("Don\'t use IDs in selectors.", selector.line, selector.col, rule);\n
+                } else if (idCount \076 1){\n
+                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);\n
+                }\n
+            }\n
+\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use @import, use \074link\076 instead.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "import",\n
+    name: "Disallow @import",\n
+    desc: "Don\'t use @import, use \074link\076 instead.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("import", function(event){\n
+            reporter.report("@import prevents parallel downloads, use \074link\076 instead.", event.line, event.col, rule);\n
+        });\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Make sure !important is not overused, this could lead to specificity\n
+ * war. Display a warning on !important declarations, an error if it\'s\n
+ * used more at least 10 times.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "important",\n
+    name: "Disallow !important",\n
+    desc: "Be careful when using !important declaration",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0;\n
+\n
+        //warn that important is used and increment the declaration counter\n
+        parser.addListener("property", function(event){\n
+            if (event.important === true){\n
+                count++;\n
+                reporter.report("Use of !important", event.line, event.col, rule);\n
+            }\n
+        });\n
+\n
+        //if there are more than 10, show an error\n
+        parser.addListener("endstylesheet", function(){\n
+            reporter.stat("important", count);\n
+            if (count \076= 10){\n
+                reporter.rollupWarn("Too many !important declarations (" + count + "), try to use less than 10 to avoid specificity issues.", rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Properties should be known (listed in CSS3 specification) or\n
+ * be a vendor-prefixed property.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "known-properties",\n
+    name: "Require use of known properties",\n
+    desc: "Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase();\n
+\n
+            // the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)\n
+            if (event.invalid) {\n
+                reporter.report(event.invalid.message, event.line, event.col, rule);\n
+            }\n
+\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: outline: none or outline: 0 should only be used in a :focus rule\n
+ *       and only if there are other properties in the same rule.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "outline-none",\n
+    name: "Disallow outline: none",\n
+    desc: "Use of outline: none or outline: 0 should be limited to :focus rules.",\n
+    browsers: "All",\n
+    tags: ["Accessibility"],\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            lastRule;\n
+\n
+        function startRule(event){\n
+            if (event.selectors){\n
+                lastRule = {\n
+                    line: event.line,\n
+                    col: event.col,\n
+                    selectors: event.selectors,\n
+                    propCount: 0,\n
+                    outline: false\n
+                };\n
+            } else {\n
+                lastRule = null;\n
+            }\n
+        }\n
+\n
+        function endRule(event){\n
+            if (lastRule){\n
+                if (lastRule.outline){\n
+                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") == -1){\n
+                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);\n
+                    } else if (lastRule.propCount == 1) {\n
+                        reporter.report("Outlines shouldn\'t be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);\n
+                    }\n
+                }\n
+            }\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startpage", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase(),\n
+                value = event.value;\n
+\n
+            if (lastRule){\n
+                lastRule.propCount++;\n
+                if (name == "outline" \046\046 (value == "none" || value == "0")){\n
+                    lastRule.outline = true;\n
+                }\n
+            }\n
+\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+        parser.addListener("endpage", endRule);\n
+        parser.addListener("endpagemargin", endRule);\n
+        parser.addListener("endkeyframerule", endRule);\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use classes or IDs with elements (a.foo or a#foo).\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "overqualified-elements",\n
+    name: "Disallow overqualified elements",\n
+    desc: "Don\'t use classes or IDs with elements (a.foo or a#foo).",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            classes = {};\n
+\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                i, j, k;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+\n
+                for (j=0; j \074 selector.parts.length; j++){\n
+                    part = selector.parts[j];\n
+                    if (part.type == parser.SELECTOR_PART_TYPE){\n
+                        for (k=0; k \074 part.modifiers.length; k++){\n
+                            modifier = part.modifiers[k];\n
+                            if (part.elementName \046\046 modifier.type == "id"){\n
+                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);\n
+                            } else if (modifier.type == "class"){\n
+\n
+                                if (!classes[modifier]){\n
+                                    classes[modifier] = [];\n
+                                }\n
+                                classes[modifier].push({ modifier: modifier, part: part });\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function(){\n
+\n
+            var prop;\n
+            for (prop in classes){\n
+                if (classes.hasOwnProperty(prop)){\n
+\n
+                    //one use means that this is overqualified\n
+                    if (classes[prop].length == 1 \046\046 classes[prop][0].part.elementName){\n
+                        reporter.report("Element (" + classes[prop][0].part + ") is overqualified, just use " + classes[prop][0].modifier + " without element name.", classes[prop][0].part.line, classes[prop][0].part.col, rule);\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Headings (h1-h6) should not be qualified (namespaced).\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "qualified-headings",\n
+    name: "Disallow qualified headings",\n
+    desc: "Headings should not be qualified (namespaced).",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                i, j;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+\n
+                for (j=0; j \074 selector.parts.length; j++){\n
+                    part = selector.parts[j];\n
+                    if (part.type == parser.SELECTOR_PART_TYPE){\n
+                        if (part.elementName \046\046 /h[1-6]/.test(part.elementName.toString()) \046\046 j \076 0){\n
+                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Selectors that look like regular expressions are slow and should be avoided.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "regex-selectors",\n
+    name: "Disallow selectors that look like regexs",\n
+    desc: "Selectors that look like regular expressions are slow and should be avoided.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                i, j, k;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+                for (j=0; j \074 selector.parts.length; j++){\n
+                    part = selector.parts[j];\n
+                    if (part.type == parser.SELECTOR_PART_TYPE){\n
+                        for (k=0; k \074 part.modifiers.length; k++){\n
+                            modifier = part.modifiers[k];\n
+                            if (modifier.type == "attribute"){\n
+                                if (/([\\~\\|\\^\\$\\*]=)/.test(modifier)){\n
+                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);\n
+                                }\n
+                            }\n
+\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Total number of rules should not exceed x.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "rules-count",\n
+    name: "Rules Count",\n
+    desc: "Track how many rules there are.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            count = 0;\n
+\n
+        //count each rule\n
+        parser.addListener("startrule", function(){\n
+            count++;\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function(){\n
+            reporter.stat("rule-count", count);\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Warn people with approaching the IE 4095 limit\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "selector-max-approaching",\n
+    name: "Warn when approaching the 4095 selector limit for IE",\n
+    desc: "Will warn when selector count is \076= 3800 selectors.",\n
+    browsers: "IE",\n
+\n
+    //initialization\n
+    init: function(parser, reporter) {\n
+        var rule = this, count = 0;\n
+\n
+        parser.addListener(\'startrule\', function(event) {\n
+            count += event.selectors.length;\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function() {\n
+            if (count \076= 3800) {\n
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.",0,0,rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+\n
+/*\n
+ * Rule: Warn people past the IE 4095 limit\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "selector-max",\n
+    name: "Error when past the 4095 selector limit for IE",\n
+    desc: "Will error when selector count is \076 4095.",\n
+    browsers: "IE",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this, count = 0;\n
+\n
+        parser.addListener(\'startrule\',function(event) {\n
+            count += event.selectors.length;\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function() {\n
+            if (count \076 4095) {\n
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.",0,0,rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Use shorthand properties where possible.\n
+ *\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "shorthand",\n
+    name: "Require shorthand properties",\n
+    desc: "Use shorthand properties where possible.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            prop, i, len,\n
+            propertiesToCheck = {},\n
+            properties,\n
+            mapping = {\n
+                "margin": [\n
+                    "margin-top",\n
+                    "margin-bottom",\n
+                    "margin-left",\n
+                    "margin-right"\n
+                ],\n
+                "padding": [\n
+                    "padding-top",\n
+                    "padding-bottom",\n
+                    "padding-left",\n
+                    "padding-right"\n
+                ]\n
+            };\n
+\n
+        //initialize propertiesToCheck\n
+        for (prop in mapping){\n
+            if (mapping.hasOwnProperty(prop)){\n
+                for (i=0, len=mapping[prop].length; i \074 len; i++){\n
+                    propertiesToCheck[mapping[prop][i]] = prop;\n
+                }\n
+            }\n
+        }\n
+\n
+        function startRule(event){\n
+            properties = {};\n
+        }\n
+\n
+        //event handler for end of rules\n
+        function endRule(event){\n
+\n
+            var prop, i, len, total;\n
+\n
+            //check which properties this rule has\n
+            for (prop in mapping){\n
+                if (mapping.hasOwnProperty(prop)){\n
+                    total=0;\n
+\n
+                    for (i=0, len=mapping[prop].length; i \074 len; i++){\n
+                        total += properties[mapping[prop][i]] ? 1 : 0;\n
+                    }\n
+\n
+                    if (total == mapping[prop].length){\n
+                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);\n
+                    }\n
+                }\n
+            }\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+\n
+        //check for use of "font-size"\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.toString().toLowerCase(),\n
+                value = event.value.parts[0].value;\n
+\n
+            if (propertiesToCheck[name]){\n
+                properties[name] = 1;\n
+            }\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use properties with a star prefix.\n
+ *\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "star-property-hack",\n
+    name: "Disallow properties with a star prefix",\n
+    desc: "Checks for the star property hack (targets IE6/7)",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        //check if property name starts with "*"\n
+        parser.addListener("property", function(event){\n
+            var property = event.property;\n
+\n
+            if (property.hack == "*") {\n
+                reporter.report("Property with star prefix found.", event.property.line, event.property.col, rule);\n
+            }\n
+        });\n
+    }\n
+});\n
+/*\n
+ * Rule: Don\'t use text-indent for image replacement if you need to support rtl.\n
+ *\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "text-indent",\n
+    name: "Disallow negative text-indent",\n
+    desc: "Checks for text indent less than -99px",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            textIndent,\n
+            direction;\n
+\n
+\n
+        function startRule(event){\n
+            textIndent = false;\n
+            direction = "inherit";\n
+        }\n
+\n
+        //event handler for end of rules\n
+        function endRule(event){\n
+            if (textIndent \046\046 direction != "ltr"){\n
+                reporter.report("Negative text-indent doesn\'t work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.", textIndent.line, textIndent.col, rule);\n
+            }\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+\n
+        //check for use of "font-size"\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.toString().toLowerCase(),\n
+                value = event.value;\n
+\n
+            if (name == "text-indent" \046\046 value.parts[0].value \074 -99){\n
+                textIndent = event.property;\n
+            } else if (name == "direction" \046\046 value == "ltr"){\n
+                direction = "ltr";\n
+            }\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use properties with a underscore prefix.\n
+ *\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "underscore-property-hack",\n
+    name: "Disallow properties with an underscore prefix",\n
+    desc: "Checks for the underscore property hack (targets IE6)",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        //check if property name starts with "_"\n
+        parser.addListener("property", function(event){\n
+            var property = event.property;\n
+\n
+            if (property.hack == "_") {\n
+                reporter.report("Property with underscore prefix found.", event.property.line, event.property.col, rule);\n
+            }\n
+        });\n
+    }\n
+});\n
+/*\n
+ * Rule: Headings (h1-h6) should be defined only once.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "unique-headings",\n
+    name: "Headings should only be defined once",\n
+    desc: "Headings should be defined only once.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        var headings =  {\n
+                h1: 0,\n
+                h2: 0,\n
+                h3: 0,\n
+                h4: 0,\n
+                h5: 0,\n
+                h6: 0\n
+            };\n
+\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                pseudo,\n
+                i, j;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+                part = selector.parts[selector.parts.length-1];\n
+\n
+                if (part.elementName \046\046 /(h[1-6])/i.test(part.elementName.toString())){\n
+\n
+                    for (j=0; j \074 part.modifiers.length; j++){\n
+                        if (part.modifiers[j].type == "pseudo"){\n
+                            pseudo = true;\n
+                            break;\n
+                        }\n
+                    }\n
+\n
+                    if (!pseudo){\n
+                        headings[RegExp.$1]++;\n
+                        if (headings[RegExp.$1] \076 1) {\n
+                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        });\n
+\n
+        parser.addListener("endstylesheet", function(event){\n
+            var prop,\n
+                messages = [];\n
+\n
+            for (prop in headings){\n
+                if (headings.hasOwnProperty(prop)){\n
+                    if (headings[prop] \076 1){\n
+                        messages.push(headings[prop] + " " + prop + "s");\n
+                    }\n
+                }\n
+            }\n
+\n
+            if (messages.length){\n
+                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use universal selector because it\'s slow.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "universal-selector",\n
+    name: "Disallow universal selector",\n
+    desc: "The universal selector (*) is known to be slow.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("startrule", function(event){\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                i, j, k;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+\n
+                part = selector.parts[selector.parts.length-1];\n
+                if (part.elementName == "*"){\n
+                    reporter.report(rule.desc, part.line, part.col, rule);\n
+                }\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: Don\'t use unqualified attribute selectors because they\'re just like universal selectors.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "unqualified-attributes",\n
+    name: "Disallow unqualified attribute selectors",\n
+    desc: "Unqualified attribute selectors are known to be slow.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        parser.addListener("startrule", function(event){\n
+\n
+            var selectors = event.selectors,\n
+                selector,\n
+                part,\n
+                modifier,\n
+                i, j, k;\n
+\n
+            for (i=0; i \074 selectors.length; i++){\n
+                selector = selectors[i];\n
+\n
+                part = selector.parts[selector.parts.length-1];\n
+                if (part.type == parser.SELECTOR_PART_TYPE){\n
+                    for (k=0; k \074 part.modifiers.length; k++){\n
+                        modifier = part.modifiers[k];\n
+                        if (modifier.type == "attribute" \046\046 (!part.elementName || part.elementName == "*")){\n
+                            reporter.report(rule.desc, part.line, part.col, rule);\n
+                        }\n
+                    }\n
+                }\n
+\n
+            }\n
+        });\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: When using a vendor-prefixed property, make sure to\n
+ * include the standard one.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "vendor-prefix",\n
+    name: "Require standard property with vendor prefix",\n
+    desc: "When using a vendor-prefixed property, make sure to include the standard one.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this,\n
+            properties,\n
+            num,\n
+            propertiesToCheck = {\n
+                "-webkit-border-radius": "border-radius",\n
+                "-webkit-border-top-left-radius": "border-top-left-radius",\n
+                "-webkit-border-top-right-radius": "border-top-right-radius",\n
+                "-webkit-border-bottom-left-radius": "border-bottom-left-radius",\n
+                "-webkit-border-bottom-right-radius": "border-bottom-right-radius",\n
+\n
+                "-o-border-radius": "border-radius",\n
+                "-o-border-top-left-radius": "border-top-left-radius",\n
+                "-o-border-top-right-radius": "border-top-right-radius",\n
+                "-o-border-bottom-left-radius": "border-bottom-left-radius",\n
+                "-o-border-bottom-right-radius": "border-bottom-right-radius",\n
+\n
+                "-moz-border-radius": "border-radius",\n
+                "-moz-border-radius-topleft": "border-top-left-radius",\n
+                "-moz-border-radius-topright": "border-top-right-radius",\n
+                "-moz-border-radius-bottomleft": "border-bottom-left-radius",\n
+                "-moz-border-radius-bottomright": "border-bottom-right-radius",\n
+\n
+                "-moz-column-count": "column-count",\n
+                "-webkit-column-count": "column-count",\n
+\n
+                "-moz-column-gap": "column-gap",\n
+                "-webkit-column-gap": "column-gap",\n
+\n
+                "-moz-column-rule": "column-rule",\n
+                "-webkit-column-rule": "column-rule",\n
+\n
+                "-moz-column-rule-style": "column-rule-style",\n
+                "-webkit-column-rule-style": "column-rule-style",\n
+\n
+                "-moz-column-rule-color": "column-rule-color",\n
+                "-webkit-column-rule-color": "column-rule-color",\n
+\n
+                "-moz-column-rule-width": "column-rule-width",\n
+                "-webkit-column-rule-width": "column-rule-width",\n
+\n
+                "-moz-column-width": "column-width",\n
+                "-webkit-column-width": "column-width",\n
+\n
+                "-webkit-column-span": "column-span",\n
+                "-webkit-columns": "columns",\n
+\n
+                "-moz-box-shadow": "box-shadow",\n
+                "-webkit-box-shadow": "box-shadow",\n
+\n
+                "-moz-transform" : "transform",\n
+                "-webkit-transform" : "transform",\n
+                "-o-transform" : "transform",\n
+                "-ms-transform" : "transform",\n
+\n
+                "-moz-transform-origin" : "transform-origin",\n
+                "-webkit-transform-origin" : "transform-origin",\n
+                "-o-transform-origin" : "transform-origin",\n
+                "-ms-transform-origin" : "transform-origin",\n
+\n
+                "-moz-box-sizing" : "box-sizing",\n
+                "-webkit-box-sizing" : "box-sizing",\n
+\n
+                "-moz-user-select" : "user-select",\n
+                "-khtml-user-select" : "user-select",\n
+                "-webkit-user-select" : "user-select"\n
+            };\n
+\n
+        //event handler for beginning of rules\n
+        function startRule(){\n
+            properties = {};\n
+            num=1;\n
+        }\n
+\n
+        //event handler for end of rules\n
+        function endRule(event){\n
+            var prop,\n
+                i, len,\n
+                standard,\n
+                needed,\n
+                actual,\n
+                needsStandard = [];\n
+\n
+            for (prop in properties){\n
+                if (propertiesToCheck[prop]){\n
+                    needsStandard.push({ actual: prop, needed: propertiesToCheck[prop]});\n
+                }\n
+            }\n
+\n
+            for (i=0, len=needsStandard.length; i \074 len; i++){\n
+                needed = needsStandard[i].needed;\n
+                actual = needsStandard[i].actual;\n
+\n
+                if (!properties[needed]){\n
+                    reporter.report("Missing standard property \'" + needed + "\' to go along with \'" + actual + "\'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n
+                } else {\n
+                    //make sure standard property is last\n
+                    if (properties[needed][0].pos \074 properties[actual][0].pos){\n
+                        reporter.report("Standard property \'" + needed + "\' should come after vendor-prefixed property \'" + actual + "\'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n
+                    }\n
+                }\n
+            }\n
+\n
+        }\n
+\n
+        parser.addListener("startrule", startRule);\n
+        parser.addListener("startfontface", startRule);\n
+        parser.addListener("startpage", startRule);\n
+        parser.addListener("startpagemargin", startRule);\n
+        parser.addListener("startkeyframerule", startRule);\n
+\n
+        parser.addListener("property", function(event){\n
+            var name = event.property.text.toLowerCase();\n
+\n
+            if (!properties[name]){\n
+                properties[name] = [];\n
+            }\n
+\n
+            properties[name].push({ name: event.property, value : event.value, pos:num++ });\n
+        });\n
+\n
+        parser.addListener("endrule", endRule);\n
+        parser.addListener("endfontface", endRule);\n
+        parser.addListener("endpage", endRule);\n
+        parser.addListener("endpagemargin", endRule);\n
+        parser.addListener("endkeyframerule", endRule);\n
+    }\n
+\n
+});\n
+/*\n
+ * Rule: You don\'t need to specify units when a value is 0.\n
+ */\n
+/*global CSSLint*/\n
+CSSLint.addRule({\n
+\n
+    //rule information\n
+    id: "zero-units",\n
+    name: "Disallow units for 0 values",\n
+    desc: "You don\'t need to specify units when a value is 0.",\n
+    browsers: "All",\n
+\n
+    //initialization\n
+    init: function(parser, reporter){\n
+        var rule = this;\n
+\n
+        //count how many times "float" is used\n
+        parser.addListener("property", function(event){\n
+            var parts = event.value.parts,\n
+                i = 0,\n
+                len = parts.length;\n
+\n
+            while(i \074 len){\n
+                if ((parts[i].units || parts[i].type == "percentage") \046\046 parts[i].value === 0 \046\046 parts[i].type != "time"){\n
+                    reporter.report("Values of 0 shouldn\'t have units specified.", parts[i].line, parts[i].col, rule);\n
+                }\n
+                i++;\n
+            }\n
+\n
+        });\n
+\n
+    }\n
+\n
+});\n
+/*global CSSLint*/\n
+(function() {\n
+\n
+    /**\n
+     * Replace special characters before write to output.\n
+     *\n
+     * Rules:\n
+     *  - single quotes is the escape sequence for double-quotes\n
+     *  - \046amp; is the escape sequence for \046\n
+     *  - \046lt; is the escape sequence for \074\n
+     *  - \046gt; is the escape sequence for \076\n
+     *\n
+     * @param {String} message to escape\n
+     * @return escaped message as {String}\n
+     */\n
+    var xmlEscape = function(str) {\n
+        if (!str || str.constructor !== String) {\n
+            return "";\n
+        }\n
+\n
+        return str.replace(/[\\"\046\076\074]/g, function(match) {\n
+            switch (match) {\n
+                case "\\"":\n
+                    return "\046quot;";\n
+                case "\046":\n
+                    return "\046amp;";\n
+                case "\074":\n
+                    return "\046lt;";\n
+                case "\076":\n
+                    return "\046gt;";\n
+            }\n
+        });\n
+    };\n
+\n
+    CSSLint.addFormatter({\n
+        //format information\n
+        id: "checkstyle-xml",\n
+        name: "Checkstyle XML format",\n
+\n
+        /**\n
+         * Return opening root XML tag.\n
+         * @return {String} to prepend before all results\n
+         */\n
+        startFormat: function(){\n
+            return "\074?xml version=\\"1.0\\" encoding=\\"utf-8\\"?\076\074checkstyle\076";\n
+        },\n
+\n
+        /**\n
+         * Return closing root XML tag.\n
+         * @return {String} to append after all results\n
+         */\n
+        endFormat: function(){\n
+            return "\074/checkstyle\076";\n
+        },\n
+\n
+        /**\n
+         * Returns message when there is a file read error.\n
+         * @param {String} filename The name of the file that caused the error.\n
+         * @param {String} message The error message\n
+         * @return {String} The error message.\n
+         */\n
+        readError: function(filename, message) {\n
+            return "\074file name=\\"" + xmlEscape(filename) + "\\"\076\074error line=\\"0\\" column=\\"0\\" severty=\\"error\\" message=\\"" + xmlEscape(message) + "\\"\076\074/error\076\074/file\076";\n
+        },\n
+\n
+        /**\n
+         * Given CSS Lint results for a file, return output for this format.\n
+         * @param results {Object} with error and warning messages\n
+         * @param filename {String} relative file path\n
+         * @param options {Object} (UNUSED for now) specifies special handling of output\n
+         * @return {String} output for results\n
+         */\n
+        formatResults: function(results, filename, options) {\n
+            var messages = results.messages,\n
+                output = [];\n
+\n
+            /**\n
+             * Generate a source string for a rule.\n
+             * Checkstyle source strings usually resemble Java class names e.g\n
+             * net.csslint.SomeRuleName\n
+             * @param {Object} rule\n
+             * @return rule source as {String}\n
+             */\n
+            var generateSource = function(rule) {\n
+                if (!rule || !(\'name\' in rule)) {\n
+                    return "";\n
+                }\n
+                return \'net.csslint.\' + rule.name.replace(/\\s/g,\'\');\n
+            };\n
+\n
+\n
+\n
+            if (messages.length \076 0) {\n
+                output.push("\074file name=\\""+filename+"\\"\076");\n
+                CSSLint.Util.forEach(messages, function (message, i) {\n
+                    //ignore rollups for now\n
+                    if (!message.rollup) {\n
+                      output.push("\074error line=\\"" + message.line + "\\" column=\\"" + message.col + "\\" severity=\\"" + message.type + "\\"" +\n
+                          " message=\\"" + xmlEscape(message.message) + "\\" source=\\"" + generateSource(message.rule) +"\\"/\076");\n
+                    }\n
+                });\n
+                output.push("\074/file\076");\n
+            }\n
+\n
+            return output.join("");\n
+        }\n
+    });\n
+\n
+}());\n
+/*global CSSLint*/\n
+CSSLint.addFormatter({\n
+    //format information\n
+    id: "compact",\n
+    name: "Compact, \'porcelain\' format",\n
+\n
+    /**\n
+     * Return content to be printed before all file results.\n
+     * @return {String} to prepend before all results\n
+     */\n
+    startFormat: function() {\n
+        return "";\n
+    },\n
+\n
+    /**\n
+     * Return content to be printed after all file results.\n
+     * @return {String} to append after all results\n
+     */\n
+    endFormat: function() {\n
+        return "";\n
+    },\n
+\n
+    /**\n
+     * Given CSS Lint results for a file, return output for this format.\n
+     * @param results {Object} with error and warning messages\n
+     * @param filename {String} relative file path\n
+     * @param options {Object} (Optional) specifies special handling of output\n
+     * @return {String} output for results\n
+     */\n
+    formatResults: function(results, filename, options) {\n
+        var messages = results.messages,\n
+            output = "";\n
+        options = options || {};\n
+\n
+        /**\n
+         * Capitalize and return given string.\n
+         * @param str {String} to capitalize\n
+         * @return {String} capitalized\n
+         */\n
+        var capitalize = function(str) {\n
+            return str.charAt(0).toUpperCase() + str.slice(1);\n
+        };\n
+\n
+        if (messages.length === 0) {\n
+            return options.quiet ? "" : filename + ": Lint Free!";\n
+        }\n
+\n
+        CSSLint.Util.forEach(messages, function(message, i) {\n
+            if (message.rollup) {\n
+                output += filename + ": " + capitalize(message.type) + " - " + message.message + "\\n";\n
+            } else {\n
+                output += filename + ": " + "line " + message.line +\n
+                    ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + "\\n";\n
+            }\n
+        });\n
+\n
+        return output;\n
+    }\n
+});\n
+/*global CSSLint*/\n
+CSSLint.addFormatter({\n
+    //format information\n
+    id: "csslint-xml",\n
+    name: "CSSLint XML format",\n
+\n
+    /**\n
+     * Return opening root XML tag.\n
+     * @return {String} to prepend before all results\n
+     */\n
+    startFormat: function(){\n
+        return "\074?xml version=\\"1.0\\" encoding=\\"utf-8\\"?\076\074csslint\076";\n
+    },\n
+\n
+    /**\n
+     * Return closing root XML tag.\n
+     * @return {String} to append after all results\n
+     */\n
+    endFormat: function(){\n
+        return "\074/csslint\076";\n
+    },\n
+\n
+    /**\n
+     * Given CSS Lint results for a file, return output for this format.\n
+     * @param results {Object} with error and warning messages\n
+     * @param filename {String} relative file path\n
+     * @param options {Object} (UNUSED for now) specifies special handling of output\n
+     * @return {String} output for results\n
+     */\n
+    formatResults: function(results, filename, options) {\n
+        var messages = results.messages,\n
+            output = [];\n
+\n
+        /**\n
+         * Replace special characters before write to output.\n
+         *\n
+         * Rules:\n
+         *  - single quotes is the escape sequence for double-quotes\n
+         *  - \046amp; is the escape sequence for \046\n
+         *  - \046lt; is the escape sequence for \074\n
+         *  - \046gt; is the escape sequence for \076\n
+         *\n
+         * @param {String} message to escape\n
+         * @return escaped message as {String}\n
+         */\n
+        var escapeSpecialCharacters = function(str) {\n
+            if (!str || str.constructor !== String) {\n
+                return "";\n
+            }\n
+            return str.replace(/\\"/g, "\'").replace(/\046/g, "\046amp;").replace(/\074/g, "\046lt;").replace(/\076/g, "\046gt;");\n
+        };\n
+\n
+        if (messages.length \076 0) {\n
+            output.push("\074file name=\\""+filename+"\\"\076");\n
+            CSSLint.Util.forEach(messages, function (message, i) {\n
+                if (message.rollup) {\n
+                    output.push("\074issue severity=\\"" + message.type + "\\" reason=\\"" + escapeSpecialCharacters(message.message) + "\\" evidence=\\"" + escapeSpecialCharacters(message.evidence) + "\\"/\076");\n
+                } else {\n
+                    output.push("\074issue line=\\"" + message.line + "\\" char=\\"" + message.col + "\\" severity=\\"" + message.type + "\\"" +\n
+                        " reason=\\"" + escapeSpecialCharacters(message.message) + "\\" evidence=\\"" + escapeSpecialCharacters(message.evidence) + "\\"/\076");\n
+                }\n
+            });\n
+            output.push("\074/file\076");\n
+        }\n
+\n
+        return output.join("");\n
+    }\n
+});\n
+/*global CSSLint*/\n
+CSSLint.addFormatter({\n
+    //format information\n
+    id: "junit-xml",\n
+    name: "JUNIT XML format",\n
+\n
+    /**\n
+     * Return opening root XML tag.\n
+     * @return {String} to prepend before all results\n
+     */\n
+    startFormat: function(){\n
+        return "\074?xml version=\\"1.0\\" encoding=\\"utf-8\\"?\076\074testsuites\076";\n
+    },\n
+\n
+    /**\n
+     * Return closing root XML tag.\n
+     * @return {String} to append after all results\n
+     */\n
+    endFormat: function() {\n
+        return "\074/testsuites\076";\n
+    },\n
+\n
+    /**\n
+     * Given CSS Lint results for a file, return output for this format.\n
+     * @param results {Object} with error and warning messages\n
+     * @param filename {String} relative file path\n
+     * @param options {Object} (UNUSED for now) specifies special handling of output\n
+     * @return {String} output for results\n
+     */\n
+    formatResults: function(results, filename, options) {\n
+\n
+        var messages = results.messages,\n
+            output = [],\n
+            tests = {\n
+                \'error\': 0,\n
+                \'failure\': 0\n
+            };\n
+\n
+        /**\n
+         * Generate a source string for a rule.\n
+         * JUNIT source strings usually resemble Java class names e.g\n
+         * net.csslint.SomeRuleName\n
+         * @param {Object} rule\n
+         * @return rule source as {String}\n
+         */\n
+        var generateSource = function(rule) {\n
+            if (!rule || !(\'name\' in rule)) {\n
+                return "";\n
+            }\n
+            return \'net.csslint.\' + rule.name.replace(/\\s/g,\'\');\n
+        };\n
+\n
+        /**\n
+         * Replace special characters before write to output.\n
+         *\n
+         * Rules:\n
+         *  - single quotes is the escape sequence for double-quotes\n
+         *  - \046lt; is the escape sequence for \074\n
+         *  - \046gt; is the escape sequence for \076\n
+         *\n
+         * @param {String} message to escape\n
+         * @return escaped message as {String}\n
+         */\n
+        var escapeSpecialCharacters = function(str) {\n
+\n
+            if (!str || str.constructor !== String) {\n
+                return "";\n
+            }\n
+\n
+            return str.replace(/\\"/g, "\'").replace(/\074/g, "\046lt;").replace(/\076/g, "\046gt;");\n
+\n
+        };\n
+\n
+        if (messages.length \076 0) {\n
+\n
+            messages.forEach(function (message, i) {\n
+\n
+                // since junit has no warning class\n
+                // all issues as errors\n
+                var type = message.type === \'warning\' ? \'error\' : message.type;\n
+\n
+                //ignore rollups for now\n
+                if (!message.rollup) {\n
+\n
+                    // build the test case seperately, once joined\n
+                    // we\'ll add it to a custom array filtered by type\n
+                    output.push("\074testcase time=\\"0\\" name=\\"" + generateSource(message.rule) + "\\"\076");\n
+                    output.push("\074" + type + " message=\\"" + escapeSpecialCharacters(message.message) + "\\"\076\074![CDATA[" + message.line + \':\' + message.col + \':\' + escapeSpecialCharacters(message.evidence)  + "]]\076\074/" + type + "\076");\n
+                    output.push("\074/testcase\076");\n
+\n
+                    tests[type] += 1;\n
+\n
+                }\n
+\n
+            });\n
+\n
+            output.unshift("\074testsuite time=\\"0\\" tests=\\"" + messages.length + "\\" skipped=\\"0\\" errors=\\"" + tests.error + "\\" failures=\\"" + tests.failure + "\\" package=\\"net.csslint\\" name=\\"" + filename + "\\"\076");\n
+            output.push("\074/testsuite\076");\n
+\n
+        }\n
+\n
+        return output.join("");\n
+\n
+    }\n
+});\n
+/*global CSSLint*/\n
+CSSLint.addFormatter({\n
+    //format information\n
+    id: "lint-xml",\n
+    name: "Lint XML format",\n
+\n
+    /**\n
+     * Return opening root XML tag.\n
+     * @return {String} to prepend before all results\n
+     */\n
+    startFormat: function(){\n
+        return "\074?xml version=\\"1.0\\" encoding=\\"utf-8\\"?\076\074lint\076";\n
+    },\n
+\n
+    /**\n
+     * Return closing root XML tag.\n
+     * @return {String} to append after all results\n
+     */\n
+    endFormat: function(){\n
+        return "\074/lint\076";\n
+    },\n
+\n
+    /**\n
+     * Given CSS Lint results for a file, return output for this format.\n
+     * @param results {Object} with error and warning messages\n
+     * @param filename {String} relative file path\n
+     * @param options {Object} (UNUSED for now) specifies special handling of output\n
+     * @return {String} output for results\n
+     */\n
+    formatResults: function(results, filename, options) {\n
+        var messages = results.messages,\n
+            output = [];\n
+\n
+        /**\n
+         * Replace special characters before write to output.\n
+         *\n
+         * Rules:\n
+         *  - single quotes is the escape sequence for double-quotes\n
+         *  - \046amp; is the escape sequence for \046\n
+         *  - \046lt; is the escape sequence for \074\n
+         *  - \046gt; is the escape sequence for \076\n
+         *\n
+         * @param {String} message to escape\n
+         * @return escaped message as {String}\n
+         */\n
+        var escapeSpecialCharacters = function(str) {\n
+            if (!str || str.constructor !== String) {\n
+                return "";\n
+            }\n
+            return str.replace(/\\"/g, "\'").replace(/\046/g, "\046amp;").replace(/\074/g, "\046lt;").replace(/\076/g, "\046gt;");\n
+        };\n
+\n
+        if (messages.length \076 0) {\n
+\n
+            output.push("\074file name=\\""+filename+"\\"\076");\n
+            CSSLint.Util.forEach(messages, function (message, i) {\n
+                if (message.rollup) {\n
+                    output.push("\074issue severity=\\"" + message.type + "\\" reason=\\"" + escapeSpecialCharacters(message.message) + "\\" evidence=\\"" + escapeSpecialCharacters(message.evidence) + "\\"/\076");\n
+                } else {\n
+                    output.push("\074issue line=\\"" + message.line + "\\" char=\\"" + message.col + "\\" severity=\\"" + message.type + "\\"" +\n
+                        " reason=\\"" + escapeSpecialCharacters(message.message) + "\\" evidence=\\"" + escapeSpecialCharacters(message.evidence) + "\\"/\076");\n
+                }\n
+            });\n
+            output.push("\074/file\076");\n
+        }\n
+\n
+        return output.join("");\n
+    }\n
+});\n
+/*global CSSLint*/\n
+CSSLint.addFormatter({\n
+    //format information\n
+    id: "text",\n
+    name: "Plain Text",\n
+\n
+    /**\n
+     * Return content to be printed before all file results.\n
+     * @return {String} to prepend before all results\n
+     */\n
+    startFormat: function() {\n
+        return "";\n
+    },\n
+\n
+    /**\n
+     * Return content to be printed after all file results.\n
+     * @return {String} to append after all results\n
+     */\n
+    endFormat: function() {\n
+        return "";\n
+    },\n
+\n
+    /**\n
+     * Given CSS Lint results for a file, return output for this format.\n
+     * @param results {Object} with error and warning messages\n
+     * @param filename {String} relative file path\n
+     * @param options {Object} (Optional) specifies special handling of output\n
+     * @return {String} output for results\n
+     */\n
+    formatResults: function(results, filename, options) {\n
+        var messages = results.messages,\n
+            output = "";\n
+        options = options || {};\n
+\n
+        if (messages.length === 0) {\n
+            return options.quiet ? "" : "\\n\\ncsslint: No errors in " + filename + ".";\n
+        }\n
+\n
+        output = "\\n\\ncsslint: There are " + messages.length  +  " problems in " + filename + ".";\n
+        var pos = filename.lastIndexOf("/"),\n
+            shortFilename = filename;\n
+\n
+        if (pos === -1){\n
+            pos = filename.lastIndexOf("\\\\");\n
+        }\n
+        if (pos \076 -1){\n
+            shortFilename = filename.substring(pos+1);\n
+        }\n
+\n
+        CSSLint.Util.forEach(messages, function (message, i) {\n
+            output = output + "\\n\\n" + shortFilename;\n
+            if (message.rollup) {\n
+                output += "\\n" + (i+1) + ": " + message.type;\n
+                output += "\\n" + message.message;\n
+            } else {\n
+                output += "\\n" + (i+1) + ": " + message.type + " at line " + message.line + ", col " + message.col;\n
+                output += "\\n" + message.message;\n
+                output += "\\n" + message.evidence;\n
+            }\n
+        });\n
+\n
+        return output;\n
+    }\n
+});\n
+return CSSLint;\n
+})();</string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/jshint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/jshint.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f56eccccb9e205471257cd26ebde0452ceabcb1
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/jshint.js.xml
@@ -0,0 +1,4611 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts29784793.18</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jshint.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>163537</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+ * JSHint, by JSHint Community.\n
+ *\n
+ * Licensed under the same slightly modified MIT license that JSLint is.\n
+ * It stops evil-doers everywhere.\n
+ *\n
+ * JSHint is a derivative work of JSLint:\n
+ *\n
+ *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n
+ *\n
+ *   Permission is hereby granted, free of charge, to any person obtaining\n
+ *   a copy of this software and associated documentation files (the "Software"),\n
+ *   to deal in the Software without restriction, including without limitation\n
+ *   the rights to use, copy, modify, merge, publish, distribute, sublicense,\n
+ *   and/or sell copies of the Software, and to permit persons to whom\n
+ *   the Software is furnished to do so, subject to the following conditions:\n
+ *\n
+ *   The above copyright notice and this permission notice shall be included\n
+ *   in all copies or substantial portions of the Software.\n
+ *\n
+ *   The Software shall be used for Good, not Evil.\n
+ *\n
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
+ *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n
+ *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n
+ *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n
+ *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n
+ *   DEALINGS IN THE SOFTWARE.\n
+ *\n
+ * JSHint was forked from 2010-12-16 edition of JSLint.\n
+ *\n
+ */\n
+\n
+/*\n
+ JSHINT is a global function. It takes two parameters.\n
+\n
+     var myResult = JSHINT(source, option);\n
+\n
+ The first parameter is either a string or an array of strings. If it is a\n
+ string, it will be split on \'\\n\' or \'\\r\'. If it is an array of strings, it\n
+ is assumed that each string represents one line. The source can be a\n
+ JavaScript text or a JSON text.\n
+\n
+ The second parameter is an optional object of options which control the\n
+ operation of JSHINT. Most of the options are booleans: They are all\n
+ optional and have a default value of false. One of the options, predef,\n
+ can be an array of names, which will be used to declare global variables,\n
+ or an object whose keys are used as global names, with a boolean value\n
+ that determines if they are assignable.\n
+\n
+ If it checks out, JSHINT returns true. Otherwise, it returns false.\n
+\n
+ If false, you can inspect JSHINT.errors to find out the problems.\n
+ JSHINT.errors is an array of objects containing these members:\n
+\n
+ {\n
+     line      : The line (relative to 0) at which the lint was found\n
+     character : The character (relative to 0) at which the lint was found\n
+     reason    : The problem\n
+     evidence  : The text line in which the problem occurred\n
+     raw       : The raw message before the details were inserted\n
+     a         : The first detail\n
+     b         : The second detail\n
+     c         : The third detail\n
+     d         : The fourth detail\n
+ }\n
+\n
+ If a fatal error was found, a null will be the last element of the\n
+ JSHINT.errors array.\n
+\n
+ You can request a Function Report, which shows all of the functions\n
+ and the parameters and vars that they use. This can be used to find\n
+ implied global variables and other problems. The report is in HTML and\n
+ can be inserted in an HTML <body>.\n
+\n
+     var myReport = JSHINT.report(limited);\n
+\n
+ If limited is true, then the report will be limited to only errors.\n
+\n
+ You can request a data structure which contains JSHint\'s results.\n
+\n
+     var myData = JSHINT.data();\n
+\n
+ It returns a structure with this form:\n
+\n
+ {\n
+     errors: [\n
+         {\n
+             line: NUMBER,\n
+             character: NUMBER,\n
+             reason: STRING,\n
+             evidence: STRING\n
+         }\n
+     ],\n
+     functions: [\n
+         name: STRING,\n
+         line: NUMBER,\n
+         last: NUMBER,\n
+         param: [\n
+             STRING\n
+         ],\n
+         closure: [\n
+             STRING\n
+         ],\n
+         var: [\n
+             STRING\n
+         ],\n
+         exception: [\n
+             STRING\n
+         ],\n
+         outer: [\n
+             STRING\n
+         ],\n
+         unused: [\n
+             STRING\n
+         ],\n
+         global: [\n
+             STRING\n
+         ],\n
+         label: [\n
+             STRING\n
+         ]\n
+     ],\n
+     globals: [\n
+         STRING\n
+     ],\n
+     member: {\n
+         STRING: NUMBER\n
+     },\n
+     unused: [\n
+         {\n
+             name: STRING,\n
+             line: NUMBER\n
+         }\n
+     ],\n
+     implieds: [\n
+         {\n
+             name: STRING,\n
+             line: NUMBER\n
+         }\n
+     ],\n
+     urls: [\n
+         STRING\n
+     ],\n
+     json: BOOLEAN\n
+ }\n
+\n
+ Empty arrays will not be included.\n
+\n
+*/\n
+\n
+/*jshint\n
+ evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,\n
+ undef: true, maxlen: 100, indent:4\n
+*/\n
+\n
+/*members "\\b", "\\t", "\\n", "\\f", "\\r", "!=", "!==", "\\"", "%", "(begin)",\n
+ "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)",\n
+ "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)",\n
+ "(statement)", "(verb)", "*", "+", "++", "-", "--", "\\/", "<", "<=", "==",\n
+ "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,\n
+ __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,\n
+ Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,\n
+ CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,\n
+ Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser, Drag,\n
+ E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,\n
+ Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,\n
+ FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,\n
+ HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,\n
+ HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,\n
+ HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,\n
+ HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,\n
+ HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,\n
+ HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,\n
+ HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,\n
+ HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,\n
+ HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,\n
+ HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,\n
+ HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,\n
+ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,\n
+ HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,\n
+ HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,\n
+ Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,\n
+ Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,\n
+ MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,\n
+ MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object, ObjectRange, Option,\n
+ Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,\n
+ RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,\n
+ SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,\n
+ ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,\n
+ Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,\n
+ SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,\n
+ Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,\n
+ VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,\n
+ XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,\n
+ "\\\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity, asi, atob,\n
+ b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, btoa, c, call, callee,\n
+ caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,\n
+ close, closed, closure, comment, condition, confirm, console, constructor,\n
+ content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,\n
+ decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,\n
+ dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,\n
+ entityify, eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,\n
+ ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,\n
+ forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,\n
+ g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,\n
+ hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,\n
+ indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,\n
+ isDigit, isFinite, isNaN, iterator, java, join, jshint,\n
+ JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma,\n
+ latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,\n
+ log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,\n
+ moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen,\n
+ nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus,\n
+ onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param,\n
+ parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,\n
+ proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp,\n
+ readFile, readUrl, regexdash, removeEventListener, replace, report, require,\n
+ reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,\n
+ runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal,\n
+ send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice,\n
+ smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow,\n
+ supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing,\n
+ type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis,\n
+ value, valueOf, var, vars, version, WebSocket, withstmt, white, window, windows, Worker, wsh*/\n
+\n
+/*global exports: false */\n
+\n
+// We build the application inside a function so that we produce only a single\n
+// global variable. That function will be invoked immediately, and its return\n
+// value is the JSHINT function itself.\n
+\n
+var JSHINT = (function () {\n
+    "use strict";\n
+\n
+    var anonname,       // The guessed name for anonymous functions.\n
+\n
+// These are operators that should not be used with the ! operator.\n
+\n
+        bang = {\n
+            \'<\'  : true,\n
+            \'<=\' : true,\n
+            \'==\' : true,\n
+            \'===\': true,\n
+            \'!==\': true,\n
+            \'!=\' : true,\n
+            \'>\'  : true,\n
+            \'>=\' : true,\n
+            \'+\'  : true,\n
+            \'-\'  : true,\n
+            \'*\'  : true,\n
+            \'/\'  : true,\n
+            \'%\'  : true\n
+        },\n
+\n
+        // These are the JSHint boolean options.\n
+        boolOptions = {\n
+            asi         : true, // if automatic semicolon insertion should be tolerated\n
+            bitwise     : true, // if bitwise operators should not be allowed\n
+            boss        : true, // if advanced usage of assignments should be allowed\n
+            browser     : true, // if the standard browser globals should be predefined\n
+            couch       : true, // if CouchDB globals should be predefined\n
+            curly       : true, // if curly braces around all blocks should be required\n
+            debug       : true, // if debugger statements should be allowed\n
+            devel       : true, // if logging globals should be predefined (console,\n
+                                // alert, etc.)\n
+            dojo        : true, // if Dojo Toolkit globals should be predefined\n
+            eqeqeq      : true, // if === should be required\n
+            eqnull      : true, // if == null comparisons should be tolerated\n
+            es5         : true, // if ES5 syntax should be allowed\n
+            esnext      : true, // if es.next specific syntax should be allowed\n
+            evil        : true, // if eval should be allowed\n
+            expr        : true, // if ExpressionStatement should be allowed as Programs\n
+            forin       : true, // if for in statements must filter\n
+            funcscope   : true, // if only function scope should be used for scope tests\n
+            globalstrict: true, // if global "use strict"; should be allowed (also\n
+                                // enables \'strict\')\n
+            immed       : true, // if immediate invocations must be wrapped in parens\n
+            iterator    : true, // if the `__iterator__` property should be allowed\n
+            jquery      : true, // if jQuery globals should be predefined\n
+            lastsemic   : true, // if semicolons may be ommitted for the trailing\n
+                                // statements inside of a one-line blocks.\n
+            latedef     : true, // if the use before definition should not be tolerated\n
+            laxbreak    : true, // if line breaks should not be checked\n
+            laxcomma    : true, // if line breaks should not be checked around commas\n
+            loopfunc    : true, // if functions should be allowed to be defined within\n
+                                // loops\n
+            mootools    : true, // if MooTools globals should be predefined\n
+            multistr    : true, // allow multiline strings\n
+            newcap      : true, // if constructor names must be capitalized\n
+            noarg       : true, // if arguments.caller and arguments.callee should be\n
+                                // disallowed\n
+            node        : true, // if the Node.js environment globals should be\n
+                                // predefined\n
+            noempty     : true, // if empty blocks should be disallowed\n
+            nonew       : true, // if using `new` for side-effects should be disallowed\n
+            nonstandard : true, // if non-standard (but widely adopted) globals should\n
+                                // be predefined\n
+            nomen       : true, // if names should be checked\n
+            onevar      : true, // if only one var statement per function should be\n
+                                // allowed\n
+            onecase     : true, // if one case switch statements should be allowed\n
+            passfail    : true, // if the scan should stop on first error\n
+            plusplus    : true, // if increment/decrement should not be allowed\n
+            proto       : true, // if the `__proto__` property should be allowed\n
+            prototypejs : true, // if Prototype and Scriptaculous globals should be\n
+                                // predefined\n
+            regexdash   : true, // if unescaped first/last dash (-) inside brackets\n
+                                // should be tolerated\n
+            regexp      : true, // if the . should not be allowed in regexp literals\n
+            rhino       : true, // if the Rhino environment globals should be predefined\n
+            undef       : true, // if variables should be declared before used\n
+            scripturl   : true, // if script-targeted URLs should be tolerated\n
+            shadow      : true, // if variable shadowing should be tolerated\n
+            smarttabs   : true, // if smarttabs should be tolerated\n
+                                // (http://www.emacswiki.org/emacs/SmartTabs)\n
+            strict      : true, // require the "use strict"; pragma\n
+            sub         : true, // if all forms of subscript notation are tolerated\n
+            supernew    : true, // if `new function () { ... };` and `new Object;`\n
+                                // should be tolerated\n
+            trailing    : true, // if trailing whitespace rules apply\n
+            validthis   : true, // if \'this\' inside a non-constructor function is valid.\n
+                                // This is a function scoped option only.\n
+            withstmt    : true, // if with statements should be allowed\n
+            white       : true, // if strict whitespace rules apply\n
+            wsh         : true  // if the Windows Scripting Host environment globals\n
+                                // should be predefined\n
+        },\n
+\n
+        // These are the JSHint options that can take any value\n
+        // (we use this object to detect invalid options)\n
+        valOptions = {\n
+            maxlen: false,\n
+            indent: false,\n
+            maxerr: false,\n
+            predef: false\n
+        },\n
+\n
+        // These are JSHint boolean options which are shared with JSLint\n
+        // where the definition in JSHint is opposite JSLint\n
+        invertedOptions = {\n
+            bitwise     : true,\n
+            forin       : true,\n
+            newcap      : true,\n
+            nomen       : true,\n
+            plusplus    : true,\n
+            regexp      : true,\n
+            undef       : true,\n
+            white       : true,\n
+\n
+            // Inverted and renamed, use JSHint name here\n
+            eqeqeq      : true,\n
+            onevar      : true\n
+        },\n
+\n
+        // These are JSHint boolean options which are shared with JSLint\n
+        // where the name has been changed but the effect is unchanged\n
+        renamedOptions = {\n
+            eqeq        : "eqeqeq",\n
+            vars        : "onevar",\n
+            windows     : "wsh"\n
+        },\n
+\n
+\n
+        // browser contains a set of global names which are commonly provided by a\n
+        // web browser environment.\n
+        browser = {\n
+            ArrayBuffer              :  false,\n
+            ArrayBufferView          :  false,\n
+            Audio                    :  false,\n
+            addEventListener         :  false,\n
+            applicationCache         :  false,\n
+            atob                     :  false,\n
+            blur                     :  false,\n
+            btoa                     :  false,\n
+            clearInterval            :  false,\n
+            clearTimeout             :  false,\n
+            close                    :  false,\n
+            closed                   :  false,\n
+            DataView                 :  false,\n
+            DOMParser                :  false,\n
+            defaultStatus            :  false,\n
+            document                 :  false,\n
+            event                    :  false,\n
+            FileReader               :  false,\n
+            Float32Array             :  false,\n
+            Float64Array             :  false,\n
+            FormData                 :  false,\n
+            focus                    :  false,\n
+            frames                   :  false,\n
+            getComputedStyle         :  false,\n
+            HTMLElement              :  false,\n
+            HTMLAnchorElement        :  false,\n
+            HTMLBaseElement          :  false,\n
+            HTMLBlockquoteElement    :  false,\n
+            HTMLBodyElement          :  false,\n
+            HTMLBRElement            :  false,\n
+            HTMLButtonElement        :  false,\n
+            HTMLCanvasElement        :  false,\n
+            HTMLDirectoryElement     :  false,\n
+            HTMLDivElement           :  false,\n
+            HTMLDListElement         :  false,\n
+            HTMLFieldSetElement      :  false,\n
+            HTMLFontElement          :  false,\n
+            HTMLFormElement          :  false,\n
+            HTMLFrameElement         :  false,\n
+            HTMLFrameSetElement      :  false,\n
+            HTMLHeadElement          :  false,\n
+            HTMLHeadingElement       :  false,\n
+            HTMLHRElement            :  false,\n
+            HTMLHtmlElement          :  false,\n
+            HTMLIFrameElement        :  false,\n
+            HTMLImageElement         :  false,\n
+            HTMLInputElement         :  false,\n
+            HTMLIsIndexElement       :  false,\n
+            HTMLLabelElement         :  false,\n
+            HTMLLayerElement         :  false,\n
+            HTMLLegendElement        :  false,\n
+            HTMLLIElement            :  false,\n
+            HTMLLinkElement          :  false,\n
+            HTMLMapElement           :  false,\n
+            HTMLMenuElement          :  false,\n
+            HTMLMetaElement          :  false,\n
+            HTMLModElement           :  false,\n
+            HTMLObjectElement        :  false,\n
+            HTMLOListElement         :  false,\n
+            HTMLOptGroupElement      :  false,\n
+            HTMLOptionElement        :  false,\n
+            HTMLParagraphElement     :  false,\n
+            HTMLParamElement         :  false,\n
+            HTMLPreElement           :  false,\n
+            HTMLQuoteElement         :  false,\n
+            HTMLScriptElement        :  false,\n
+            HTMLSelectElement        :  false,\n
+            HTMLStyleElement         :  false,\n
+            HTMLTableCaptionElement  :  false,\n
+            HTMLTableCellElement     :  false,\n
+            HTMLTableColElement      :  false,\n
+            HTMLTableElement         :  false,\n
+            HTMLTableRowElement      :  false,\n
+            HTMLTableSectionElement  :  false,\n
+            HTMLTextAreaElement      :  false,\n
+            HTMLTitleElement         :  false,\n
+            HTMLUListElement         :  false,\n
+            HTMLVideoElement         :  false,\n
+            history                  :  false,\n
+            Int16Array               :  false,\n
+            Int32Array               :  false,\n
+            Int8Array                :  false,\n
+            Image                    :  false,\n
+            length                   :  false,\n
+            localStorage             :  false,\n
+            location                 :  false,\n
+            MessageChannel           :  false,\n
+            MessageEvent             :  false,\n
+            MessagePort              :  false,\n
+            moveBy                   :  false,\n
+            moveTo                   :  false,\n
+            name                     :  false,\n
+            navigator                :  false,\n
+            onbeforeunload           :  true,\n
+            onblur                   :  true,\n
+            onerror                  :  true,\n
+            onfocus                  :  true,\n
+            onload                   :  true,\n
+            onresize                 :  true,\n
+            onunload                 :  true,\n
+            open                     :  false,\n
+            openDatabase             :  false,\n
+            opener                   :  false,\n
+            Option                   :  false,\n
+            parent                   :  false,\n
+            print                    :  false,\n
+            removeEventListener      :  false,\n
+            resizeBy                 :  false,\n
+            resizeTo                 :  false,\n
+            screen                   :  false,\n
+            scroll                   :  false,\n
+            scrollBy                 :  false,\n
+            scrollTo                 :  false,\n
+            sessionStorage           :  false,\n
+            setInterval              :  false,\n
+            setTimeout               :  false,\n
+            SharedWorker             :  false,\n
+            status                   :  false,\n
+            top                      :  false,\n
+            Uint16Array              :  false,\n
+            Uint32Array              :  false,\n
+            Uint8Array               :  false,\n
+            WebSocket                :  false,\n
+            window                   :  false,\n
+            Worker                   :  false,\n
+            XMLHttpRequest           :  false,\n
+            XMLSerializer            :  false,\n
+            XPathEvaluator           :  false,\n
+            XPathException           :  false,\n
+            XPathExpression          :  false,\n
+            XPathNamespace           :  false,\n
+            XPathNSResolver          :  false,\n
+            XPathResult              :  false\n
+        },\n
+\n
+        couch = {\n
+            "require" : false,\n
+            respond   : false,\n
+            getRow    : false,\n
+            emit      : false,\n
+            send      : false,\n
+            start     : false,\n
+            sum       : false,\n
+            log       : false,\n
+            exports   : false,\n
+            module    : false,\n
+            provides  : false\n
+        },\n
+\n
+        devel = {\n
+            alert   : false,\n
+            confirm : false,\n
+            console : false,\n
+            Debug   : false,\n
+            opera   : false,\n
+            prompt  : false\n
+        },\n
+\n
+        dojo = {\n
+            dojo      : false,\n
+            dijit     : false,\n
+            dojox     : false,\n
+            define    : false,\n
+            "require" : false\n
+        },\n
+\n
+        escapes = {\n
+            \'\\b\': \'\\\\b\',\n
+            \'\\t\': \'\\\\t\',\n
+            \'\\n\': \'\\\\n\',\n
+            \'\\f\': \'\\\\f\',\n
+            \'\\r\': \'\\\\r\',\n
+            \'"\' : \'\\\\"\',\n
+            \'/\' : \'\\\\/\',\n
+            \'\\\\\': \'\\\\\\\\\'\n
+        },\n
+\n
+        funct,          // The current function\n
+\n
+        functionicity = [\n
+            \'closure\', \'exception\', \'global\', \'label\',\n
+            \'outer\', \'unused\', \'var\'\n
+        ],\n
+\n
+        functions,      // All of the functions\n
+\n
+        global,         // The global scope\n
+        implied,        // Implied globals\n
+        inblock,\n
+        indent,\n
+        jsonmode,\n
+\n
+        jquery = {\n
+            \'$\'    : false,\n
+            jQuery : false\n
+        },\n
+\n
+        lines,\n
+        lookahead,\n
+        member,\n
+        membersOnly,\n
+\n
+        mootools = {\n
+            \'$\'             : false,\n
+            \'$$\'            : false,\n
+            Assets          : false,\n
+            Browser         : false,\n
+            Chain           : false,\n
+            Class           : false,\n
+            Color           : false,\n
+            Cookie          : false,\n
+            Core            : false,\n
+            Document        : false,\n
+            DomReady        : false,\n
+            DOMReady        : false,\n
+            Drag            : false,\n
+            Element         : false,\n
+            Elements        : false,\n
+            Event           : false,\n
+            Events          : false,\n
+            Fx              : false,\n
+            Group           : false,\n
+            Hash            : false,\n
+            HtmlTable       : false,\n
+            Iframe          : false,\n
+            IframeShim      : false,\n
+            InputValidator  : false,\n
+            instanceOf      : false,\n
+            Keyboard        : false,\n
+            Locale          : false,\n
+            Mask            : false,\n
+            MooTools        : false,\n
+            Native          : false,\n
+            Options         : false,\n
+            OverText        : false,\n
+            Request         : false,\n
+            Scroller        : false,\n
+            Slick           : false,\n
+            Slider          : false,\n
+            Sortables       : false,\n
+            Spinner         : false,\n
+            Swiff           : false,\n
+            Tips            : false,\n
+            Type            : false,\n
+            typeOf          : false,\n
+            URI             : false,\n
+            Window          : false\n
+        },\n
+\n
+        nexttoken,\n
+\n
+        node = {\n
+            __filename    : false,\n
+            __dirname     : false,\n
+            Buffer        : false,\n
+            console       : false,\n
+            exports       : false,\n
+            GLOBAL        : false,\n
+            global        : false,\n
+            module        : false,\n
+            process       : false,\n
+            require       : false,\n
+            setTimeout    : false,\n
+            clearTimeout  : false,\n
+            setInterval   : false,\n
+            clearInterval : false\n
+        },\n
+\n
+        noreach,\n
+        option,\n
+        predefined,     // Global variables defined by option\n
+        prereg,\n
+        prevtoken,\n
+\n
+        prototypejs = {\n
+            \'$\'               : false,\n
+            \'$$\'              : false,\n
+            \'$A\'              : false,\n
+            \'$F\'              : false,\n
+            \'$H\'              : false,\n
+            \'$R\'              : false,\n
+            \'$break\'          : false,\n
+            \'$continue\'       : false,\n
+            \'$w\'              : false,\n
+            Abstract          : false,\n
+            Ajax              : false,\n
+            Class             : false,\n
+            Enumerable        : false,\n
+            Element           : false,\n
+            Event             : false,\n
+            Field             : false,\n
+            Form              : false,\n
+            Hash              : false,\n
+            Insertion         : false,\n
+            ObjectRange       : false,\n
+            PeriodicalExecuter: false,\n
+            Position          : false,\n
+            Prototype         : false,\n
+            Selector          : false,\n
+            Template          : false,\n
+            Toggle            : false,\n
+            Try               : false,\n
+            Autocompleter     : false,\n
+            Builder           : false,\n
+            Control           : false,\n
+            Draggable         : false,\n
+            Draggables        : false,\n
+            Droppables        : false,\n
+            Effect            : false,\n
+            Sortable          : false,\n
+            SortableObserver  : false,\n
+            Sound             : false,\n
+            Scriptaculous     : false\n
+        },\n
+\n
+        rhino = {\n
+            defineClass  : false,\n
+            deserialize  : false,\n
+            gc           : false,\n
+            help         : false,\n
+            importPackage: false,\n
+            "java"       : false,\n
+            load         : false,\n
+            loadClass    : false,\n
+            print        : false,\n
+            quit         : false,\n
+            readFile     : false,\n
+            readUrl      : false,\n
+            runCommand   : false,\n
+            seal         : false,\n
+            serialize    : false,\n
+            spawn        : false,\n
+            sync         : false,\n
+            toint32      : false,\n
+            version      : false\n
+        },\n
+\n
+        scope,      // The current scope\n
+        stack,\n
+\n
+        // standard contains the global names that are provided by the\n
+        // ECMAScript standard.\n
+        standard = {\n
+            Array               : false,\n
+            Boolean             : false,\n
+            Date                : false,\n
+            decodeURI           : false,\n
+            decodeURIComponent  : false,\n
+            encodeURI           : false,\n
+            encodeURIComponent  : false,\n
+            Error               : false,\n
+            \'eval\'              : false,\n
+            EvalError           : false,\n
+            Function            : false,\n
+            hasOwnProperty      : false,\n
+            isFinite            : false,\n
+            isNaN               : false,\n
+            JSON                : false,\n
+            Math                : false,\n
+            Number              : false,\n
+            Object              : false,\n
+            parseInt            : false,\n
+            parseFloat          : false,\n
+            RangeError          : false,\n
+            ReferenceError      : false,\n
+            RegExp              : false,\n
+            String              : false,\n
+            SyntaxError         : false,\n
+            TypeError           : false,\n
+            URIError            : false\n
+        },\n
+\n
+        // widely adopted global names that are not part of ECMAScript standard\n
+        nonstandard = {\n
+            escape              : false,\n
+            unescape            : false\n
+        },\n
+\n
+        standard_member = {\n
+            E                   : true,\n
+            LN2                 : true,\n
+            LN10                : true,\n
+            LOG2E               : true,\n
+            LOG10E              : true,\n
+            MAX_VALUE           : true,\n
+            MIN_VALUE           : true,\n
+            NEGATIVE_INFINITY   : true,\n
+            PI                  : true,\n
+            POSITIVE_INFINITY   : true,\n
+            SQRT1_2             : true,\n
+            SQRT2               : true\n
+        },\n
+\n
+        directive,\n
+        syntax = {},\n
+        tab,\n
+        token,\n
+        urls,\n
+        useESNextSyntax,\n
+        warnings,\n
+\n
+        wsh = {\n
+            ActiveXObject             : true,\n
+            Enumerator                : true,\n
+            GetObject                 : true,\n
+            ScriptEngine              : true,\n
+            ScriptEngineBuildVersion  : true,\n
+            ScriptEngineMajorVersion  : true,\n
+            ScriptEngineMinorVersion  : true,\n
+            VBArray                   : true,\n
+            WSH                       : true,\n
+            WScript                   : true,\n
+            XDomainRequest            : true\n
+        };\n
+\n
+    // Regular expressions. Some of these are stupidly long.\n
+    var ax, cx, tx, nx, nxg, lx, ix, jx, ft;\n
+    (function () {\n
+        /*jshint maxlen:300 */\n
+\n
+        // unsafe comment or string\n
+        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i;\n
+\n
+        // unsafe characters that are silently deleted by one or more browsers\n
+        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n
+\n
+        // token\n
+        tx = /^\\s*([(){}\\[.,:;\'"~\\?\\]#@]|==?=?|\\/(\\*(jshint|jslint|members?|global)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|%=?|&[&=]?|\\|[|=]?|>>?>?=?|<([\\/=!]|\\!(\\[|--)?|<=?)?|\\^=?|\\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\\.[0-9]*)?([eE][+\\-]?[0-9]+)?)/;\n
+\n
+        // characters in strings that need escapement\n
+        nx = /[\\u0000-\\u001f&<"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n
+        nxg = /[\\u0000-\\u001f&<"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n
+\n
+        // star slash\n
+        lx = /\\*\\/|\\/\\*/;\n
+\n
+        // identifier\n
+        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\n
+\n
+        // javascript url\n
+        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i;\n
+\n
+        // catches /* falls through */ comments\n
+        ft = /^\\s*\\/\\*\\s*falls\\sthrough\\s*\\*\\/\\s*$/;\n
+    }());\n
+\n
+    function F() {}     // Used by Object.create\n
+\n
+    function is_own(object, name) {\n
+\n
+// The object.hasOwnProperty method fails when the property under consideration\n
+// is named \'hasOwnProperty\'. So we have to use this more convoluted form.\n
+\n
+        return Object.prototype.hasOwnProperty.call(object, name);\n
+    }\n
+\n
+    function checkOption(name, t) {\n
+        if (valOptions[name] === undefined && boolOptions[name] === undefined) {\n
+            warning("Bad option: \'" + name + "\'.", t);\n
+        }\n
+    }\n
+\n
+// Provide critical ES5 functions to ES3.\n
+\n
+    if (typeof Array.isArray !== \'function\') {\n
+        Array.isArray = function (o) {\n
+            return Object.prototype.toString.apply(o) === \'[object Array]\';\n
+        };\n
+    }\n
+\n
+    if (typeof Object.create !== \'function\') {\n
+        Object.create = function (o) {\n
+            F.prototype = o;\n
+            return new F();\n
+        };\n
+    }\n
+\n
+    if (typeof Object.keys !== \'function\') {\n
+        Object.keys = function (o) {\n
+            var a = [], k;\n
+            for (k in o) {\n
+                if (is_own(o, k)) {\n
+                    a.push(k);\n
+                }\n
+            }\n
+            return a;\n
+        };\n
+    }\n
+\n
+// Non standard methods\n
+\n
+    if (typeof String.prototype.entityify !== \'function\') {\n
+        String.prototype.entityify = function () {\n
+            return this\n
+                .replace(/&/g, \'&amp;\')\n
+                .replace(/</g, \'&lt;\')\n
+                .replace(/>/g, \'&gt;\');\n
+        };\n
+    }\n
+\n
+    if (typeof String.prototype.isAlpha !== \'function\') {\n
+        String.prototype.isAlpha = function () {\n
+            return (this >= \'a\' && this <= \'z\\uffff\') ||\n
+                (this >= \'A\' && this <= \'Z\\uffff\');\n
+        };\n
+    }\n
+\n
+    if (typeof String.prototype.isDigit !== \'function\') {\n
+        String.prototype.isDigit = function () {\n
+            return (this >= \'0\' && this <= \'9\');\n
+        };\n
+    }\n
+\n
+    if (typeof String.prototype.supplant !== \'function\') {\n
+        String.prototype.supplant = function (o) {\n
+            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n
+                var r = o[b];\n
+                return typeof r === \'string\' || typeof r === \'number\' ? r : a;\n
+            });\n
+        };\n
+    }\n
+\n
+    if (typeof String.prototype.name !== \'function\') {\n
+        String.prototype.name = function () {\n
+\n
+// If the string looks like an identifier, then we can return it as is.\n
+// If the string contains no control characters, no quote characters, and no\n
+// backslash characters, then we can simply slap some quotes around it.\n
+// Otherwise we must also replace the offending characters with safe\n
+// sequences.\n
+\n
+            if (ix.test(this)) {\n
+                return this;\n
+            }\n
+            if (nx.test(this)) {\n
+                return \'"\' + this.replace(nxg, function (a) {\n
+                    var c = escapes[a];\n
+                    if (c) {\n
+                        return c;\n
+                    }\n
+                    return \'\\\\u\' + (\'0000\' + a.charCodeAt().toString(16)).slice(-4);\n
+                }) + \'"\';\n
+            }\n
+            return \'"\' + this + \'"\';\n
+        };\n
+    }\n
+\n
+\n
+    function combine(t, o) {\n
+        var n;\n
+        for (n in o) {\n
+            if (is_own(o, n)) {\n
+                t[n] = o[n];\n
+            }\n
+        }\n
+    }\n
+\n
+    function assume() {\n
+        if (option.couch) {\n
+            combine(predefined, couch);\n
+        }\n
+\n
+        if (option.rhino) {\n
+            combine(predefined, rhino);\n
+        }\n
+\n
+        if (option.prototypejs) {\n
+            combine(predefined, prototypejs);\n
+        }\n
+\n
+        if (option.node) {\n
+            combine(predefined, node);\n
+            option.globalstrict = true;\n
+        }\n
+\n
+        if (option.devel) {\n
+            combine(predefined, devel);\n
+        }\n
+\n
+        if (option.dojo) {\n
+            combine(predefined, dojo);\n
+        }\n
+\n
+        if (option.browser) {\n
+            combine(predefined, browser);\n
+        }\n
+\n
+        if (option.nonstandard) {\n
+            combine(predefined, nonstandard);\n
+        }\n
+\n
+        if (option.jquery) {\n
+            combine(predefined, jquery);\n
+        }\n
+\n
+        if (option.mootools) {\n
+            combine(predefined, mootools);\n
+        }\n
+\n
+        if (option.wsh) {\n
+            combine(predefined, wsh);\n
+        }\n
+\n
+        if (option.esnext) {\n
+            useESNextSyntax();\n
+        }\n
+\n
+        if (option.globalstrict && option.strict !== false) {\n
+            option.strict = true;\n
+        }\n
+    }\n
+\n
+\n
+    // Produce an error warning.\n
+    function quit(message, line, chr) {\n
+        var percentage = Math.floor((line / lines.length) * 100);\n
+\n
+        throw {\n
+            name: \'JSHintError\',\n
+            line: line,\n
+            character: chr,\n
+            message: message + " (" + percentage + "% scanned).",\n
+            raw: message\n
+        };\n
+    }\n
+\n
+    function isundef(scope, m, t, a) {\n
+        return JSHINT.undefs.push([scope, m, t, a]);\n
+    }\n
+\n
+    function warning(m, t, a, b, c, d) {\n
+        var ch, l, w;\n
+        t = t || nexttoken;\n
+        if (t.id === \'(end)\') {  // `~\n
+            t = token;\n
+        }\n
+        l = t.line || 0;\n
+        ch = t.from || 0;\n
+        w = {\n
+            id: \'(error)\',\n
+            raw: m,\n
+            evidence: lines[l - 1] || \'\',\n
+            line: l,\n
+            character: ch,\n
+            a: a,\n
+            b: b,\n
+            c: c,\n
+            d: d\n
+        };\n
+        w.reason = m.supplant(w);\n
+        JSHINT.errors.push(w);\n
+        if (option.passfail) {\n
+            quit(\'Stopping. \', l, ch);\n
+        }\n
+        warnings += 1;\n
+        if (warnings >= option.maxerr) {\n
+            quit("Too many errors.", l, ch);\n
+        }\n
+        return w;\n
+    }\n
+\n
+    function warningAt(m, l, ch, a, b, c, d) {\n
+        return warning(m, {\n
+            line: l,\n
+            from: ch\n
+        }, a, b, c, d);\n
+    }\n
+\n
+    function error(m, t, a, b, c, d) {\n
+        var w = warning(m, t, a, b, c, d);\n
+    }\n
+\n
+    function errorAt(m, l, ch, a, b, c, d) {\n
+        return error(m, {\n
+            line: l,\n
+            from: ch\n
+        }, a, b, c, d);\n
+    }\n
+\n
+\n
+\n
+// lexical analysis and token construction\n
+\n
+    var lex = (function lex() {\n
+        var character, from, line, s;\n
+\n
+// Private lex methods\n
+\n
+        function nextLine() {\n
+            var at,\n
+                tw; // trailing whitespace check\n
+\n
+            if (line >= lines.length)\n
+                return false;\n
+\n
+            character = 1;\n
+            s = lines[line];\n
+            line += 1;\n
+\n
+            // If smarttabs option is used check for spaces followed by tabs only.\n
+            // Otherwise check for any occurence of mixed tabs and spaces.\n
+            if (option.smarttabs)\n
+                at = s.search(/ \\t/);\n
+            else\n
+                at = s.search(/ \\t|\\t /);\n
+\n
+            if (at >= 0)\n
+                warningAt("Mixed spaces and tabs.", line, at + 1);\n
+\n
+            s = s.replace(/\\t/g, tab);\n
+            at = s.search(cx);\n
+\n
+            if (at >= 0)\n
+                warningAt("Unsafe character.", line, at);\n
+\n
+            if (option.maxlen && option.maxlen < s.length)\n
+                warningAt("Line too long.", line, s.length);\n
+\n
+            // Check for trailing whitespaces\n
+            tw = option.trailing && s.match(/^(.*?)\\s+$/);\n
+            if (tw && !/^\\s+$/.test(s)) {\n
+                warningAt("Trailing whitespace.", line, tw[1].length + 1);\n
+            }\n
+            return true;\n
+        }\n
+\n
+// Produce a token object.  The token inherits from a syntax symbol.\n
+\n
+        function it(type, value) {\n
+            var i, t;\n
+            if (type === \'(color)\' || type === \'(range)\') {\n
+                t = {type: type};\n
+            } else if (type === \'(punctuator)\' ||\n
+                    (type === \'(identifier)\' && is_own(syntax, value))) {\n
+                t = syntax[value] || syntax[\'(error)\'];\n
+            } else {\n
+                t = syntax[type];\n
+            }\n
+            t = Object.create(t);\n
+            if (type === \'(string)\' || type === \'(range)\') {\n
+                if (!option.scripturl && jx.test(value)) {\n
+                    warningAt("Script URL.", line, from);\n
+                }\n
+            }\n
+            if (type === \'(identifier)\') {\n
+                t.identifier = true;\n
+                if (value === \'__proto__\' && !option.proto) {\n
+                    warningAt("The \'{a}\' property is deprecated.",\n
+                        line, from, value);\n
+                } else if (value === \'__iterator__\' && !option.iterator) {\n
+                    warningAt("\'{a}\' is only available in JavaScript 1.7.",\n
+                        line, from, value);\n
+                } else if (option.nomen && (value.charAt(0) === \'_\' ||\n
+                         value.charAt(value.length - 1) === \'_\')) {\n
+                    if (!option.node || token.id === \'.\' ||\n
+                            (value !== \'__dirname\' && value !== \'__filename\')) {\n
+                        warningAt("Unexpected {a} in \'{b}\'.", line, from, "dangling \'_\'", value);\n
+                    }\n
+                }\n
+            }\n
+            t.value = value;\n
+            t.line = line;\n
+            t.character = character;\n
+            t.from = from;\n
+            i = t.id;\n
+            if (i !== \'(endline)\') {\n
+                prereg = i &&\n
+                    ((\'(,=:[!&|?{};\'.indexOf(i.charAt(i.length - 1)) >= 0) ||\n
+                    i === \'return\' ||\n
+                    i === \'case\');\n
+            }\n
+            return t;\n
+        }\n
+\n
+        // Public lex methods\n
+        return {\n
+            init: function (source) {\n
+                if (typeof source === \'string\') {\n
+                    lines = source\n
+                        .replace(/\\r\\n/g, \'\\n\')\n
+                        .replace(/\\r/g, \'\\n\')\n
+                        .split(\'\\n\');\n
+                } else {\n
+                    lines = source;\n
+                }\n
+\n
+                // If the first line is a shebang (#!), make it a blank and move on.\n
+                // Shebangs are used by Node scripts.\n
+                if (lines[0] && lines[0].substr(0, 2) === \'#!\')\n
+                    lines[0] = \'\';\n
+\n
+                line = 0;\n
+                nextLine();\n
+                from = 1;\n
+            },\n
+\n
+            range: function (begin, end) {\n
+                var c, value = \'\';\n
+                from = character;\n
+                if (s.charAt(0) !== begin) {\n
+                    errorAt("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                            line, character, begin, s.charAt(0));\n
+                }\n
+                for (;;) {\n
+                    s = s.slice(1);\n
+                    character += 1;\n
+                    c = s.charAt(0);\n
+                    switch (c) {\n
+                    case \'\':\n
+                        errorAt("Missing \'{a}\'.", line, character, c);\n
+                        break;\n
+                    case end:\n
+                        s = s.slice(1);\n
+                        character += 1;\n
+                        return it(\'(range)\', value);\n
+                    case \'\\\\\':\n
+                        warningAt("Unexpected \'{a}\'.", line, character, c);\n
+                    }\n
+                    value += c;\n
+                }\n
+\n
+            },\n
+\n
+\n
+            // token -- this is called by advance to get the next token\n
+            token: function () {\n
+                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;\n
+\n
+                function match(x) {\n
+                    var r = x.exec(s), r1;\n
+                    if (r) {\n
+                        l = r[0].length;\n
+                        r1 = r[1];\n
+                        c = r1.charAt(0);\n
+                        s = s.substr(l);\n
+                        from = character + l - r1.length;\n
+                        character += l;\n
+                        return r1;\n
+                    }\n
+                }\n
+\n
+                function string(x) {\n
+                    var c, j, r = \'\', allowNewLine = false;\n
+\n
+                    if (jsonmode && x !== \'"\') {\n
+                        warningAt("Strings must use doublequote.",\n
+                                line, character);\n
+                    }\n
+\n
+                    function esc(n) {\n
+                        var i = parseInt(s.substr(j + 1, n), 16);\n
+                        j += n;\n
+                        if (i >= 32 && i <= 126 &&\n
+                                i !== 34 && i !== 92 && i !== 39) {\n
+                            warningAt("Unnecessary escapement.", line, character);\n
+                        }\n
+                        character += n;\n
+                        c = String.fromCharCode(i);\n
+                    }\n
+                    j = 0;\n
+unclosedString:     for (;;) {\n
+                        while (j >= s.length) {\n
+                            j = 0;\n
+\n
+                            var cl = line, cf = from;\n
+                            if (!nextLine()) {\n
+                                errorAt("Unclosed string.", cl, cf);\n
+                                break unclosedString;\n
+                            }\n
+\n
+                            if (allowNewLine) {\n
+                                allowNewLine = false;\n
+                            } else {\n
+                                warningAt("Unclosed string.", cl, cf);\n
+                            }\n
+                        }\n
+                        c = s.charAt(j);\n
+                        if (c === x) {\n
+                            character += 1;\n
+                            s = s.substr(j + 1);\n
+                            return it(\'(string)\', r, x);\n
+                        }\n
+                        if (c < \' \') {\n
+                            if (c === \'\\n\' || c === \'\\r\') {\n
+                                break;\n
+                            }\n
+                            warningAt("Control character in string: {a}.",\n
+                                    line, character + j, s.slice(0, j));\n
+                        } else if (c === \'\\\\\') {\n
+                            j += 1;\n
+                            character += 1;\n
+                            c = s.charAt(j);\n
+                            n = s.charAt(j + 1);\n
+                            switch (c) {\n
+                            case \'\\\\\':\n
+                            case \'"\':\n
+                            case \'/\':\n
+                                break;\n
+                            case \'\\\'\':\n
+                                if (jsonmode) {\n
+                                    warningAt("Avoid \\\\\'.", line, character);\n
+                                }\n
+                                break;\n
+                            case \'b\':\n
+                                c = \'\\b\';\n
+                                break;\n
+                            case \'f\':\n
+                                c = \'\\f\';\n
+                                break;\n
+                            case \'n\':\n
+                                c = \'\\n\';\n
+                                break;\n
+                            case \'r\':\n
+                                c = \'\\r\';\n
+                                break;\n
+                            case \'t\':\n
+                                c = \'\\t\';\n
+                                break;\n
+                            case \'0\':\n
+                                c = \'\\0\';\n
+                                // Octal literals fail in strict mode\n
+                                // check if the number is between 00 and 07\n
+                                // where \'n\' is the token next to \'c\'\n
+                                if (n >= 0 && n <= 7 && directive["use strict"]) {\n
+                                    warningAt(\n
+                                    "Octal literals are not allowed in strict mode.",\n
+                                    line, character);\n
+                                }\n
+                                break;\n
+                            case \'u\':\n
+                                esc(4);\n
+                                break;\n
+                            case \'v\':\n
+                                if (jsonmode) {\n
+                                    warningAt("Avoid \\\\v.", line, character);\n
+                                }\n
+                                c = \'\\v\';\n
+                                break;\n
+                            case \'x\':\n
+                                if (jsonmode) {\n
+                                    warningAt("Avoid \\\\x-.", line, character);\n
+                                }\n
+                                esc(2);\n
+                                break;\n
+                            case \'\':\n
+                                // last character is escape character\n
+                                // always allow new line if escaped, but show\n
+                                // warning if option is not set\n
+                                allowNewLine = true;\n
+                                if (option.multistr) {\n
+                                    if (jsonmode) {\n
+                                        warningAt("Avoid EOL escapement.", line, character);\n
+                                    }\n
+                                    c = \'\';\n
+                                    character -= 1;\n
+                                    break;\n
+                                }\n
+                                warningAt("Bad escapement of EOL. Use option multistr if needed.",\n
+                                    line, character);\n
+                                break;\n
+                            default:\n
+                                warningAt("Bad escapement.", line, character);\n
+                            }\n
+                        }\n
+                        r += c;\n
+                        character += 1;\n
+                        j += 1;\n
+                    }\n
+                }\n
+\n
+                for (;;) {\n
+                    if (!s) {\n
+                        return it(nextLine() ? \'(endline)\' : \'(end)\', \'\');\n
+                    }\n
+                    t = match(tx);\n
+                    if (!t) {\n
+                        t = \'\';\n
+                        c = \'\';\n
+                        while (s && s < \'!\') {\n
+                            s = s.substr(1);\n
+                        }\n
+                        if (s) {\n
+                            errorAt("Unexpected \'{a}\'.", line, character, s.substr(0, 1));\n
+                            s = \'\';\n
+                        }\n
+                    } else {\n
+\n
+    //      identifier\n
+\n
+                        if (c.isAlpha() || c === \'_\' || c === \'$\') {\n
+                            return it(\'(identifier)\', t);\n
+                        }\n
+\n
+    //      number\n
+\n
+                        if (c.isDigit()) {\n
+                            if (!isFinite(Number(t))) {\n
+                                warningAt("Bad number \'{a}\'.",\n
+                                    line, character, t);\n
+                            }\n
+                            if (s.substr(0, 1).isAlpha()) {\n
+                                warningAt("Missing space after \'{a}\'.",\n
+                                        line, character, t);\n
+                            }\n
+                            if (c === \'0\') {\n
+                                d = t.substr(1, 1);\n
+                                if (d.isDigit()) {\n
+                                    if (token.id !== \'.\') {\n
+                                        warningAt("Don\'t use extra leading zeros \'{a}\'.",\n
+                                            line, character, t);\n
+                                    }\n
+                                } else if (jsonmode && (d === \'x\' || d === \'X\')) {\n
+                                    warningAt("Avoid 0x-. \'{a}\'.",\n
+                                            line, character, t);\n
+                                }\n
+                            }\n
+                            if (t.substr(t.length - 1) === \'.\') {\n
+                                warningAt(\n
+"A trailing decimal point can be confused with a dot \'{a}\'.", line, character, t);\n
+                            }\n
+                            return it(\'(number)\', t);\n
+                        }\n
+                        switch (t) {\n
+\n
+    //      string\n
+\n
+                        case \'"\':\n
+                        case "\'":\n
+                            return string(t);\n
+\n
+    //      // comment\n
+\n
+                        case \'//\':\n
+                            s = \'\';\n
+                            token.comment = true;\n
+                            break;\n
+\n
+    //      /* comment\n
+\n
+                        case \'/*\':\n
+                            for (;;) {\n
+                                i = s.search(lx);\n
+                                if (i >= 0) {\n
+                                    break;\n
+                                }\n
+                                if (!nextLine()) {\n
+                                    errorAt("Unclosed comment.", line, character);\n
+                                }\n
+                            }\n
+                            character += i + 2;\n
+                            if (s.substr(i, 1) === \'/\') {\n
+                                errorAt("Nested comment.", line, character);\n
+                            }\n
+                            s = s.substr(i + 2);\n
+                            token.comment = true;\n
+                            break;\n
+\n
+    //      /*members /*jshint /*global\n
+\n
+                        case \'/*members\':\n
+                        case \'/*member\':\n
+                        case \'/*jshint\':\n
+                        case \'/*jslint\':\n
+                        case \'/*global\':\n
+                        case \'*/\':\n
+                            return {\n
+                                value: t,\n
+                                type: \'special\',\n
+                                line: line,\n
+                                character: character,\n
+                                from: from\n
+                            };\n
+\n
+                        case \'\':\n
+                            break;\n
+    //      /\n
+                        case \'/\':\n
+                            if (token.id === \'/=\') {\n
+                                errorAt("A regular expression literal can be confused with \'/=\'.",\n
+                                    line, from);\n
+                            }\n
+                            if (prereg) {\n
+                                depth = 0;\n
+                                captures = 0;\n
+                                l = 0;\n
+                                for (;;) {\n
+                                    b = true;\n
+                                    c = s.charAt(l);\n
+                                    l += 1;\n
+                                    switch (c) {\n
+                                    case \'\':\n
+                                        errorAt("Unclosed regular expression.", line, from);\n
+                                        return quit(\'Stopping.\', line, from);\n
+                                    case \'/\':\n
+                                        if (depth > 0) {\n
+                                            warningAt("{a} unterminated regular expression " +\n
+                                                "group(s).", line, from + l, depth);\n
+                                        }\n
+                                        c = s.substr(0, l - 1);\n
+                                        q = {\n
+                                            g: true,\n
+                                            i: true,\n
+                                            m: true\n
+                                        };\n
+                                        while (q[s.charAt(l)] === true) {\n
+                                            q[s.charAt(l)] = false;\n
+                                            l += 1;\n
+                                        }\n
+                                        character += l;\n
+                                        s = s.substr(l);\n
+                                        q = s.charAt(0);\n
+                                        if (q === \'/\' || q === \'*\') {\n
+                                            errorAt("Confusing regular expression.",\n
+                                                    line, from);\n
+                                        }\n
+                                        return it(\'(regexp)\', c);\n
+                                    case \'\\\\\':\n
+                                        c = s.charAt(l);\n
+                                        if (c < \' \') {\n
+                                            warningAt(\n
+"Unexpected control character in regular expression.", line, from + l);\n
+                                        } else if (c === \'<\') {\n
+                                            warningAt(\n
+"Unexpected escaped character \'{a}\' in regular expression.", line, from + l, c);\n
+                                        }\n
+                                        l += 1;\n
+                                        break;\n
+                                    case \'(\':\n
+                                        depth += 1;\n
+                                        b = false;\n
+                                        if (s.charAt(l) === \'?\') {\n
+                                            l += 1;\n
+                                            switch (s.charAt(l)) {\n
+                                            case \':\':\n
+                                            case \'=\':\n
+                                            case \'!\':\n
+                                                l += 1;\n
+                                                break;\n
+                                            default:\n
+                                                warningAt(\n
+"Expected \'{a}\' and instead saw \'{b}\'.", line, from + l, \':\', s.charAt(l));\n
+                                            }\n
+                                        } else {\n
+                                            captures += 1;\n
+                                        }\n
+                                        break;\n
+                                    case \'|\':\n
+                                        b = false;\n
+                                        break;\n
+                                    case \')\':\n
+                                        if (depth === 0) {\n
+                                            warningAt("Unescaped \'{a}\'.",\n
+                                                    line, from + l, \')\');\n
+                                        } else {\n
+                                            depth -= 1;\n
+                                        }\n
+                                        break;\n
+                                    case \' \':\n
+                                        q = 1;\n
+                                        while (s.charAt(l) === \' \') {\n
+                                            l += 1;\n
+                                            q += 1;\n
+                                        }\n
+                                        if (q > 1) {\n
+                                            warningAt(\n
+"Spaces are hard to count. Use {{a}}.", line, from + l, q);\n
+                                        }\n
+                                        break;\n
+                                    case \'[\':\n
+                                        c = s.charAt(l);\n
+                                        if (c === \'^\') {\n
+                                            l += 1;\n
+                                            if (option.regexp) {\n
+                                                warningAt("Insecure \'{a}\'.",\n
+                                                        line, from + l, c);\n
+                                            } else if (s.charAt(l) === \']\') {\n
+                                                errorAt("Unescaped \'{a}\'.",\n
+                                                    line, from + l, \'^\');\n
+                                            }\n
+                                        }\n
+                                        if (c === \']\') {\n
+                                            warningAt("Empty class.", line,\n
+                                                    from + l - 1);\n
+                                        }\n
+                                        isLiteral = false;\n
+                                        isInRange = false;\n
+klass:                                  do {\n
+                                            c = s.charAt(l);\n
+                                            l += 1;\n
+                                            switch (c) {\n
+                                            case \'[\':\n
+                                            case \'^\':\n
+                                                warningAt("Unescaped \'{a}\'.",\n
+                                                        line, from + l, c);\n
+                                                if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else {\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                                break;\n
+                                            case \'-\':\n
+                                                if (isLiteral && !isInRange) {\n
+                                                    isLiteral = false;\n
+                                                    isInRange = true;\n
+                                                } else if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else if (s.charAt(l) === \']\') {\n
+                                                    isInRange = true;\n
+                                                } else {\n
+                                                    if (option.regexdash !== (l === 2 || (l === 3 &&\n
+                                                        s.charAt(1) === \'^\'))) {\n
+                                                        warningAt("Unescaped \'{a}\'.",\n
+                                                            line, from + l - 1, \'-\');\n
+                                                    }\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                                break;\n
+                                            case \']\':\n
+                                                if (isInRange && !option.regexdash) {\n
+                                                    warningAt("Unescaped \'{a}\'.",\n
+                                                            line, from + l - 1, \'-\');\n
+                                                }\n
+                                                break klass;\n
+                                            case \'\\\\\':\n
+                                                c = s.charAt(l);\n
+                                                if (c < \' \') {\n
+                                                    warningAt(\n
+"Unexpected control character in regular expression.", line, from + l);\n
+                                                } else if (c === \'<\') {\n
+                                                    warningAt(\n
+"Unexpected escaped character \'{a}\' in regular expression.", line, from + l, c);\n
+                                                }\n
+                                                l += 1;\n
+\n
+                                                // \\w, \\s and \\d are never part of a character range\n
+                                                if (/[wsd]/i.test(c)) {\n
+                                                    if (isInRange) {\n
+                                                        warningAt("Unescaped \'{a}\'.",\n
+                                                            line, from + l, \'-\');\n
+                                                        isInRange = false;\n
+                                                    }\n
+                                                    isLiteral = false;\n
+                                                } else if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else {\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                                break;\n
+                                            case \'/\':\n
+                                                warningAt("Unescaped \'{a}\'.",\n
+                                                        line, from + l - 1, \'/\');\n
+\n
+                                                if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else {\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                                break;\n
+                                            case \'<\':\n
+                                                if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else {\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                                break;\n
+                                            default:\n
+                                                if (isInRange) {\n
+                                                    isInRange = false;\n
+                                                } else {\n
+                                                    isLiteral = true;\n
+                                                }\n
+                                            }\n
+                                        } while (c);\n
+                                        break;\n
+                                    case \'.\':\n
+                                        if (option.regexp) {\n
+                                            warningAt("Insecure \'{a}\'.", line,\n
+                                                    from + l, c);\n
+                                        }\n
+                                        break;\n
+                                    case \']\':\n
+                                    case \'?\':\n
+                                    case \'{\':\n
+                                    case \'}\':\n
+                                    case \'+\':\n
+                                    case \'*\':\n
+                                        warningAt("Unescaped \'{a}\'.", line,\n
+                                                from + l, c);\n
+                                    }\n
+                                    if (b) {\n
+                                        switch (s.charAt(l)) {\n
+                                        case \'?\':\n
+                                        case \'+\':\n
+                                        case \'*\':\n
+                                            l += 1;\n
+                                            if (s.charAt(l) === \'?\') {\n
+                                                l += 1;\n
+                                            }\n
+                                            break;\n
+                                        case \'{\':\n
+                                            l += 1;\n
+                                            c = s.charAt(l);\n
+                                            if (c < \'0\' || c > \'9\') {\n
+                                                warningAt(\n
+"Expected a number and instead saw \'{a}\'.", line, from + l, c);\n
+                                            }\n
+                                            l += 1;\n
+                                            low = +c;\n
+                                            for (;;) {\n
+                                                c = s.charAt(l);\n
+                                                if (c < \'0\' || c > \'9\') {\n
+                                                    break;\n
+                                                }\n
+                                                l += 1;\n
+                                                low = +c + (low * 10);\n
+                                            }\n
+                                            high = low;\n
+                                            if (c === \',\') {\n
+                                                l += 1;\n
+                                                high = Infinity;\n
+                                                c = s.charAt(l);\n
+                                                if (c >= \'0\' && c <= \'9\') {\n
+                                                    l += 1;\n
+                                                    high = +c;\n
+                                                    for (;;) {\n
+                                                        c = s.charAt(l);\n
+                                                        if (c < \'0\' || c > \'9\') {\n
+                                                            break;\n
+                                                        }\n
+                                                        l += 1;\n
+                                                        high = +c + (high * 10);\n
+                                                    }\n
+                                                }\n
+                                            }\n
+                                            if (s.charAt(l) !== \'}\') {\n
+                                                warningAt(\n
+"Expected \'{a}\' and instead saw \'{b}\'.", line, from + l, \'}\', c);\n
+                                            } else {\n
+                                                l += 1;\n
+                                            }\n
+                                            if (s.charAt(l) === \'?\') {\n
+                                                l += 1;\n
+                                            }\n
+                                            if (low > high) {\n
+                                                warningAt(\n
+"\'{a}\' should not be greater than \'{b}\'.", line, from + l, low, high);\n
+                                            }\n
+                                        }\n
+                                    }\n
+                                }\n
+                                c = s.substr(0, l - 1);\n
+                                character += l;\n
+                                s = s.substr(l);\n
+                                return it(\'(regexp)\', c);\n
+                            }\n
+                            return it(\'(punctuator)\', t);\n
+\n
+    //      punctuator\n
+\n
+                        case \'#\':\n
+                            return it(\'(punctuator)\', t);\n
+                        default:\n
+                            return it(\'(punctuator)\', t);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        };\n
+    }());\n
+\n
+\n
+    function addlabel(t, type) {\n
+\n
+        if (t === \'hasOwnProperty\') {\n
+            warning("\'hasOwnProperty\' is a really bad name.");\n
+        }\n
+\n
+// Define t in the current function in the current scope.\n
+        if (is_own(funct, t) && !funct[\'(global)\']) {\n
+            if (funct[t] === true) {\n
+                if (option.latedef)\n
+                    warning("\'{a}\' was used before it was defined.", nexttoken, t);\n
+            } else {\n
+                if (!option.shadow && type !== "exception")\n
+                    warning("\'{a}\' is already defined.", nexttoken, t);\n
+            }\n
+        }\n
+\n
+        funct[t] = type;\n
+        if (funct[\'(global)\']) {\n
+            global[t] = funct;\n
+            if (is_own(implied, t)) {\n
+                if (option.latedef)\n
+                    warning("\'{a}\' was used before it was defined.", nexttoken, t);\n
+                delete implied[t];\n
+            }\n
+        } else {\n
+            scope[t] = funct;\n
+        }\n
+    }\n
+\n
+\n
+    function doOption() {\n
+        var b, obj, filter, o = nexttoken.value, t, tn, v;\n
+\n
+        switch (o) {\n
+        case \'*/\':\n
+            error("Unbegun comment.");\n
+            break;\n
+        case \'/*members\':\n
+        case \'/*member\':\n
+            o = \'/*members\';\n
+            if (!membersOnly) {\n
+                membersOnly = {};\n
+            }\n
+            obj = membersOnly;\n
+            break;\n
+        case \'/*jshint\':\n
+        case \'/*jslint\':\n
+            obj = option;\n
+            filter = boolOptions;\n
+            break;\n
+        case \'/*global\':\n
+            obj = predefined;\n
+            break;\n
+        default:\n
+            error("What?");\n
+        }\n
+\n
+        t = lex.token();\n
+loop:   for (;;) {\n
+            for (;;) {\n
+                if (t.type === \'special\' && t.value === \'*/\') {\n
+                    break loop;\n
+                }\n
+                if (t.id !== \'(endline)\' && t.id !== \',\') {\n
+                    break;\n
+                }\n
+                t = lex.token();\n
+            }\n
+            if (t.type !== \'(string)\' && t.type !== \'(identifier)\' &&\n
+                    o !== \'/*members\') {\n
+                error("Bad option.", t);\n
+            }\n
+\n
+            v = lex.token();\n
+            if (v.id === \':\') {\n
+                v = lex.token();\n
+\n
+                if (obj === membersOnly) {\n
+                    error("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                            t, \'*/\', \':\');\n
+                }\n
+\n
+                if (o === \'/*jshint\') {\n
+                    checkOption(t.value, t);\n
+                }\n
+\n
+                if (t.value === \'indent\' && (o === \'/*jshint\' || o === \'/*jslint\')) {\n
+                    b = +v.value;\n
+                    if (typeof b !== \'number\' || !isFinite(b) || b <= 0 ||\n
+                            Math.floor(b) !== b) {\n
+                        error("Expected a small integer and instead saw \'{a}\'.",\n
+                                v, v.value);\n
+                    }\n
+                    obj.white = true;\n
+                    obj.indent = b;\n
+                } else if (t.value === \'maxerr\' && (o === \'/*jshint\' || o === \'/*jslint\')) {\n
+                    b = +v.value;\n
+                    if (typeof b !== \'number\' || !isFinite(b) || b <= 0 ||\n
+                            Math.floor(b) !== b) {\n
+                        error("Expected a small integer and instead saw \'{a}\'.",\n
+                                v, v.value);\n
+                    }\n
+                    obj.maxerr = b;\n
+                } else if (t.value === \'maxlen\' && (o === \'/*jshint\' || o === \'/*jslint\')) {\n
+                    b = +v.value;\n
+                    if (typeof b !== \'number\' || !isFinite(b) || b <= 0 ||\n
+                            Math.floor(b) !== b) {\n
+                        error("Expected a small integer and instead saw \'{a}\'.",\n
+                                v, v.value);\n
+                    }\n
+                    obj.maxlen = b;\n
+                } else if (t.value === \'validthis\') {\n
+                    if (funct[\'(global)\']) {\n
+                        error("Option \'validthis\' can\'t be used in a global scope.");\n
+                    } else {\n
+                        if (v.value === \'true\' || v.value === \'false\')\n
+                            obj[t.value] = v.value === \'true\';\n
+                        else\n
+                            error("Bad option value.", v);\n
+                    }\n
+                } else if (v.value === \'true\' || v.value === \'false\') {\n
+                    if (o === \'/*jslint\') {\n
+                        tn = renamedOptions[t.value] || t.value;\n
+                        obj[tn] = v.value === \'true\';\n
+                        if (invertedOptions[tn] !== undefined) {\n
+                            obj[tn] = !obj[tn];\n
+                        }\n
+                    } else {\n
+                        obj[t.value] = v.value === \'true\';\n
+                    }\n
+                } else {\n
+                    error("Bad option value.", v);\n
+                }\n
+                t = lex.token();\n
+            } else {\n
+                if (o === \'/*jshint\' || o === \'/*jslint\') {\n
+                    error("Missing option value.", t);\n
+                }\n
+                obj[t.value] = false;\n
+                t = v;\n
+            }\n
+        }\n
+        if (filter) {\n
+            assume();\n
+        }\n
+    }\n
+\n
+\n
+// We need a peek function. If it has an argument, it peeks that much farther\n
+// ahead. It is used to distinguish\n
+//     for ( var i in ...\n
+// from\n
+//     for ( var i = ...\n
+\n
+    function peek(p) {\n
+        var i = p || 0, j = 0, t;\n
+\n
+        while (j <= i) {\n
+            t = lookahead[j];\n
+            if (!t) {\n
+                t = lookahead[j] = lex.token();\n
+            }\n
+            j += 1;\n
+        }\n
+        return t;\n
+    }\n
+\n
+\n
+\n
+// Produce the next token. It looks for programming errors.\n
+\n
+    function advance(id, t) {\n
+        switch (token.id) {\n
+        case \'(number)\':\n
+            if (nexttoken.id === \'.\') {\n
+                warning("A dot following a number can be confused with a decimal point.", token);\n
+            }\n
+            break;\n
+        case \'-\':\n
+            if (nexttoken.id === \'-\' || nexttoken.id === \'--\') {\n
+                warning("Confusing minusses.");\n
+            }\n
+            break;\n
+        case \'+\':\n
+            if (nexttoken.id === \'+\' || nexttoken.id === \'++\') {\n
+                warning("Confusing plusses.");\n
+            }\n
+            break;\n
+        }\n
+\n
+        if (token.type === \'(string)\' || token.identifier) {\n
+            anonname = token.value;\n
+        }\n
+\n
+        if (id && nexttoken.id !== id) {\n
+            if (t) {\n
+                if (nexttoken.id === \'(end)\') {\n
+                    warning("Unmatched \'{a}\'.", t, t.id);\n
+                } else {\n
+                    warning("Expected \'{a}\' to match \'{b}\' from line {c} and instead saw \'{d}\'.",\n
+                            nexttoken, id, t.id, t.line, nexttoken.value);\n
+                }\n
+            } else if (nexttoken.type !== \'(identifier)\' ||\n
+                            nexttoken.value !== id) {\n
+                warning("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                        nexttoken, id, nexttoken.value);\n
+            }\n
+        }\n
+\n
+        prevtoken = token;\n
+        token = nexttoken;\n
+        for (;;) {\n
+            nexttoken = lookahead.shift() || lex.token();\n
+            if (nexttoken.id === \'(end)\' || nexttoken.id === \'(error)\') {\n
+                return;\n
+            }\n
+            if (nexttoken.type === \'special\') {\n
+                doOption();\n
+            } else {\n
+                if (nexttoken.id !== \'(endline)\') {\n
+                    break;\n
+                }\n
+            }\n
+        }\n
+    }\n
+\n
+\n
+// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\n
+// is looking for ad hoc lint patterns. We add .fud to Pratt\'s model, which is\n
+// like .nud except that it is only used on the first token of a statement.\n
+// Having .fud makes it much easier to define statement-oriented languages like\n
+// JavaScript. I retained Pratt\'s nomenclature.\n
+\n
+// .nud     Null denotation\n
+// .fud     First null denotation\n
+// .led     Left denotation\n
+//  lbp     Left binding power\n
+//  rbp     Right binding power\n
+\n
+// They are elements of the parsing method called Top Down Operator Precedence.\n
+\n
+    function expression(rbp, initial) {\n
+        var left, isArray = false, isObject = false;\n
+\n
+        if (nexttoken.id === \'(end)\')\n
+            error("Unexpected early end of program.", token);\n
+\n
+        advance();\n
+        if (initial) {\n
+            anonname = \'anonymous\';\n
+            funct[\'(verb)\'] = token.value;\n
+        }\n
+        if (initial === true && token.fud) {\n
+            left = token.fud();\n
+        } else {\n
+            if (token.nud) {\n
+                left = token.nud();\n
+            } else {\n
+                if (nexttoken.type === \'(number)\' && token.id === \'.\') {\n
+                    warning("A leading decimal point can be confused with a dot: \'.{a}\'.",\n
+                            token, nexttoken.value);\n
+                    advance();\n
+                    return token;\n
+                } else {\n
+                    error("Expected an identifier and instead saw \'{a}\'.",\n
+                            token, token.id);\n
+                }\n
+            }\n
+            while (rbp < nexttoken.lbp) {\n
+                isArray = token.value === \'Array\';\n
+                isObject = token.value === \'Object\';\n
+\n
+                // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()\n
+                // Line breaks in IfStatement heads exist to satisfy the checkJSHint\n
+                // "Line too long." error.\n
+                if (left && (left.value || (left.first && left.first.value))) {\n
+                    // If the left.value is not "new", or the left.first.value is a "."\n
+                    // then safely assume that this is not "new Array()" and possibly\n
+                    // not "new Object()"...\n
+                    if (left.value !== \'new\' ||\n
+                      (left.first && left.first.value && left.first.value === \'.\')) {\n
+                        isArray = false;\n
+                        // ...In the case of Object, if the left.value and token.value\n
+                        // are not equal, then safely assume that this not "new Object()"\n
+                        if (left.value !== token.value) {\n
+                            isObject = false;\n
+                        }\n
+                    }\n
+                }\n
+\n
+                advance();\n
+                if (isArray && token.id === \'(\' && nexttoken.id === \')\')\n
+                    warning("Use the array literal notation [].", token);\n
+                if (isObject && token.id === \'(\' && nexttoken.id === \')\')\n
+                    warning("Use the object literal notation {}.", token);\n
+                if (token.led) {\n
+                    left = token.led(left);\n
+                } else {\n
+                    error("Expected an operator and instead saw \'{a}\'.",\n
+                        token, token.id);\n
+                }\n
+            }\n
+        }\n
+        return left;\n
+    }\n
+\n
+\n
+// Functions for conformance of style.\n
+\n
+    function adjacent(left, right) {\n
+        left = left || token;\n
+        right = right || nexttoken;\n
+        if (option.white) {\n
+            if (left.character !== right.from && left.line === right.line) {\n
+                left.from += (left.character - left.from);\n
+                warning("Unexpected space after \'{a}\'.", left, left.value);\n
+            }\n
+        }\n
+    }\n
+\n
+    function nobreak(left, right) {\n
+        left = left || token;\n
+        right = right || nexttoken;\n
+        if (option.white && (left.character !== right.from || left.line !== right.line)) {\n
+            warning("Unexpected space before \'{a}\'.", right, right.value);\n
+        }\n
+    }\n
+\n
+    function nospace(left, right) {\n
+        left = left || token;\n
+        right = right || nexttoken;\n
+        if (option.white && !left.comment) {\n
+            if (left.line === right.line) {\n
+                adjacent(left, right);\n
+            }\n
+        }\n
+    }\n
+\n
+    function nonadjacent(left, right) {\n
+        if (option.white) {\n
+            left = left || token;\n
+            right = right || nexttoken;\n
+            if (left.line === right.line && left.character === right.from) {\n
+                left.from += (left.character - left.from);\n
+                warning("Missing space after \'{a}\'.",\n
+                        left, left.value);\n
+            }\n
+        }\n
+    }\n
+\n
+    function nobreaknonadjacent(left, right) {\n
+        left = left || token;\n
+        right = right || nexttoken;\n
+        if (!option.laxbreak && left.line !== right.line) {\n
+            warning("Bad line breaking before \'{a}\'.", right, right.id);\n
+        } else if (option.white) {\n
+            left = left || token;\n
+            right = right || nexttoken;\n
+            if (left.character === right.from) {\n
+                left.from += (left.character - left.from);\n
+                warning("Missing space after \'{a}\'.",\n
+                        left, left.value);\n
+            }\n
+        }\n
+    }\n
+\n
+    function indentation(bias) {\n
+        var i;\n
+        if (option.white && nexttoken.id !== \'(end)\') {\n
+            i = indent + (bias || 0);\n
+            if (nexttoken.from !== i) {\n
+                warning(\n
+"Expected \'{a}\' to have an indentation at {b} instead at {c}.",\n
+                        nexttoken, nexttoken.value, i, nexttoken.from);\n
+            }\n
+        }\n
+    }\n
+\n
+    function nolinebreak(t) {\n
+        t = t || token;\n
+        if (t.line !== nexttoken.line) {\n
+            warning("Line breaking error \'{a}\'.", t, t.value);\n
+        }\n
+    }\n
+\n
+\n
+    function comma() {\n
+        if (token.line !== nexttoken.line) {\n
+            if (!option.laxcomma) {\n
+                if (comma.first) {\n
+                    warning("Comma warnings can be turned off with \'laxcomma\'");\n
+                    comma.first = false;\n
+                }\n
+                warning("Bad line breaking before \'{a}\'.", token, nexttoken.id);\n
+            }\n
+        } else if (!token.comment && token.character !== nexttoken.from && option.white) {\n
+            token.from += (token.character - token.from);\n
+            warning("Unexpected space after \'{a}\'.", token, token.value);\n
+        }\n
+        advance(\',\');\n
+        nonadjacent(token, nexttoken);\n
+    }\n
+\n
+\n
+// Functional constructors for making the symbols that will be inherited by\n
+// tokens.\n
+\n
+    function symbol(s, p) {\n
+        var x = syntax[s];\n
+        if (!x || typeof x !== \'object\') {\n
+            syntax[s] = x = {\n
+                id: s,\n
+                lbp: p,\n
+                value: s\n
+            };\n
+        }\n
+        return x;\n
+    }\n
+\n
+\n
+    function delim(s) {\n
+        return symbol(s, 0);\n
+    }\n
+\n
+\n
+    function stmt(s, f) {\n
+        var x = delim(s);\n
+        x.identifier = x.reserved = true;\n
+        x.fud = f;\n
+        return x;\n
+    }\n
+\n
+\n
+    function blockstmt(s, f) {\n
+        var x = stmt(s, f);\n
+        x.block = true;\n
+        return x;\n
+    }\n
+\n
+\n
+    function reserveName(x) {\n
+        var c = x.id.charAt(0);\n
+        if ((c >= \'a\' && c <= \'z\') || (c >= \'A\' && c <= \'Z\')) {\n
+            x.identifier = x.reserved = true;\n
+        }\n
+        return x;\n
+    }\n
+\n
+\n
+    function prefix(s, f) {\n
+        var x = symbol(s, 150);\n
+        reserveName(x);\n
+        x.nud = (typeof f === \'function\') ? f : function () {\n
+            this.right = expression(150);\n
+            this.arity = \'unary\';\n
+            if (this.id === \'++\' || this.id === \'--\') {\n
+                if (option.plusplus) {\n
+                    warning("Unexpected use of \'{a}\'.", this, this.id);\n
+                } else if ((!this.right.identifier || this.right.reserved) &&\n
+                        this.right.id !== \'.\' && this.right.id !== \'[\') {\n
+                    warning("Bad operand.", this);\n
+                }\n
+            }\n
+            return this;\n
+        };\n
+        return x;\n
+    }\n
+\n
+\n
+    function type(s, f) {\n
+        var x = delim(s);\n
+        x.type = s;\n
+        x.nud = f;\n
+        return x;\n
+    }\n
+\n
+\n
+    function reserve(s, f) {\n
+        var x = type(s, f);\n
+        x.identifier = x.reserved = true;\n
+        return x;\n
+    }\n
+\n
+\n
+    function reservevar(s, v) {\n
+        return reserve(s, function () {\n
+            if (typeof v === \'function\') {\n
+                v(this);\n
+            }\n
+            return this;\n
+        });\n
+    }\n
+\n
+\n
+    function infix(s, f, p, w) {\n
+        var x = symbol(s, p);\n
+        reserveName(x);\n
+        x.led = function (left) {\n
+            if (!w) {\n
+                nobreaknonadjacent(prevtoken, token);\n
+                nonadjacent(token, nexttoken);\n
+            }\n
+            if (s === "in" && left.id === "!") {\n
+                warning("Confusing use of \'{a}\'.", left, \'!\');\n
+            }\n
+            if (typeof f === \'function\') {\n
+                return f(left, this);\n
+            } else {\n
+                this.left = left;\n
+                this.right = expression(p);\n
+                return this;\n
+            }\n
+        };\n
+        return x;\n
+    }\n
+\n
+\n
+    function relation(s, f) {\n
+        var x = symbol(s, 100);\n
+        x.led = function (left) {\n
+            nobreaknonadjacent(prevtoken, token);\n
+            nonadjacent(token, nexttoken);\n
+            var right = expression(100);\n
+            if ((left && left.id === \'NaN\') || (right && right.id === \'NaN\')) {\n
+                warning("Use the isNaN function to compare with NaN.", this);\n
+            } else if (f) {\n
+                f.apply(this, [left, right]);\n
+            }\n
+            if (left.id === \'!\') {\n
+                warning("Confusing use of \'{a}\'.", left, \'!\');\n
+            }\n
+            if (right.id === \'!\') {\n
+                warning("Confusing use of \'{a}\'.", right, \'!\');\n
+            }\n
+            this.left = left;\n
+            this.right = right;\n
+            return this;\n
+        };\n
+        return x;\n
+    }\n
+\n
+\n
+    function isPoorRelation(node) {\n
+        return node &&\n
+              ((node.type === \'(number)\' && +node.value === 0) ||\n
+               (node.type === \'(string)\' && node.value === \'\') ||\n
+               (node.type === \'null\' && !option.eqnull) ||\n
+                node.type === \'true\' ||\n
+                node.type === \'false\' ||\n
+                node.type === \'undefined\');\n
+    }\n
+\n
+\n
+    function assignop(s, f) {\n
+        symbol(s, 20).exps = true;\n
+        return infix(s, function (left, that) {\n
+            var l;\n
+            that.left = left;\n
+            if (predefined[left.value] === false &&\n
+                    scope[left.value][\'(global)\'] === true) {\n
+                warning("Read only.", left);\n
+            } else if (left[\'function\']) {\n
+                warning("\'{a}\' is a function.", left, left.value);\n
+            }\n
+            if (left) {\n
+                if (option.esnext && funct[left.value] === \'const\') {\n
+                    warning("Attempting to override \'{a}\' which is a constant", left, left.value);\n
+                }\n
+                if (left.id === \'.\' || left.id === \'[\') {\n
+                    if (!left.left || left.left.value === \'arguments\') {\n
+                        warning(\'Bad assignment.\', that);\n
+                    }\n
+                    that.right = expression(19);\n
+                    return that;\n
+                } else if (left.identifier && !left.reserved) {\n
+                    if (funct[left.value] === \'exception\') {\n
+                        warning("Do not assign to the exception parameter.", left);\n
+                    }\n
+                    that.right = expression(19);\n
+                    return that;\n
+                }\n
+                if (left === syntax[\'function\']) {\n
+                    warning(\n
+"Expected an identifier in an assignment and instead saw a function invocation.",\n
+                                token);\n
+                }\n
+            }\n
+            error("Bad assignment.", that);\n
+        }, 20);\n
+    }\n
+\n
+\n
+    function bitwise(s, f, p) {\n
+        var x = symbol(s, p);\n
+        reserveName(x);\n
+        x.led = (typeof f === \'function\') ? f : function (left) {\n
+            if (option.bitwise) {\n
+                warning("Unexpected use of \'{a}\'.", this, this.id);\n
+            }\n
+            this.left = left;\n
+            this.right = expression(p);\n
+            return this;\n
+        };\n
+        return x;\n
+    }\n
+\n
+\n
+    function bitwiseassignop(s) {\n
+        symbol(s, 20).exps = true;\n
+        return infix(s, function (left, that) {\n
+            if (option.bitwise) {\n
+                warning("Unexpected use of \'{a}\'.", that, that.id);\n
+            }\n
+            nonadjacent(prevtoken, token);\n
+            nonadjacent(token, nexttoken);\n
+            if (left) {\n
+                if (left.id === \'.\' || left.id === \'[\' ||\n
+                        (left.identifier && !left.reserved)) {\n
+                    expression(19);\n
+                    return that;\n
+                }\n
+                if (left === syntax[\'function\']) {\n
+                    warning(\n
+"Expected an identifier in an assignment, and instead saw a function invocation.",\n
+                                token);\n
+                }\n
+                return that;\n
+            }\n
+            error("Bad assignment.", that);\n
+        }, 20);\n
+    }\n
+\n
+\n
+    function suffix(s, f) {\n
+        var x = symbol(s, 150);\n
+        x.led = function (left) {\n
+            if (option.plusplus) {\n
+                warning("Unexpected use of \'{a}\'.", this, this.id);\n
+            } else if ((!left.identifier || left.reserved) &&\n
+                    left.id !== \'.\' && left.id !== \'[\') {\n
+                warning("Bad operand.", this);\n
+            }\n
+            this.left = left;\n
+            return this;\n
+        };\n
+        return x;\n
+    }\n
+\n
+\n
+    // fnparam means that this identifier is being defined as a function\n
+    // argument (see identifier())\n
+    function optionalidentifier(fnparam) {\n
+        if (nexttoken.identifier) {\n
+            advance();\n
+            if (token.reserved && !option.es5) {\n
+                // `undefined` as a function param is a common pattern to protect\n
+                // against the case when somebody does `undefined = true` and\n
+                // help with minification. More info: https://gist.github.com/315916\n
+                if (!fnparam || token.value !== \'undefined\') {\n
+                    warning("Expected an identifier and instead saw \'{a}\' (a reserved word).",\n
+                            token, token.id);\n
+                }\n
+            }\n
+            return token.value;\n
+        }\n
+    }\n
+\n
+    // fnparam means that this identifier is being defined as a function\n
+    // argument\n
+    function identifier(fnparam) {\n
+        var i = optionalidentifier(fnparam);\n
+        if (i) {\n
+            return i;\n
+        }\n
+        if (token.id === \'function\' && nexttoken.id === \'(\') {\n
+            warning("Missing name in function declaration.");\n
+        } else {\n
+            error("Expected an identifier and instead saw \'{a}\'.",\n
+                    nexttoken, nexttoken.value);\n
+        }\n
+    }\n
+\n
+\n
+    function reachable(s) {\n
+        var i = 0, t;\n
+        if (nexttoken.id !== \';\' || noreach) {\n
+            return;\n
+        }\n
+        for (;;) {\n
+            t = peek(i);\n
+            if (t.reach) {\n
+                return;\n
+            }\n
+            if (t.id !== \'(endline)\') {\n
+                if (t.id === \'function\') {\n
+                    if (!option.latedef) {\n
+                        break;\n
+                    }\n
+                    warning(\n
+"Inner functions should be listed at the top of the outer function.", t);\n
+                    break;\n
+                }\n
+                warning("Unreachable \'{a}\' after \'{b}\'.", t, t.value, s);\n
+                break;\n
+            }\n
+            i += 1;\n
+        }\n
+    }\n
+\n
+\n
+    function statement(noindent) {\n
+        var i = indent, r, s = scope, t = nexttoken;\n
+\n
+        if (t.id === ";") {\n
+            advance(";");\n
+            return;\n
+        }\n
+\n
+// Is this a labelled statement?\n
+\n
+        if (t.identifier && !t.reserved && peek().id === \':\') {\n
+            advance();\n
+            advance(\':\');\n
+            scope = Object.create(s);\n
+            addlabel(t.value, \'label\');\n
+            if (!nexttoken.labelled) {\n
+                warning("Label \'{a}\' on {b} statement.",\n
+                        nexttoken, t.value, nexttoken.value);\n
+            }\n
+            if (jx.test(t.value + \':\')) {\n
+                warning("Label \'{a}\' looks like a javascript url.",\n
+                        t, t.value);\n
+            }\n
+            nexttoken.label = t.value;\n
+            t = nexttoken;\n
+        }\n
+\n
+// Parse the statement.\n
+\n
+        if (!noindent) {\n
+            indentation();\n
+        }\n
+        r = expression(0, true);\n
+\n
+        // Look for the final semicolon.\n
+        if (!t.block) {\n
+            if (!option.expr && (!r || !r.exps)) {\n
+                warning("Expected an assignment or function call and instead saw an expression.",\n
+                    token);\n
+            } else if (option.nonew && r.id === \'(\' && r.left.id === \'new\') {\n
+                warning("Do not use \'new\' for side effects.");\n
+            }\n
+\n
+            if (nexttoken.id === \',\') {\n
+                return comma();\n
+            }\n
+\n
+            if (nexttoken.id !== \';\') {\n
+                if (!option.asi) {\n
+                    // If this is the last statement in a block that ends on\n
+                    // the same line *and* option lastsemic is on, ignore the warning.\n
+                    // Otherwise, complain about missing semicolon.\n
+                    if (!option.lastsemic || nexttoken.id !== \'}\' ||\n
+                            nexttoken.line !== token.line) {\n
+                        warningAt("Missing semicolon.", token.line, token.character);\n
+                    }\n
+                }\n
+            } else {\n
+                adjacent(token, nexttoken);\n
+                advance(\';\');\n
+                nonadjacent(token, nexttoken);\n
+            }\n
+        }\n
+\n
+// Restore the indentation.\n
+\n
+        indent = i;\n
+        scope = s;\n
+        return r;\n
+    }\n
+\n
+\n
+    function statements(startLine) {\n
+        var a = [], f, p;\n
+\n
+        while (!nexttoken.reach && nexttoken.id !== \'(end)\') {\n
+            if (nexttoken.id === \';\') {\n
+                p = peek();\n
+                if (!p || p.id !== "(") {\n
+                    warning("Unnecessary semicolon.");\n
+                }\n
+                advance(\';\');\n
+            } el
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+se {\n
+                a.push(statement(startLine === nexttoken.line));\n
+            }\n
+        }\n
+        return a;\n
+    }\n
+\n
+\n
+    /*\n
+     * read all directives\n
+     * recognizes a simple form of asi, but always\n
+     * warns, if it is used\n
+     */\n
+    function directives() {\n
+        var i, p, pn;\n
+\n
+        for (;;) {\n
+            if (nexttoken.id === "(string)") {\n
+                p = peek(0);\n
+                if (p.id === "(endline)") {\n
+                    i = 1;\n
+                    do {\n
+                        pn = peek(i);\n
+                        i = i + 1;\n
+                    } while (pn.id === "(endline)");\n
+\n
+                    if (pn.id !== ";") {\n
+                        if (pn.id !== "(string)" && pn.id !== "(number)" &&\n
+                            pn.id !== "(regexp)" && pn.identifier !== true &&\n
+                            pn.id !== "}") {\n
+                            break;\n
+                        }\n
+                        warning("Missing semicolon.", nexttoken);\n
+                    } else {\n
+                        p = pn;\n
+                    }\n
+                } else if (p.id === "}") {\n
+                    // directive with no other statements, warn about missing semicolon\n
+                    warning("Missing semicolon.", p);\n
+                } else if (p.id !== ";") {\n
+                    break;\n
+                }\n
+\n
+                indentation();\n
+                advance();\n
+                if (directive[token.value]) {\n
+                    warning("Unnecessary directive \\"{a}\\".", token, token.value);\n
+                }\n
+\n
+                if (token.value === "use strict") {\n
+                    option.newcap = true;\n
+                    option.undef = true;\n
+                }\n
+\n
+                // there\'s no directive negation, so always set to true\n
+                directive[token.value] = true;\n
+\n
+                if (p.id === ";") {\n
+                    advance(";");\n
+                }\n
+                continue;\n
+            }\n
+            break;\n
+        }\n
+    }\n
+\n
+\n
+    /*\n
+     * Parses a single block. A block is a sequence of statements wrapped in\n
+     * braces.\n
+     *\n
+     * ordinary - true for everything but function bodies and try blocks.\n
+     * stmt     - true if block can be a single statement (e.g. in if/for/while).\n
+     * isfunc   - true if block is a function body\n
+     */\n
+    function block(ordinary, stmt, isfunc) {\n
+        var a,\n
+            b = inblock,\n
+            old_indent = indent,\n
+            m,\n
+            s = scope,\n
+            t,\n
+            line,\n
+            d;\n
+\n
+        inblock = ordinary;\n
+        if (!ordinary || !option.funcscope) scope = Object.create(scope);\n
+        nonadjacent(token, nexttoken);\n
+        t = nexttoken;\n
+\n
+        if (nexttoken.id === \'{\') {\n
+            advance(\'{\');\n
+            line = token.line;\n
+            if (nexttoken.id !== \'}\') {\n
+                indent += option.indent;\n
+                while (!ordinary && nexttoken.from > indent) {\n
+                    indent += option.indent;\n
+                }\n
+\n
+                if (isfunc) {\n
+                    m = {};\n
+                    for (d in directive) {\n
+                        if (is_own(directive, d)) {\n
+                            m[d] = directive[d];\n
+                        }\n
+                    }\n
+                    directives();\n
+\n
+                    if (option.strict && funct[\'(context)\'][\'(global)\']) {\n
+                        if (!m["use strict"] && !directive["use strict"]) {\n
+                            warning("Missing \\"use strict\\" statement.");\n
+                        }\n
+                    }\n
+                }\n
+\n
+                a = statements(line);\n
+\n
+                if (isfunc) {\n
+                    directive = m;\n
+                }\n
+\n
+                indent -= option.indent;\n
+                if (line !== nexttoken.line) {\n
+                    indentation();\n
+                }\n
+            } else if (line !== nexttoken.line) {\n
+                indentation();\n
+            }\n
+            advance(\'}\', t);\n
+            indent = old_indent;\n
+        } else if (!ordinary) {\n
+            error("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                  nexttoken, \'{\', nexttoken.value);\n
+        } else {\n
+            if (!stmt || option.curly)\n
+                warning("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                        nexttoken, \'{\', nexttoken.value);\n
+\n
+            noreach = true;\n
+            indent += option.indent;\n
+            // test indentation only if statement is in new line\n
+            a = [statement(nexttoken.line === token.line)];\n
+            indent -= option.indent;\n
+            noreach = false;\n
+        }\n
+        funct[\'(verb)\'] = null;\n
+        if (!ordinary || !option.funcscope) scope = s;\n
+        inblock = b;\n
+        if (ordinary && option.noempty && (!a || a.length === 0)) {\n
+            warning("Empty block.");\n
+        }\n
+        return a;\n
+    }\n
+\n
+\n
+    function countMember(m) {\n
+        if (membersOnly && typeof membersOnly[m] !== \'boolean\') {\n
+            warning("Unexpected /*member \'{a}\'.", token, m);\n
+        }\n
+        if (typeof member[m] === \'number\') {\n
+            member[m] += 1;\n
+        } else {\n
+            member[m] = 1;\n
+        }\n
+    }\n
+\n
+\n
+    function note_implied(token) {\n
+        var name = token.value, line = token.line, a = implied[name];\n
+        if (typeof a === \'function\') {\n
+            a = false;\n
+        }\n
+\n
+        if (!a) {\n
+            a = [line];\n
+            implied[name] = a;\n
+        } else if (a[a.length - 1] !== line) {\n
+            a.push(line);\n
+        }\n
+    }\n
+\n
+\n
+    // Build the syntax table by declaring the syntactic elements of the language.\n
+\n
+    type(\'(number)\', function () {\n
+        return this;\n
+    });\n
+\n
+    type(\'(string)\', function () {\n
+        return this;\n
+    });\n
+\n
+    syntax[\'(identifier)\'] = {\n
+        type: \'(identifier)\',\n
+        lbp: 0,\n
+        identifier: true,\n
+        nud: function () {\n
+            var v = this.value,\n
+                s = scope[v],\n
+                f;\n
+\n
+            if (typeof s === \'function\') {\n
+                // Protection against accidental inheritance.\n
+                s = undefined;\n
+            } else if (typeof s === \'boolean\') {\n
+                f = funct;\n
+                funct = functions[0];\n
+                addlabel(v, \'var\');\n
+                s = funct;\n
+                funct = f;\n
+            }\n
+\n
+            // The name is in scope and defined in the current function.\n
+            if (funct === s) {\n
+                // Change \'unused\' to \'var\', and reject labels.\n
+                switch (funct[v]) {\n
+                case \'unused\':\n
+                    funct[v] = \'var\';\n
+                    break;\n
+                case \'unction\':\n
+                    funct[v] = \'function\';\n
+                    this[\'function\'] = true;\n
+                    break;\n
+                case \'function\':\n
+                    this[\'function\'] = true;\n
+                    break;\n
+                case \'label\':\n
+                    warning("\'{a}\' is a statement label.", token, v);\n
+                    break;\n
+                }\n
+            } else if (funct[\'(global)\']) {\n
+                // The name is not defined in the function.  If we are in the global\n
+                // scope, then we have an undefined variable.\n
+                //\n
+                // Operators typeof and delete do not raise runtime errors even if\n
+                // the base object of a reference is null so no need to display warning\n
+                // if we\'re inside of typeof or delete.\n
+\n
+                if (option.undef && typeof predefined[v] !== \'boolean\') {\n
+                    // Attempting to subscript a null reference will throw an\n
+                    // error, even within the typeof and delete operators\n
+                    if (!(anonname === \'typeof\' || anonname === \'delete\') ||\n
+                        (nexttoken && (nexttoken.value === \'.\' || nexttoken.value === \'[\'))) {\n
+\n
+                        isundef(funct, "\'{a}\' is not defined.", token, v);\n
+                    }\n
+                }\n
+                note_implied(token);\n
+            } else {\n
+                // If the name is already defined in the current\n
+                // function, but not as outer, then there is a scope error.\n
+\n
+                switch (funct[v]) {\n
+                case \'closure\':\n
+                case \'function\':\n
+                case \'var\':\n
+                case \'unused\':\n
+                    warning("\'{a}\' used out of scope.", token, v);\n
+                    break;\n
+                case \'label\':\n
+                    warning("\'{a}\' is a statement label.", token, v);\n
+                    break;\n
+                case \'outer\':\n
+                case \'global\':\n
+                    break;\n
+                default:\n
+                    // If the name is defined in an outer function, make an outer entry,\n
+                    // and if it was unused, make it var.\n
+                    if (s === true) {\n
+                        funct[v] = true;\n
+                    } else if (s === null) {\n
+                        warning("\'{a}\' is not allowed.", token, v);\n
+                        note_implied(token);\n
+                    } else if (typeof s !== \'object\') {\n
+                        // Operators typeof and delete do not raise runtime errors even\n
+                        // if the base object of a reference is null so no need to\n
+                        // display warning if we\'re inside of typeof or delete.\n
+                        if (option.undef) {\n
+                            // Attempting to subscript a null reference will throw an\n
+                            // error, even within the typeof and delete operators\n
+                            if (!(anonname === \'typeof\' || anonname === \'delete\') ||\n
+                                (nexttoken &&\n
+                                    (nexttoken.value === \'.\' || nexttoken.value === \'[\'))) {\n
+\n
+                                isundef(funct, "\'{a}\' is not defined.", token, v);\n
+                            }\n
+                        }\n
+                        funct[v] = true;\n
+                        note_implied(token);\n
+                    } else {\n
+                        switch (s[v]) {\n
+                        case \'function\':\n
+                        case \'unction\':\n
+                            this[\'function\'] = true;\n
+                            s[v] = \'closure\';\n
+                            funct[v] = s[\'(global)\'] ? \'global\' : \'outer\';\n
+                            break;\n
+                        case \'var\':\n
+                        case \'unused\':\n
+                            s[v] = \'closure\';\n
+                            funct[v] = s[\'(global)\'] ? \'global\' : \'outer\';\n
+                            break;\n
+                        case \'closure\':\n
+                        case \'parameter\':\n
+                            funct[v] = s[\'(global)\'] ? \'global\' : \'outer\';\n
+                            break;\n
+                        case \'label\':\n
+                            warning("\'{a}\' is a statement label.", token, v);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+            return this;\n
+        },\n
+        led: function () {\n
+            error("Expected an operator and instead saw \'{a}\'.",\n
+                nexttoken, nexttoken.value);\n
+        }\n
+    };\n
+\n
+    type(\'(regexp)\', function () {\n
+        return this;\n
+    });\n
+\n
+\n
+// ECMAScript parser\n
+\n
+    delim(\'(endline)\');\n
+    delim(\'(begin)\');\n
+    delim(\'(end)\').reach = true;\n
+    delim(\'</\').reach = true;\n
+    delim(\'<!\');\n
+    delim(\'<!--\');\n
+    delim(\'-->\');\n
+    delim(\'(error)\').reach = true;\n
+    delim(\'}\').reach = true;\n
+    delim(\')\');\n
+    delim(\']\');\n
+    delim(\'"\').reach = true;\n
+    delim("\'").reach = true;\n
+    delim(\';\');\n
+    delim(\':\').reach = true;\n
+    delim(\',\');\n
+    delim(\'#\');\n
+    delim(\'@\');\n
+    reserve(\'else\');\n
+    reserve(\'case\').reach = true;\n
+    reserve(\'catch\');\n
+    reserve(\'default\').reach = true;\n
+    reserve(\'finally\');\n
+    reservevar(\'arguments\', function (x) {\n
+        if (directive[\'use strict\'] && funct[\'(global)\']) {\n
+            warning("Strict violation.", x);\n
+        }\n
+    });\n
+    reservevar(\'eval\');\n
+    reservevar(\'false\');\n
+    reservevar(\'Infinity\');\n
+    reservevar(\'NaN\');\n
+    reservevar(\'null\');\n
+    reservevar(\'this\', function (x) {\n
+        if (directive[\'use strict\'] && !option.validthis && ((funct[\'(statement)\'] &&\n
+                funct[\'(name)\'].charAt(0) > \'Z\') || funct[\'(global)\'])) {\n
+            warning("Possible strict violation.", x);\n
+        }\n
+    });\n
+    reservevar(\'true\');\n
+    reservevar(\'undefined\');\n
+    assignop(\'=\', \'assign\', 20);\n
+    assignop(\'+=\', \'assignadd\', 20);\n
+    assignop(\'-=\', \'assignsub\', 20);\n
+    assignop(\'*=\', \'assignmult\', 20);\n
+    assignop(\'/=\', \'assigndiv\', 20).nud = function () {\n
+        error("A regular expression literal can be confused with \'/=\'.");\n
+    };\n
+    assignop(\'%=\', \'assignmod\', 20);\n
+    bitwiseassignop(\'&=\', \'assignbitand\', 20);\n
+    bitwiseassignop(\'|=\', \'assignbitor\', 20);\n
+    bitwiseassignop(\'^=\', \'assignbitxor\', 20);\n
+    bitwiseassignop(\'<<=\', \'assignshiftleft\', 20);\n
+    bitwiseassignop(\'>>=\', \'assignshiftright\', 20);\n
+    bitwiseassignop(\'>>>=\', \'assignshiftrightunsigned\', 20);\n
+    infix(\'?\', function (left, that) {\n
+        that.left = left;\n
+        that.right = expression(10);\n
+        advance(\':\');\n
+        that[\'else\'] = expression(10);\n
+        return that;\n
+    }, 30);\n
+\n
+    infix(\'||\', \'or\', 40);\n
+    infix(\'&&\', \'and\', 50);\n
+    bitwise(\'|\', \'bitor\', 70);\n
+    bitwise(\'^\', \'bitxor\', 80);\n
+    bitwise(\'&\', \'bitand\', 90);\n
+    relation(\'==\', function (left, right) {\n
+        var eqnull = option.eqnull && (left.value === \'null\' || right.value === \'null\');\n
+\n
+        if (!eqnull && option.eqeqeq)\n
+            warning("Expected \'{a}\' and instead saw \'{b}\'.", this, \'===\', \'==\');\n
+        else if (isPoorRelation(left))\n
+            warning("Use \'{a}\' to compare with \'{b}\'.", this, \'===\', left.value);\n
+        else if (isPoorRelation(right))\n
+            warning("Use \'{a}\' to compare with \'{b}\'.", this, \'===\', right.value);\n
+\n
+        return this;\n
+    });\n
+    relation(\'===\');\n
+    relation(\'!=\', function (left, right) {\n
+        var eqnull = option.eqnull &&\n
+                (left.value === \'null\' || right.value === \'null\');\n
+\n
+        if (!eqnull && option.eqeqeq) {\n
+            warning("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                    this, \'!==\', \'!=\');\n
+        } else if (isPoorRelation(left)) {\n
+            warning("Use \'{a}\' to compare with \'{b}\'.",\n
+                    this, \'!==\', left.value);\n
+        } else if (isPoorRelation(right)) {\n
+            warning("Use \'{a}\' to compare with \'{b}\'.",\n
+                    this, \'!==\', right.value);\n
+        }\n
+        return this;\n
+    });\n
+    relation(\'!==\');\n
+    relation(\'<\');\n
+    relation(\'>\');\n
+    relation(\'<=\');\n
+    relation(\'>=\');\n
+    bitwise(\'<<\', \'shiftleft\', 120);\n
+    bitwise(\'>>\', \'shiftright\', 120);\n
+    bitwise(\'>>>\', \'shiftrightunsigned\', 120);\n
+    infix(\'in\', \'in\', 120);\n
+    infix(\'instanceof\', \'instanceof\', 120);\n
+    infix(\'+\', function (left, that) {\n
+        var right = expression(130);\n
+        if (left && right && left.id === \'(string)\' && right.id === \'(string)\') {\n
+            left.value += right.value;\n
+            left.character = right.character;\n
+            if (!option.scripturl && jx.test(left.value)) {\n
+                warning("JavaScript URL.", left);\n
+            }\n
+            return left;\n
+        }\n
+        that.left = left;\n
+        that.right = right;\n
+        return that;\n
+    }, 130);\n
+    prefix(\'+\', \'num\');\n
+    prefix(\'+++\', function () {\n
+        warning("Confusing pluses.");\n
+        this.right = expression(150);\n
+        this.arity = \'unary\';\n
+        return this;\n
+    });\n
+    infix(\'+++\', function (left) {\n
+        warning("Confusing pluses.");\n
+        this.left = left;\n
+        this.right = expression(130);\n
+        return this;\n
+    }, 130);\n
+    infix(\'-\', \'sub\', 130);\n
+    prefix(\'-\', \'neg\');\n
+    prefix(\'---\', function () {\n
+        warning("Confusing minuses.");\n
+        this.right = expression(150);\n
+        this.arity = \'unary\';\n
+        return this;\n
+    });\n
+    infix(\'---\', function (left) {\n
+        warning("Confusing minuses.");\n
+        this.left = left;\n
+        this.right = expression(130);\n
+        return this;\n
+    }, 130);\n
+    infix(\'*\', \'mult\', 140);\n
+    infix(\'/\', \'div\', 140);\n
+    infix(\'%\', \'mod\', 140);\n
+\n
+    suffix(\'++\', \'postinc\');\n
+    prefix(\'++\', \'preinc\');\n
+    syntax[\'++\'].exps = true;\n
+\n
+    suffix(\'--\', \'postdec\');\n
+    prefix(\'--\', \'predec\');\n
+    syntax[\'--\'].exps = true;\n
+    prefix(\'delete\', function () {\n
+        var p = expression(0);\n
+        if (!p || (p.id !== \'.\' && p.id !== \'[\')) {\n
+            warning("Variables should not be deleted.");\n
+        }\n
+        this.first = p;\n
+        return this;\n
+    }).exps = true;\n
+\n
+    prefix(\'~\', function () {\n
+        if (option.bitwise) {\n
+            warning("Unexpected \'{a}\'.", this, \'~\');\n
+        }\n
+        expression(150);\n
+        return this;\n
+    });\n
+\n
+    prefix(\'!\', function () {\n
+        this.right = expression(150);\n
+        this.arity = \'unary\';\n
+        if (bang[this.right.id] === true) {\n
+            warning("Confusing use of \'{a}\'.", this, \'!\');\n
+        }\n
+        return this;\n
+    });\n
+    prefix(\'typeof\', \'typeof\');\n
+    prefix(\'new\', function () {\n
+        var c = expression(155), i;\n
+        if (c && c.id !== \'function\') {\n
+            if (c.identifier) {\n
+                c[\'new\'] = true;\n
+                switch (c.value) {\n
+                case \'Number\':\n
+                case \'String\':\n
+                case \'Boolean\':\n
+                case \'Math\':\n
+                case \'JSON\':\n
+                    warning("Do not use {a} as a constructor.", token, c.value);\n
+                    break;\n
+                case \'Function\':\n
+                    if (!option.evil) {\n
+                        warning("The Function constructor is eval.");\n
+                    }\n
+                    break;\n
+                case \'Date\':\n
+                case \'RegExp\':\n
+                    break;\n
+                default:\n
+                    if (c.id !== \'function\') {\n
+                        i = c.value.substr(0, 1);\n
+                        if (option.newcap && (i < \'A\' || i > \'Z\')) {\n
+                            warning("A constructor name should start with an uppercase letter.",\n
+                                token);\n
+                        }\n
+                    }\n
+                }\n
+            } else {\n
+                if (c.id !== \'.\' && c.id !== \'[\' && c.id !== \'(\') {\n
+                    warning("Bad constructor.", token);\n
+                }\n
+            }\n
+        } else {\n
+            if (!option.supernew)\n
+                warning("Weird construction. Delete \'new\'.", this);\n
+        }\n
+        adjacent(token, nexttoken);\n
+        if (nexttoken.id !== \'(\' && !option.supernew) {\n
+            warning("Missing \'()\' invoking a constructor.");\n
+        }\n
+        this.first = c;\n
+        return this;\n
+    });\n
+    syntax[\'new\'].exps = true;\n
+\n
+    prefix(\'void\').exps = true;\n
+\n
+    infix(\'.\', function (left, that) {\n
+        adjacent(prevtoken, token);\n
+        nobreak();\n
+        var m = identifier();\n
+        if (typeof m === \'string\') {\n
+            countMember(m);\n
+        }\n
+        that.left = left;\n
+        that.right = m;\n
+        if (left && left.value === \'arguments\' && (m === \'callee\' || m === \'caller\')) {\n
+            if (option.noarg)\n
+                warning("Avoid arguments.{a}.", left, m);\n
+            else if (directive[\'use strict\'])\n
+                error(\'Strict violation.\');\n
+        } else if (!option.evil && left && left.value === \'document\' &&\n
+                (m === \'write\' || m === \'writeln\')) {\n
+            warning("document.write can be a form of eval.", left);\n
+        }\n
+        if (!option.evil && (m === \'eval\' || m === \'execScript\')) {\n
+            warning(\'eval is evil.\');\n
+        }\n
+        return that;\n
+    }, 160, true);\n
+\n
+    infix(\'(\', function (left, that) {\n
+        if (prevtoken.id !== \'}\' && prevtoken.id !== \')\') {\n
+            nobreak(prevtoken, token);\n
+        }\n
+        nospace();\n
+        if (option.immed && !left.immed && left.id === \'function\') {\n
+            warning("Wrap an immediate function invocation in parentheses " +\n
+                "to assist the reader in understanding that the expression " +\n
+                "is the result of a function, and not the function itself.");\n
+        }\n
+        var n = 0,\n
+            p = [];\n
+        if (left) {\n
+            if (left.type === \'(identifier)\') {\n
+                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n
+                    if (left.value !== \'Number\' && left.value !== \'String\' &&\n
+                            left.value !== \'Boolean\' &&\n
+                            left.value !== \'Date\') {\n
+                        if (left.value === \'Math\') {\n
+                            warning("Math is not a function.", left);\n
+                        } else if (option.newcap) {\n
+                            warning(\n
+"Missing \'new\' prefix when invoking a constructor.", left);\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        if (nexttoken.id !== \')\') {\n
+            for (;;) {\n
+                p[p.length] = expression(10);\n
+                n += 1;\n
+                if (nexttoken.id !== \',\') {\n
+                    break;\n
+                }\n
+                comma();\n
+            }\n
+        }\n
+        advance(\')\');\n
+        nospace(prevtoken, token);\n
+        if (typeof left === \'object\') {\n
+            if (left.value === \'parseInt\' && n === 1) {\n
+                warning("Missing radix parameter.", left);\n
+            }\n
+            if (!option.evil) {\n
+                if (left.value === \'eval\' || left.value === \'Function\' ||\n
+                        left.value === \'execScript\') {\n
+                    warning("eval is evil.", left);\n
+                } else if (p[0] && p[0].id === \'(string)\' &&\n
+                       (left.value === \'setTimeout\' ||\n
+                        left.value === \'setInterval\')) {\n
+                    warning(\n
+    "Implied eval is evil. Pass a function instead of a string.", left);\n
+                }\n
+            }\n
+            if (!left.identifier && left.id !== \'.\' && left.id !== \'[\' &&\n
+                    left.id !== \'(\' && left.id !== \'&&\' && left.id !== \'||\' &&\n
+                    left.id !== \'?\') {\n
+                warning("Bad invocation.", left);\n
+            }\n
+        }\n
+        that.left = left;\n
+        return that;\n
+    }, 155, true).exps = true;\n
+\n
+    prefix(\'(\', function () {\n
+        nospace();\n
+        if (nexttoken.id === \'function\') {\n
+            nexttoken.immed = true;\n
+        }\n
+        var v = expression(0);\n
+        advance(\')\', this);\n
+        nospace(prevtoken, token);\n
+        if (option.immed && v.id === \'function\') {\n
+            if (nexttoken.id === \'(\' ||\n
+              (nexttoken.id === \'.\' && (peek().value === \'call\' || peek().value === \'apply\'))) {\n
+                warning(\n
+"Move the invocation into the parens that contain the function.", nexttoken);\n
+            } else {\n
+                warning(\n
+"Do not wrap function literals in parens unless they are to be immediately invoked.",\n
+                        this);\n
+            }\n
+        }\n
+        return v;\n
+    });\n
+\n
+    infix(\'[\', function (left, that) {\n
+        nobreak(prevtoken, token);\n
+        nospace();\n
+        var e = expression(0), s;\n
+        if (e && e.type === \'(string)\') {\n
+            if (!option.evil && (e.value === \'eval\' || e.value === \'execScript\')) {\n
+                warning("eval is evil.", that);\n
+            }\n
+            countMember(e.value);\n
+            if (!option.sub && ix.test(e.value)) {\n
+                s = syntax[e.value];\n
+                if (!s || !s.reserved) {\n
+                    warning("[\'{a}\'] is better written in dot notation.",\n
+                            e, e.value);\n
+                }\n
+            }\n
+        }\n
+        advance(\']\', that);\n
+        nospace(prevtoken, token);\n
+        that.left = left;\n
+        that.right = e;\n
+        return that;\n
+    }, 160, true);\n
+\n
+    prefix(\'[\', function () {\n
+        var b = token.line !== nexttoken.line;\n
+        this.first = [];\n
+        if (b) {\n
+            indent += option.indent;\n
+            if (nexttoken.from === indent + option.indent) {\n
+                indent += option.indent;\n
+            }\n
+        }\n
+        while (nexttoken.id !== \'(end)\') {\n
+            while (nexttoken.id === \',\') {\n
+                warning("Extra comma.");\n
+                advance(\',\');\n
+            }\n
+            if (nexttoken.id === \']\') {\n
+                break;\n
+            }\n
+            if (b && token.line !== nexttoken.line) {\n
+                indentation();\n
+            }\n
+            this.first.push(expression(10));\n
+            if (nexttoken.id === \',\') {\n
+                comma();\n
+                if (nexttoken.id === \']\' && !option.es5) {\n
+                    warning("Extra comma.", token);\n
+                    break;\n
+                }\n
+            } else {\n
+                break;\n
+            }\n
+        }\n
+        if (b) {\n
+            indent -= option.indent;\n
+            indentation();\n
+        }\n
+        advance(\']\', this);\n
+        return this;\n
+    }, 160);\n
+\n
+\n
+    function property_name() {\n
+        var id = optionalidentifier(true);\n
+        if (!id) {\n
+            if (nexttoken.id === \'(string)\') {\n
+                id = nexttoken.value;\n
+                advance();\n
+            } else if (nexttoken.id === \'(number)\') {\n
+                id = nexttoken.value.toString();\n
+                advance();\n
+            }\n
+        }\n
+        return id;\n
+    }\n
+\n
+\n
+    function functionparams() {\n
+        var i, t = nexttoken, p = [];\n
+        advance(\'(\');\n
+        nospace();\n
+        if (nexttoken.id === \')\') {\n
+            advance(\')\');\n
+            return;\n
+        }\n
+        for (;;) {\n
+            i = identifier(true);\n
+            p.push(i);\n
+            addlabel(i, \'parameter\');\n
+            if (nexttoken.id === \',\') {\n
+                comma();\n
+            } else {\n
+                advance(\')\', t);\n
+                nospace(prevtoken, token);\n
+                return p;\n
+            }\n
+        }\n
+    }\n
+\n
+\n
+    function doFunction(i, statement) {\n
+        var f,\n
+            oldOption = option,\n
+            oldScope  = scope;\n
+\n
+        option = Object.create(option);\n
+        scope = Object.create(scope);\n
+\n
+        funct = {\n
+            \'(name)\'     : i || \'"\' + anonname + \'"\',\n
+            \'(line)\'     : nexttoken.line,\n
+            \'(context)\'  : funct,\n
+            \'(breakage)\' : 0,\n
+            \'(loopage)\'  : 0,\n
+            \'(scope)\'    : scope,\n
+            \'(statement)\': statement\n
+        };\n
+        f = funct;\n
+        token.funct = funct;\n
+        functions.push(funct);\n
+        if (i) {\n
+            addlabel(i, \'function\');\n
+        }\n
+        funct[\'(params)\'] = functionparams();\n
+\n
+        block(false, false, true);\n
+        scope = oldScope;\n
+        option = oldOption;\n
+        funct[\'(last)\'] = token.line;\n
+        funct = funct[\'(context)\'];\n
+        return f;\n
+    }\n
+\n
+\n
+    (function (x) {\n
+        x.nud = function () {\n
+            var b, f, i, j, p, t;\n
+            var props = {}; // All properties, including accessors\n
+\n
+            function saveProperty(name, token) {\n
+                if (props[name] && is_own(props, name))\n
+                    warning("Duplicate member \'{a}\'.", nexttoken, i);\n
+                else\n
+                    props[name] = {};\n
+\n
+                props[name].basic = true;\n
+                props[name].basicToken = token;\n
+            }\n
+\n
+            function saveSetter(name, token) {\n
+                if (props[name] && is_own(props, name)) {\n
+                    if (props[name].basic || props[name].setter)\n
+                        warning("Duplicate member \'{a}\'.", nexttoken, i);\n
+                } else {\n
+                    props[name] = {};\n
+                }\n
+\n
+                props[name].setter = true;\n
+                props[name].setterToken = token;\n
+            }\n
+\n
+            function saveGetter(name) {\n
+                if (props[name] && is_own(props, name)) {\n
+                    if (props[name].basic || props[name].getter)\n
+                        warning("Duplicate member \'{a}\'.", nexttoken, i);\n
+                } else {\n
+                    props[name] = {};\n
+                }\n
+\n
+                props[name].getter = true;\n
+                props[name].getterToken = token;\n
+            }\n
+\n
+            b = token.line !== nexttoken.line;\n
+            if (b) {\n
+                indent += option.indent;\n
+                if (nexttoken.from === indent + option.indent) {\n
+                    indent += option.indent;\n
+                }\n
+            }\n
+            for (;;) {\n
+                if (nexttoken.id === \'}\') {\n
+                    break;\n
+                }\n
+                if (b) {\n
+                    indentation();\n
+                }\n
+                if (nexttoken.value === \'get\' && peek().id !== \':\') {\n
+                    advance(\'get\');\n
+                    if (!option.es5) {\n
+                        error("get/set are ES5 features.");\n
+                    }\n
+                    i = property_name();\n
+                    if (!i) {\n
+                        error("Missing property name.");\n
+                    }\n
+                    saveGetter(i);\n
+                    t = nexttoken;\n
+                    adjacent(token, nexttoken);\n
+                    f = doFunction();\n
+                    p = f[\'(params)\'];\n
+                    if (p) {\n
+                        warning("Unexpected parameter \'{a}\' in get {b} function.", t, p[0], i);\n
+                    }\n
+                    adjacent(token, nexttoken);\n
+                } else if (nexttoken.value === \'set\' && peek().id !== \':\') {\n
+                    advance(\'set\');\n
+                    if (!option.es5) {\n
+                        error("get/set are ES5 features.");\n
+                    }\n
+                    i = property_name();\n
+                    if (!i) {\n
+                        error("Missing property name.");\n
+                    }\n
+                    saveSetter(i, nexttoken);\n
+                    t = nexttoken;\n
+                    adjacent(token, nexttoken);\n
+                    f = doFunction();\n
+                    p = f[\'(params)\'];\n
+                    if (!p || p.length !== 1) {\n
+                        warning("Expected a single parameter in set {a} function.", t, i);\n
+                    }\n
+                } else {\n
+                    i = property_name();\n
+                    saveProperty(i, nexttoken);\n
+                    if (typeof i !== \'string\') {\n
+                        break;\n
+                    }\n
+                    advance(\':\');\n
+                    nonadjacent(token, nexttoken);\n
+                    expression(10);\n
+                }\n
+\n
+                countMember(i);\n
+                if (nexttoken.id === \',\') {\n
+                    comma();\n
+                    if (nexttoken.id === \',\') {\n
+                        warning("Extra comma.", token);\n
+                    } else if (nexttoken.id === \'}\' && !option.es5) {\n
+                        warning("Extra comma.", token);\n
+                    }\n
+                } else {\n
+                    break;\n
+                }\n
+            }\n
+            if (b) {\n
+                indent -= option.indent;\n
+                indentation();\n
+            }\n
+            advance(\'}\', this);\n
+\n
+            // Check for lonely setters if in the ES5 mode.\n
+            if (option.es5) {\n
+                for (var name in props) {\n
+                    if (is_own(props, name) && props[name].setter && !props[name].getter) {\n
+                        warning("Setter is defined without getter.", props[name].setterToken);\n
+                    }\n
+                }\n
+            }\n
+            return this;\n
+        };\n
+        x.fud = function () {\n
+            error("Expected to see a statement and instead saw a block.", token);\n
+        };\n
+    }(delim(\'{\')));\n
+\n
+// This Function is called when esnext option is set to true\n
+// it adds the `const` statement to JSHINT\n
+\n
+    useESNextSyntax = function () {\n
+        var conststatement = stmt(\'const\', function (prefix) {\n
+            var id, name, value;\n
+\n
+            this.first = [];\n
+            for (;;) {\n
+                nonadjacent(token, nexttoken);\n
+                id = identifier();\n
+                if (funct[id] === "const") {\n
+                    warning("const \'" + id + "\' has already been declared");\n
+                }\n
+                if (funct[\'(global)\'] && predefined[id] === false) {\n
+                    warning("Redefinition of \'{a}\'.", token, id);\n
+                }\n
+                addlabel(id, \'const\');\n
+                if (prefix) {\n
+                    break;\n
+                }\n
+                name = token;\n
+                this.first.push(token);\n
+\n
+                if (nexttoken.id !== "=") {\n
+                    warning("const " +\n
+                      "\'{a}\' is initialized to \'undefined\'.", token, id);\n
+                }\n
+\n
+                if (nexttoken.id === \'=\') {\n
+                    nonadjacent(token, nexttoken);\n
+                    advance(\'=\');\n
+                    nonadjacent(token, nexttoken);\n
+                    if (nexttoken.id === \'undefined\') {\n
+                        warning("It is not necessary to initialize " +\n
+                          "\'{a}\' to \'undefined\'.", token, id);\n
+                    }\n
+                    if (peek(0).id === \'=\' && nexttoken.identifier) {\n
+                        error("Constant {a} was not declared correctly.",\n
+                                nexttoken, nexttoken.value);\n
+                    }\n
+                    value = expression(0);\n
+                    name.first = value;\n
+                }\n
+\n
+                if (nexttoken.id !== \',\') {\n
+                    break;\n
+                }\n
+                comma();\n
+            }\n
+            return this;\n
+        });\n
+        conststatement.exps = true;\n
+    };\n
+\n
+    var varstatement = stmt(\'var\', function (prefix) {\n
+        // JavaScript does not have block scope. It only has function scope. So,\n
+        // declaring a variable in a block can have unexpected consequences.\n
+        var id, name, value;\n
+\n
+        if (funct[\'(onevar)\'] && option.onevar) {\n
+            warning("Too many var statements.");\n
+        } else if (!funct[\'(global)\']) {\n
+            funct[\'(onevar)\'] = true;\n
+        }\n
+        this.first = [];\n
+        for (;;) {\n
+            nonadjacent(token, nexttoken);\n
+            id = identifier();\n
+            if (option.esnext && funct[id] === "const") {\n
+                warning("const \'" + id + "\' has already been declared");\n
+            }\n
+            if (funct[\'(global)\'] && predefined[id] === false) {\n
+                warning("Redefinition of \'{a}\'.", token, id);\n
+            }\n
+            addlabel(id, \'unused\');\n
+            if (prefix) {\n
+                break;\n
+            }\n
+            name = token;\n
+            this.first.push(token);\n
+            if (nexttoken.id === \'=\') {\n
+                nonadjacent(token, nexttoken);\n
+                advance(\'=\');\n
+                nonadjacent(token, nexttoken);\n
+                if (nexttoken.id === \'undefined\') {\n
+                    warning("It is not necessary to initialize \'{a}\' to \'undefined\'.", token, id);\n
+                }\n
+                if (peek(0).id === \'=\' && nexttoken.identifier) {\n
+                    error("Variable {a} was not declared correctly.",\n
+                            nexttoken, nexttoken.value);\n
+                }\n
+                value = expression(0);\n
+                name.first = value;\n
+            }\n
+            if (nexttoken.id !== \',\') {\n
+                break;\n
+            }\n
+            comma();\n
+        }\n
+        return this;\n
+    });\n
+    varstatement.exps = true;\n
+\n
+    blockstmt(\'function\', function () {\n
+        if (inblock) {\n
+            warning("Function declarations should not be placed in blocks. " +\n
+                "Use a function expression or move the statement to the top of " +\n
+                "the outer function.", token);\n
+\n
+        }\n
+        var i = identifier();\n
+        if (option.esnext && funct[i] === "const") {\n
+            warning("const \'" + i + "\' has already been declared");\n
+        }\n
+        adjacent(token, nexttoken);\n
+        addlabel(i, \'unction\');\n
+        doFunction(i, true);\n
+        if (nexttoken.id === \'(\' && nexttoken.line === token.line) {\n
+            error(\n
+"Function declarations are not invocable. Wrap the whole function invocation in parens.");\n
+        }\n
+        return this;\n
+    });\n
+\n
+    prefix(\'function\', function () {\n
+        var i = optionalidentifier();\n
+        if (i) {\n
+            adjacent(token, nexttoken);\n
+        } else {\n
+            nonadjacent(token, nexttoken);\n
+        }\n
+        doFunction(i);\n
+        if (!option.loopfunc && funct[\'(loopage)\']) {\n
+            warning("Don\'t make functions within a loop.");\n
+        }\n
+        return this;\n
+    });\n
+\n
+    blockstmt(\'if\', function () {\n
+        var t = nexttoken;\n
+        advance(\'(\');\n
+        nonadjacent(this, t);\n
+        nospace();\n
+        expression(20);\n
+        if (nexttoken.id === \'=\') {\n
+            if (!option.boss)\n
+                warning("Expected a conditional expression and instead saw an assignment.");\n
+            advance(\'=\');\n
+            expression(20);\n
+        }\n
+        advance(\')\', t);\n
+        nospace(prevtoken, token);\n
+        block(true, true);\n
+        if (nexttoken.id === \'else\') {\n
+            nonadjacent(token, nexttoken);\n
+            advance(\'else\');\n
+            if (nexttoken.id === \'if\' || nexttoken.id === \'switch\') {\n
+                statement(true);\n
+            } else {\n
+                block(true, true);\n
+            }\n
+        }\n
+        return this;\n
+    });\n
+\n
+    blockstmt(\'try\', function () {\n
+        var b, e, s;\n
+\n
+        block(false);\n
+        if (nexttoken.id === \'catch\') {\n
+            advance(\'catch\');\n
+            nonadjacent(token, nexttoken);\n
+            advance(\'(\');\n
+            s = scope;\n
+            scope = Object.create(s);\n
+            e = nexttoken.value;\n
+            if (nexttoken.type !== \'(identifier)\') {\n
+                warning("Expected an identifier and instead saw \'{a}\'.",\n
+                    nexttoken, e);\n
+            } else {\n
+                addlabel(e, \'exception\');\n
+            }\n
+            advance();\n
+            advance(\')\');\n
+            block(false);\n
+            b = true;\n
+            scope = s;\n
+        }\n
+        if (nexttoken.id === \'finally\') {\n
+            advance(\'finally\');\n
+            block(false);\n
+            return;\n
+        } else if (!b) {\n
+            error("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                    nexttoken, \'catch\', nexttoken.value);\n
+        }\n
+        return this;\n
+    });\n
+\n
+    blockstmt(\'while\', function () {\n
+        var t = nexttoken;\n
+        funct[\'(breakage)\'] += 1;\n
+        funct[\'(loopage)\'] += 1;\n
+        advance(\'(\');\n
+        nonadjacent(this, t);\n
+        nospace();\n
+        expression(20);\n
+        if (nexttoken.id === \'=\') {\n
+            if (!option.boss)\n
+                warning("Expected a conditional expression and instead saw an assignment.");\n
+            advance(\'=\');\n
+            expression(20);\n
+        }\n
+        advance(\')\', t);\n
+        nospace(prevtoken, token);\n
+        block(true, true);\n
+        funct[\'(breakage)\'] -= 1;\n
+        funct[\'(loopage)\'] -= 1;\n
+        return this;\n
+    }).labelled = true;\n
+\n
+    blockstmt(\'with\', function () {\n
+        var t = nexttoken;\n
+        if (directive[\'use strict\']) {\n
+            error("\'with\' is not allowed in strict mode.", token);\n
+        } else if (!option.withstmt) {\n
+            warning("Don\'t use \'with\'.", token);\n
+        }\n
+\n
+        advance(\'(\');\n
+        nonadjacent(this, t);\n
+        nospace();\n
+        expression(0);\n
+        advance(\')\', t);\n
+        nospace(prevtoken, token);\n
+        block(true, true);\n
+\n
+        return this;\n
+    });\n
+\n
+    blockstmt(\'switch\', function () {\n
+        var t = nexttoken,\n
+            g = false;\n
+        funct[\'(breakage)\'] += 1;\n
+        advance(\'(\');\n
+        nonadjacent(this, t);\n
+        nospace();\n
+        this.condition = expression(20);\n
+        advance(\')\', t);\n
+        nospace(prevtoken, token);\n
+        nonadjacent(token, nexttoken);\n
+        t = nexttoken;\n
+        advance(\'{\');\n
+        nonadjacent(token, nexttoken);\n
+        indent += option.indent;\n
+        this.cases = [];\n
+        for (;;) {\n
+            switch (nexttoken.id) {\n
+            case \'case\':\n
+                switch (funct[\'(verb)\']) {\n
+                case \'break\':\n
+                case \'case\':\n
+                case \'continue\':\n
+                case \'return\':\n
+                case \'switch\':\n
+                case \'throw\':\n
+                    break;\n
+                default:\n
+                    // You can tell JSHint that you don\'t use break intentionally by\n
+                    // adding a comment /* falls through */ on a line just before\n
+                    // the next `case`.\n
+                    if (!ft.test(lines[nexttoken.line - 2])) {\n
+                        warning(\n
+                            "Expected a \'break\' statement before \'case\'.",\n
+                            token);\n
+                    }\n
+                }\n
+                indentation(-option.indent);\n
+                advance(\'case\');\n
+                this.cases.push(expression(20));\n
+                g = true;\n
+                advance(\':\');\n
+                funct[\'(verb)\'] = \'case\';\n
+                break;\n
+            case \'default\':\n
+                switch (funct[\'(verb)\']) {\n
+                case \'break\':\n
+                case \'continue\':\n
+                case \'return\':\n
+                case \'throw\':\n
+                    break;\n
+                default:\n
+                    if (!ft.test(lines[nexttoken.line - 2])) {\n
+                        warning(\n
+                            "Expected a \'break\' statement before \'default\'.",\n
+                            token);\n
+                    }\n
+                }\n
+                indentation(-option.indent);\n
+                advance(\'default\');\n
+                g = true;\n
+                advance(\':\');\n
+                break;\n
+            case \'}\':\n
+                indent -= option.indent;\n
+                indentation();\n
+                advance(\'}\', t);\n
+                if (this.cases.length === 1 || this.condition.id === \'true\' ||\n
+                        this.condition.id === \'false\') {\n
+                    if (!option.onecase)\n
+                        warning("This \'switch\' should be an \'if\'.", this);\n
+                }\n
+                funct[\'(breakage)\'] -= 1;\n
+                funct[\'(verb)\'] = undefined;\n
+                return;\n
+            case \'(end)\':\n
+                error("Missing \'{a}\'.", nexttoken, \'}\');\n
+                return;\n
+            default:\n
+                if (g) {\n
+                    switch (token.id) {\n
+                    case \',\':\n
+                        error("Each value should have its own case label.");\n
+                        return;\n
+                    case \':\':\n
+                        g = false;\n
+                        statements();\n
+                        break;\n
+                    default:\n
+                        error("Missing \':\' on a case clause.", token);\n
+                        return;\n
+                    }\n
+                } else {\n
+                    if (token.id === \':\') {\n
+                        advance(\':\');\n
+                        error("Unexpected \'{a}\'.", token, \':\');\n
+                        statements();\n
+                    } else {\n
+                        error("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                            nexttoken, \'case\', nexttoken.value);\n
+                        return;\n
+                    }\n
+                }\n
+            }\n
+        }\n
+    }).labelled = true;\n
+\n
+    stmt(\'debugger\', function () {\n
+        if (!option.debug) {\n
+            warning("All \'debugger\' statements should be removed.");\n
+        }\n
+        return this;\n
+    }).exps = true;\n
+\n
+    (function () {\n
+        var x = stmt(\'do\', function () {\n
+            funct[\'(breakage)\'] += 1;\n
+            funct[\'(loopage)\'] += 1;\n
+            this.first = block(true);\n
+            advance(\'while\');\n
+            var t = nexttoken;\n
+            nonadjacent(token, t);\n
+            advance(\'(\');\n
+            nospace();\n
+            expression(20);\n
+            if (nexttoken.id === \'=\') {\n
+                if (!option.boss)\n
+                    warning("Expected a conditional expression and instead saw an assignment.");\n
+                advance(\'=\');\n
+                expression(20);\n
+            }\n
+            advance(\')\', t);\n
+            nospace(prevtoken, token);\n
+            funct[\'(breakage)\'] -= 1;\n
+            funct[\'(loopage)\'] -= 1;\n
+            return this;\n
+        });\n
+        x.labelled = true;\n
+        x.exps = true;\n
+    }());\n
+\n
+    blockstmt(\'for\', function () {\n
+        var s, t = nexttoken;\n
+        funct[\'(breakage)\'] += 1;\n
+        funct[\'(loopage)\'] += 1;\n
+        advance(\'(\');\n
+        nonadjacent(this, t);\n
+        nospace();\n
+        if (peek(nexttoken.id === \'var\' ? 1 : 0).id === \'in\') {\n
+            if (nexttoken.id === \'var\') {\n
+                advance(\'var\');\n
+                varstatement.fud.call(varstatement, true);\n
+            } else {\n
+                switch (funct[nexttoken.value]) {\n
+                case \'unused\':\n
+                    funct[nexttoken.value] = \'var\';\n
+                    break;\n
+                case \'var\':\n
+                    break;\n
+                default:\n
+                    warning("Bad for in variable \'{a}\'.",\n
+                            nexttoken, nexttoken.value);\n
+                }\n
+                advance();\n
+            }\n
+            advance(\'in\');\n
+            expression(20);\n
+            advance(\')\', t);\n
+            s = block(true, true);\n
+            if (option.forin && s && (s.length > 1 || typeof s[0] !== \'object\' ||\n
+                    s[0].value !== \'if\')) {\n
+                warning("The body of a for in should be wrapped in an if statement to filter " +\n
+                        "unwanted properties from the prototype.", this);\n
+            }\n
+            funct[\'(breakage)\'] -= 1;\n
+            funct[\'(loopage)\'] -= 1;\n
+            return this;\n
+        } else {\n
+            if (nexttoken.id !== \';\') {\n
+                if (nexttoken.id === \'var\') {\n
+                    advance(\'var\');\n
+                    varstatement.fud.call(varstatement);\n
+                } else {\n
+                    for (;;) {\n
+                        expression(0, \'for\');\n
+                        if (nexttoken.id !== \',\') {\n
+                            break;\n
+                        }\n
+                        comma();\n
+                    }\n
+                }\n
+            }\n
+            nolinebreak(token);\n
+            advance(\';\');\n
+            if (nexttoken.id !== \';\') {\n
+                expression(20);\n
+                if (nexttoken.id === \'=\') {\n
+                    if (!option.boss)\n
+                        warning("Expected a conditional expression and instead saw an assignment.");\n
+                    advance(\'=\');\n
+                    expression(20);\n
+                }\n
+            }\n
+            nolinebreak(token);\n
+            advance(\';\');\n
+            if (nexttoken.id === \';\') {\n
+                error("Expected \'{a}\' and instead saw \'{b}\'.",\n
+                        nexttoken, \')\', \';\');\n
+            }\n
+            if (nexttoken.id !== \')\') {\n
+                for (;;) {\n
+                    expression(0, \'for\');\n
+                    if (nexttoken.id !== \',\') {\n
+                        break;\n
+                    }\n
+                    comma();\n
+                }\n
+            }\n
+            advance(\')\', t);\n
+            nospace(prevtoken, token);\n
+            block(true, true);\n
+            funct[\'(breakage)\'] -= 1;\n
+            funct[\'(loopage)\'] -= 1;\n
+            return this;\n
+        }\n
+    }).labelled = true;\n
+\n
+\n
+    stmt(\'break\', function () {\n
+        var v = nexttoken.value;\n
+\n
+        if (funct[\'(breakage)\'] === 0)\n
+            warning("Unexpected \'{a}\'.", nexttoken, this.value);\n
+\n
+        if (!option.asi)\n
+            nolinebreak(this);\n
+\n
+        if (nexttoken.id !== \';\') {\n
+            if (token.line === nexttoken.line) {\n
+                if (funct[v] !== \'label\') {\n
+                    warning("\'{a}\' is not a statement label.", nexttoken, v);\n
+                } else if (scope[v] !== funct) {\n
+                    warning("\'{a}\' is out of scope.", nexttoken, v);\n
+                }\n
+                this.first = nexttoken;\n
+                advance();\n
+            }\n
+        }\n
+        reachable(\'break\');\n
+        return this;\n
+    }).exps = true;\n
+\n
+\n
+    stmt(\'continue\', function () {\n
+        var v = nexttoken.value;\n
+\n
+        if (funct[\'(breakage)\'] === 0)\n
+            warning("Unexpected \'{a}\'.", nexttoken, this.value);\n
+\n
+        if (!option.asi)\n
+            nolinebreak(this);\n
+\n
+        if (nexttoken.id !== \';\') {\n
+            if (token.line === nexttoken.line) {\n
+                if (funct[v] !== \'label\') {\n
+                    warning("\'{a}\' is not a statement label.", nexttoken, v);\n
+                } else if (scope[v] !== funct) {\n
+                    warning("\'{a}\' is out of scope.", nexttoken, v);\n
+                }\n
+                this.first = nexttoken;\n
+                advance();\n
+            }\n
+        } else if (!funct[\'(loopage)\']) {\n
+            warning("Unexpected \'{a}\'.", nexttoken, this.value);\n
+        }\n
+        reachable(\'continue\');\n
+        return this;\n
+    }).exps = true;\n
+\n
+\n
+    stmt(\'return\', function () {\n
+        if (this.line === nexttoken.line) {\n
+            if (nexttoken.id === \'(regexp)\')\n
+                warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");\n
+\n
+            if (nexttoken.id !== \';\' && !nexttoken.reach) {\n
+                nonadjacent(token, nexttoken);\n
+                if (peek().value === "=" && !option.boss) {\n
+                    warningAt("Did you mean to return a conditional instead of an assignment?",\n
+                              token.line, token.character + 1);\n
+                }\n
+                this.first = expression(0);\n
+            }\n
+        } else if (!option.asi) {\n
+            nolinebreak(this); // always warn (Line breaking error)\n
+        }\n
+        reachable(\'return\');\n
+        return this;\n
+    }).exps = true;\n
+\n
+\n
+    stmt(\'throw\', function () {\n
+        nolinebreak(this);\n
+        nonadjacent(token, nexttoken);\n
+        this.first = expression(20);\n
+        reachable(\'throw\');\n
+        return this;\n
+    }).exps = true;\n
+\n
+//  Superfluous reserved words\n
+\n
+    reserve(\'class\');\n
+    reserve(\'const\');\n
+    reserve(\'enum\');\n
+    reserve(\'export\');\n
+    reserve(\'extends\');\n
+    reserve(\'import\');\n
+    reserve(\'super\');\n
+\n
+    reserve(\'let\');\n
+    reserve(\'yield\');\n
+    reserve(\'implements\');\n
+    reserve(\'interface\');\n
+    reserve(\'package\');\n
+    reserve(\'private\');\n
+    reserve(\'protected\');\n
+    reserve(\'public\');\n
+    reserve(\'static\');\n
+\n
+\n
+// Parse JSON\n
+\n
+    function jsonValue() {\n
+\n
+        function jsonObject() {\n
+            var o = {}, t = nexttoken;\n
+            advance(\'{\');\n
+            if (nexttoken.id !== \'}\') {\n
+                for (;;) {\n
+                    if (nexttoken.id === \'(end)\') {\n
+                        error("Missing \'}\' to match \'{\' from line {a}.",\n
+                                nexttoken, t.line);\n
+                    } else if (nexttoken.id === \'}\') {\n
+                        warning("Unexpected comma.", token);\n
+                        break;\n
+                    } else if (nexttoken.id === \',\') {\n
+                        error("Unexpected comma.", nexttoken);\n
+                    } else if (nexttoken.id !== \'(string)\') {\n
+                        warning("Expected a string and instead saw {a}.",\n
+                                nexttoken, nexttoken.value);\n
+                    }\n
+                    if (o[nexttoken.value] === true) {\n
+                        warning("Duplicate key \'{a}\'.",\n
+                                nexttoken, nexttoken.value);\n
+                    } else if ((nexttoken.value === \'__proto__\' &&\n
+                        !option.proto) || (nexttoken.value === \'__iterator__\' &&\n
+                        !option.iterator)) {\n
+                        warning("The \'{a}\' key may produce unexpected results.",\n
+                            nexttoken, nexttoken.value);\n
+                    } else {\n
+                        o[nexttoken.value] = true;\n
+                    }\n
+                    advance();\n
+                    advance(\':\');\n
+                    jsonValue();\n
+                    if (nexttoken.id !== \',\') {\n
+                        break;\n
+                    }\n
+                    advance(\',\');\n
+                }\n
+            }\n
+            advance(\'}\');\n
+        }\n
+\n
+        function jsonArray() {\n
+            var t = nexttoken;\n
+            advance(\'[\');\n
+            if (nexttoken.id !== \']\') {\n
+                for (;;) {\n
+                    if (nexttoken.id === \'(end)\') {\n
+                        error("Missing \']\' to match \'[\' from line {a}.",\n
+                                nexttoken, t.line);\n
+                    } else if (nexttoken.id === \']\') {\n
+                        warning("Unexpected comma.", token);\n
+                        break;\n
+                    } else if (nexttoken.id === \',\') {\n
+                        error("Unexpected comma.", nexttoken);\n
+                    }\n
+                    jsonValue();\n
+                    if (nexttoken.id !== \',\') {\n
+                        break;\n
+                    }\n
+                    advance(\',\');\n
+                }\n
+            }\n
+            advance(\']\');\n
+        }\n
+\n
+        switch (nexttoken.id) {\n
+        case \'{\':\n
+            jsonObject();\n
+            break;\n
+        case \'[\':\n
+            jsonArray();\n
+            break;\n
+        case \'true\':\n
+        case \'false\':\n
+        case \'null\':\n
+        case \'(number)\':\n
+        case \'(string)\':\n
+            advance();\n
+            break;\n
+        case \'-\':\n
+            advance(\'-\');\n
+            if (token.character !== nexttoken.from) {\n
+                warning("Unexpected space after \'-\'.", token);\n
+            }\n
+            adjacent(token, nexttoken);\n
+            advance(\'(number)\');\n
+            break;\n
+        default:\n
+            error("Expected a JSON value.", nexttoken);\n
+        }\n
+    }\n
+\n
+\n
+// The actual JSHINT function itself.\n
+\n
+    var itself = function (s, o, g) {\n
+        var a, i, k, x,\n
+            optionKeys,\n
+            newOptionObj = {};\n
+\n
+        JSHINT.errors = [];\n
+        JSHINT.undefs = [];\n
+        predefined = Object.create(standard);\n
+        combine(predefined, g || {});\n
+        if (o) {\n
+            a = o.predef;\n
+            if (a) {\n
+                if (Array.isArray(a)) {\n
+                    for (i = 0; i < a.length; i += 1) {\n
+                        predefined[a[i]] = true;\n
+                    }\n
+                } else if (typeof a === \'object\') {\n
+                    k = Object.keys(a);\n
+                    for (i = 0; i < k.length; i += 1) {\n
+                        predefined[k[i]] = !!a[k[i]];\n
+                    }\n
+                }\n
+            }\n
+            optionKeys = Object.keys(o);\n
+            for (x = 0; x < optionKeys.length; x++) {\n
+                newOptionObj[optionKeys[x]] = o[optionKeys[x]];\n
+            }\n
+        }\n
+\n
+        option = newOptionObj;\n
+\n
+        option.indent = option.indent || 4;\n
+        option.maxerr = option.maxerr || 50;\n
+\n
+        tab = \'\';\n
+        for (i = 0; i < option.indent; i += 1) {\n
+            tab += \' \';\n
+        }\n
+        indent = 1;\n
+        global = Object.create(predefined);\n
+        scope = global;\n
+        funct = {\n
+            \'(global)\': true,\n
+            \'(name)\': \'(global)\',\n
+            \'(scope)\': scope,\n
+            \'(breakage)\': 0,\n
+            \'(loopage)\': 0\n
+        };\n
+        functions = [funct];\n
+        urls = [];\n
+        stack = null;\n
+        member = {};\n
+        membersOnly = null;\n
+        implied = {};\n
+        inblock = false;\n
+        lookahead = [];\n
+        jsonmode = false;\n
+        warnings = 0;\n
+        lex.init(s);\n
+        prereg = true;\n
+        directive = {};\n
+\n
+        prevtoken = token = nexttoken = syntax[\'(begin)\'];\n
+\n
+        // Check options\n
+        for (var name in o) {\n
+            if (is_own(o, name)) {\n
+                checkOption(name, token);\n
+            }\n
+        }\n
+\n
+        assume();\n
+\n
+        // combine the passed globals after we\'ve assumed all our options\n
+        combine(predefined, g || {});\n
+\n
+        //reset values\n
+        comma.first = true;\n
+\n
+        try {\n
+            advance();\n
+            switch (nexttoken.id) {\n
+            case \'{\':\n
+            case \'[\':\n
+                option.laxbreak = true;\n
+                jsonmode = true;\n
+                jsonValue();\n
+                break;\n
+            default:\n
+                directives();\n
+                if (directive["use strict"] && !option.globalstrict) {\n
+                    warning("Use the function form of \\"use strict\\".", prevtoken);\n
+                }\n
+\n
+                statements();\n
+            }\n
+            advance(\'(end)\');\n
+\n
+            var markDefined = function (name, context) {\n
+                do {\n
+                    if (typeof context[name] === \'string\') {\n
+                        // JSHINT marks unused variables as \'unused\' and\n
+                        // unused function declaration as \'unction\'. This\n
+                        // code changes such instances back \'var\' and\n
+                        // \'closure\' so that the code in JSHINT.data()\n
+                        // doesn\'t think they\'re unused.\n
+\n
+                        if (context[name] === \'unused\')\n
+                            context[name] = \'var\';\n
+                        else if (context[name] === \'unction\')\n
+                            context[name] = \'closure\';\n
+\n
+                        return true;\n
+                    }\n
+\n
+                    context = context[\'(context)\'];\n
+                } while (context);\n
+\n
+                return false;\n
+            };\n
+\n
+            var clearImplied = function (name, line) {\n
+                if (!implied[name])\n
+                    return;\n
+\n
+                var newImplied = [];\n
+                for (var i = 0; i < implied[name].length; i += 1) {\n
+                    if (implied[name][i] !== line)\n
+                        newImplied.push(implied[name][i]);\n
+                }\n
+\n
+                if (newImplied.length === 0)\n
+                    delete implied[name];\n
+                else\n
+                    implied[name] = newImplied;\n
+            };\n
+\n
+            // Check queued \'x is not defined\' instances to see if they\'re still undefined.\n
+            for (i = 0; i < JSHINT.undefs.length; i += 1) {\n
+                k = JSHINT.undefs[i].slice(0);\n
+\n
+                if (markDefined(k[2].value, k[0])) {\n
+                    clearImplied(k[2].value, k[2].line);\n
+                } else {\n
+                    warning.apply(warning, k.slice(1));\n
+                }\n
+            }\n
+        } catch (e) {\n
+            if (e) {\n
+                var nt = nexttoken || {};\n
+                JSHINT.errors.push({\n
+                    raw       : e.raw,\n
+                    reason    : e.message,\n
+                    line      : e.line || nt.line,\n
+                    character : e.character || nt.from\n
+                }, null);\n
+            }\n
+        }\n
+\n
+        return JSHINT.errors.length === 0;\n
+    };\n
+\n
+    // Data summary.\n
+    itself.data = function () {\n
+\n
+        var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,\n
+            members = [], n, unused = [], v;\n
+        if (itself.errors.length) {\n
+            data.errors = itself.errors;\n
+        }\n
+\n
+        if (jsonmode) {\n
+            data.json = true;\n
+        }\n
+\n
+        for (n in implied) {\n
+            if (is_own(implied, n)) {\n
+                implieds.push({\n
+                    name: n,\n
+                    line: implied[n]\n
+                });\n
+            }\n
+        }\n
+        if (implieds.length > 0) {\n
+            data.implieds = implieds;\n
+        }\n
+\n
+        if (urls.length > 0) {\n
+            data.urls = urls;\n
+        }\n
+\n
+        globals = Object.keys(scope);\n
+        if (globals.length > 0) {\n
+            data.globals = globals;\n
+        }\n
+        for (i = 1; i < functions.length; i += 1) {\n
+            f = functions[i];\n
+            fu = {};\n
+            for (j = 0; j < functionicity.length; j += 1) {\n
+                fu[functionicity[j]] = [];\n
+            }\n
+            for (n in f) {\n
+                if (is_own(f, n) && n.charAt(0) !== \'(\') {\n
+                    v = f[n];\n
+                    if (v === \'unction\') {\n
+                        v = \'unused\';\n
+                    }\n
+                    if (Array.isArray(fu[v])) {\n
+                        fu[v].push(n);\n
+                        if (v === \'unused\') {\n
+                            unused.push({\n
+                                name: n,\n
+                                line: f[\'(line)\'],\n
+                                \'function\': f[\'(name)\']\n
+                            });\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+            for (j = 0; j < functionicity.length; j += 1) {\n
+                if (fu[functionicity[j]].length === 0) {\n
+                    delete fu[functionicity[j]];\n
+                }\n
+            }\n
+            fu.name = f[\'(name)\'];\n
+            fu.param = f[\'(params)\'];\n
+            fu.line = f[\'(line)\'];\n
+            fu.last = f[\'(last)\'];\n
+            data.functions.push(fu);\n
+        }\n
+\n
+        if (unused.length > 0) {\n
+            data.unused = unused;\n
+        }\n
+\n
+        members = [];\n
+        for (n in member) {\n
+            if (typeof member[n] === \'number\') {\n
+                data.member = member;\n
+                break;\n
+            }\n
+        }\n
+\n
+        return data;\n
+    };\n
+\n
+    itself.report = function (option) {\n
+        var data = itself.data();\n
+\n
+        var a = [], c, e, err, f, i, k, l, m = \'\', n, o = [], s;\n
+\n
+        function detail(h, array) {\n
+            var b, i, singularity;\n
+            if (array) {\n
+                o.push(\'<div><i>\' + h + \'</i> \');\n
+                array = array.sort();\n
+                for (i = 0; i < array.length; i += 1) {\n
+                    if (array[i] !== singularity) {\n
+                        singularity = array[i];\n
+                        o.push((b ? \', \' : \'\') + singularity);\n
+                        b = true;\n
+                    }\n
+                }\n
+                o.push(\'</div>\');\n
+            }\n
+        }\n
+\n
+\n
+        if (data.errors || data.implieds || data.unused) {\n
+            err = true;\n
+            o.push(\'<div id=errors><i>Error:</i>\');\n
+            if (data.errors) {\n
+                for (i = 0; i < data.errors.length; i += 1) {\n
+                    c = data.errors[i];\n
+                    if (c) {\n
+                        e = c.evidence || \'\';\n
+                        o.push(\'<p>Problem\' + (isFinite(c.line) ? \' at line \' +\n
+                                c.line + \' character \' + c.character : \'\') +\n
+                                \': \' + c.reason.entityify() +\n
+                                \'</p><p class=evidence>\' +\n
+                                (e && (e.length > 80 ? e.slice(0, 77) + \'...\' :\n
+                                e).entityify()) + \'</p>\');\n
+                    }\n
+                }\n
+            }\n
+\n
+            if (data.implieds) {\n
+                s = [];\n
+                for (i = 0; i < data.implieds.length; i += 1) {\n
+                    s[i] = \'<code>\' + data.implieds[i].name + \'</code>&nbsp;<i>\' +\n
+                        data.implieds[i].line + \'</i>\';\n
+                }\n
+                o.push(\'<p><i>Implied global:</i> \' + s.join(\', \') + \'</p>\');\n
+            }\n
+\n
+            if (data.unused) {\n
+                s = [];\n
+                for (i = 0; i < data.unused.length; i += 1) {\n
+                    s[i] = \'<code><u>\' + data.unused[i].name + \'</u></code>&nbsp;<i>\' +\n
+                        data.unused[i].line + \'</i> <code>\' +\n
+                        data.unused[i][\'function\'] + \'</code>\';\n
+                }\n
+                o.push(\'<p><i>Unused variable:</i> \' + s.join(\', \') + \'</p>\');\n
+            }\n
+            if (data.json) {\n
+                o.push(\'<p>JSON: bad.</p>\');\n
+            }\n
+            o.push(\'</div>\');\n
+        }\n
+\n
+        if (!option) {\n
+\n
+            o.push(\'<br><div id=functions>\');\n
+\n
+            if (data.urls) {\n
+                detail("URLs<br>", data.urls, \'<br>\');\n
+            }\n
+\n
+            if (data.json && !err) {\n
+                o.push(\'<p>JSON: good.</p>\');\n
+            } else if (data.globals) {\n
+                o.push(\'<div><i>Global</i> \' +\n
+                        data.globals.sort().join(\', \') + \'</div>\');\n
+            } else {\n
+                o.push(\'<div><i>No new global variables introduced.</i></div>\');\n
+            }\n
+\n
+            for (i = 0; i < data.functions.length; i += 1) {\n
+                f = data.functions[i];\n
+\n
+                o.push(\'<br><div class=function><i>\' + f.line + \'-\' +\n
+                        f.last + \'</i> \' + (f.name || \'\') + \'(\' +\n
+                        (f.param ? f.param.join(\', \') : \'\') + \')</div>\');\n
+                detail(\'<big><b>Unused</b></big>\', f.unused);\n
+                detail(\'Closure\', f.closure);\n
+                detail(\'Variable\', f[\'var\']);\n
+                detail(\'Exception\', f.exception);\n
+                detail(\'Outer\', f.outer);\n
+                detail(\'Global\', f.global);\n
+                detail(\'Label\', f.label);\n
+            }\n
+\n
+            if (data.member) {\n
+                a = Object.keys(data.member);\n
+                if (a.length) {\n
+                    a = a.sort();\n
+                    m = \'<br><pre id=members>/*members \';\n
+                    l = 10;\n
+                    for (i = 0; i < a.length; i += 1) {\n
+                        k = a[i];\n
+                        n = k.name();\n
+                        if (l + n.length > 72) {\n
+                            o.push(m + \'<br>\');\n
+                            m = \'    \';\n
+                            l = 1;\n
+                        }\n
+                        l += n.length + 2;\n
+                        if (data.member[k] === 1) {\n
+                            n = \'<i>\' + n + \'</i>\';\n
+                        }\n
+                        if (i < a.length - 1) {\n
+                            n += \', \';\n
+                        }\n
+                        m += n;\n
+                    }\n
+                    o.push(m + \'<br>*/</pre>\');\n
+                }\n
+                o.push(\'</div>\');\n
+            }\n
+        }\n
+        return o.join(\'\');\n
+    };\n
+\n
+    itself.jshint = itself;\n
+\n
+    return itself;\n
+}());\n
+\n
+// Make JSHINT a Node module, if possible.\n
+if (typeof exports === \'object\' && exports)\n
+    exports.JSHINT = JSHINT;\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/bt/change_log b/bt5/erp5_code_mirror/bt/change_log
index 85ec308f17d249e31daaa295bb379af2626fd263..b3f395cd74884fc85f16601feeec24daa30cbed7 100644
--- a/bt5/erp5_code_mirror/bt/change_log
+++ b/bt5/erp5_code_mirror/bt/change_log
@@ -1,3 +1,6 @@
+2015-04-23 arnaud.fontaine
+* Add support for the ZMI.
+
 2015-01-22 arnaud.fontaine
 * Gutter and source code separator line was not displayed because of erp5.css (df7eb0f).
 
diff --git a/bt5/erp5_code_mirror/bt/comment b/bt5/erp5_code_mirror/bt/comment
index 766ff76161cace6e6817450bac45669a33645f39..1209268a3e1e23b9526c493e9dc58d40f6191388 100644
--- a/bt5/erp5_code_mirror/bt/comment
+++ b/bt5/erp5_code_mirror/bt/comment
@@ -2,4 +2,10 @@ CodeMirror is available at:
 http://codemirror.net
 
 diff_match_patch (used by CodeMirror Merge addon):
-https://code.google.com/p/google-diff-match-patch
\ No newline at end of file
+https://code.google.com/p/google-diff-match-patch
+
+jshint.js (used by CodeMirror Javascript lint addon):
+http://ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js
+
+csslint.js (used by CodeMirror CSS lint addon):
+https://rawgit.com/stubbornella/csslint/master/release/csslint.js
diff --git a/bt5/erp5_code_mirror/bt/copyright_list b/bt5/erp5_code_mirror/bt/copyright_list
index 51cd3130bd0da6e346997b136ca058396374fa55..5a5c175cc06ca586b7307333012a081f6a2ff0fd 100644
--- a/bt5/erp5_code_mirror/bt/copyright_list
+++ b/bt5/erp5_code_mirror/bt/copyright_list
@@ -5,4 +5,10 @@ CodeMirror (under MIT license):
 Copyright (c) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
 
 diff_match_patch (under Apache 2.0 license)
-Copyright (c) 2006 Google Inc.
\ No newline at end of file
+Copyright (c) 2006 Google Inc.
+
+jshint.js (under modified MIT license):
+Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
+
+csslint.js (under MIT license):
+Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.
diff --git a/product/ERP5Form/EditorField.py b/product/ERP5Form/EditorField.py
index 8a90688b7678f430c2698c3c5b9ac50ddc4e2e76..43781da83a66c26cd33113e7d3e53a5cbaa82b58 100644
--- a/product/ERP5Form/EditorField.py
+++ b/product/ERP5Form/EditorField.py
@@ -126,7 +126,8 @@ class EditorWidget(Widget.TextAreaWidget):
         return code_mirror_support(field=field,
                                    content=value,
                                    field_id=key,
-                                   portal_url=site_root.absolute_url())
+                                   portal_url=site_root.absolute_url(),
+                                   mode='python')
     elif text_editor != 'text_area':
       return here.fckeditor_wysiwyg_support.pt_render(
            extra_context= {
diff --git a/product/ERP5Type/patches/AceEditorZMI.py b/product/ERP5Type/patches/AceEditorZMI.py
index 8f7ee09406057732143c88c6ee55ae9b7f021048..ac19619c1c16d719acb92b4fa93b347dc7668326 100644
--- a/product/ERP5Type/patches/AceEditorZMI.py
+++ b/product/ERP5Type/patches/AceEditorZMI.py
@@ -19,7 +19,7 @@ def manage_page_footer(self):
   except:
     editor = None
 
-  if editor != 'ace':
+  if editor not in ('ace', 'codemirror'):
     return default
 
   # REQUEST['PUBLISHED'] can be the form in the acquisition context of the
@@ -67,14 +67,28 @@ def manage_page_footer(self):
     textarea_selector = 'textarea[name="template:text"]'
   elif document.meta_type in ('Page Template', 'ERP5 OOo Template', ):
     if 'html' in document.content_type:
-      mode = 'html'
+      if editor == 'codemirror':
+        mode = 'htmlmixed'
+      else:
+        mode = 'html'
     else:
       mode = 'xml'
     textarea_selector = 'textarea[name="text:text"]'
 
   if not textarea_selector:
     return default
-  return '''
+
+  if editor == 'codemirror' and getattr(portal, 'code_mirror_support', None) is not None:
+    return '''<script type="text/javascript" src="%s/jquery/core/jquery.min.js"></script>
+              %s
+              </body>
+            </html>''' % (portal_url,
+                          portal.code_mirror_support(textarea_selector=textarea_selector,
+                                                     portal_url=portal_url,
+                                                     bound_names=bound_names,
+                                                     mode=mode))
+  else:
+    return '''
 <script type="text/javascript" src="%(portal_url)s/jquery/core/jquery.min.js"></script>
 <script type="text/javascript" src="%(portal_url)s/ace/ace.js"></script>
 <script type="text/javascript" src="%(portal_url)s/ace/mode-%(mode)s.js"></script>