<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[42110] trunk/src/wp-includes/js/codemirror/csslint.js: Codemirror: Unify line endings in csslint.js</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/42110">42110</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/42110","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>obenland</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-11-02 22:30:16 +0000 (Thu, 02 Nov 2017)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Codemirror: Unify line endings in csslint.js

This is likely a problem caused upstream and will probably be a non-issue once <a href="https://core.trac.wordpress.org/ticket/41870">#41870</a> is merged in a future release.

Fixes <a href="https://core.trac.wordpress.org/ticket/42424">#42424</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjscodemirrorcsslintjs">trunk/src/wp-includes/js/codemirror/csslint.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesjscodemirrorcsslintjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/codemirror/csslint.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/csslint.js    2017-11-02 19:59:55 UTC (rev 42109)
+++ trunk/src/wp-includes/js/codemirror/csslint.js      2017-11-02 22:30:16 UTC (rev 42110)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,32 +1,32 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/*!
-CSSLint v1.0.4
-Copyright (c) 2016 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the 'Software'), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-*/
-
-var CSSLint = (function(){
-  var module = module || {},
-      exports = exports || {};
-
-/*!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*!
+CSSLint v1.0.4
+Copyright (c) 2016 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the 'Software'), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*/
+
+var CSSLint = (function(){
+  var module = module || {},
+      exports = exports || {};
+
+/*!
</ins><span class="cx" style="display: block; padding: 0 10px"> Parser-Lib
</span><span class="cx" style="display: block; padding: 0 10px"> Copyright (c) 2009-2016 Nicholas C. Zakas. All rights reserved.
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46,12 +46,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
</span><span class="cx" style="display: block; padding: 0 10px"> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
</span><span class="cx" style="display: block; padding: 0 10px"> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-THE SOFTWARE.
-*/
-/* Version v1.1.0, Build time: 6-December-2016 10:31:29 */
-var parserlib = (function () {
-var require;
-require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+THE SOFTWARE.
+*/
+/* Version v1.1.0, Build time: 6-December-2016 10:31:29 */
+var parserlib = (function () {
+var require;
+require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /* exported Colors */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -238,8 +238,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     windowframe         :"Window frame.",
</span><span class="cx" style="display: block; padding: 0 10px">     windowtext          :"Text in windows."
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],2:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],2:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = Combinator;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -285,8 +285,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> Combinator.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> Combinator.prototype.constructor = Combinator;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],3:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],3:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = Matcher;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -642,8 +642,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         });
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/StringReader":24,"../util/SyntaxError":25,"./ValidationTypes":21}],4:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/StringReader":24,"../util/SyntaxError":25,"./ValidationTypes":21}],4:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = MediaFeature;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -683,8 +683,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> MediaFeature.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> MediaFeature.prototype.constructor = MediaFeature;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],5:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],5:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = MediaQuery;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -735,8 +735,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> MediaQuery.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> MediaQuery.prototype.constructor = MediaQuery;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],6:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],6:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = Parser;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3289,8 +3289,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">          ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*
</span><span class="cx" style="display: block; padding: 0 10px">   ;
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/EventTarget":23,"../util/SyntaxError":25,"../util/SyntaxUnit":26,"./Combinator":2,"./MediaFeature":4,"./MediaQuery":5,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./TokenStream":17,"./Tokens":18,"./Validation":19}],7:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/EventTarget":23,"../util/SyntaxError":25,"../util/SyntaxUnit":26,"./Combinator":2,"./MediaFeature":4,"./MediaQuery":5,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./TokenStream":17,"./Tokens":18,"./Validation":19}],7:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /* exported Properties */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3783,8 +3783,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     "z-index"                       : "<integer> | auto",
</span><span class="cx" style="display: block; padding: 0 10px">     "zoom"                          : "<number> | <percentage> | normal"
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],8:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],8:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = PropertyName;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3822,8 +3822,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> PropertyName.prototype.toString = function() {
</span><span class="cx" style="display: block; padding: 0 10px">     return (this.hack ? this.hack : "") + this.text;
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],9:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],9:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = PropertyValue;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3860,8 +3860,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> PropertyValue.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> PropertyValue.prototype.constructor = PropertyValue;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],10:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],10:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = PropertyValueIterator;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3998,8 +3998,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> PropertyValueIterator.prototype.drop = function() {
</span><span class="cx" style="display: block; padding: 0 10px">     this._marks.pop();
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],11:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],11:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = PropertyValuePart;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4247,8 +4247,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     });
</span><span class="cx" style="display: block; padding: 0 10px">     return part;
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Colors":1,"./Parser":6,"./Tokens":18}],12:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Colors":1,"./Parser":6,"./Tokens":18}],12:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> var Pseudos = module.exports = {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4265,8 +4265,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> Pseudos.isElement = function(pseudo) {
</span><span class="cx" style="display: block; padding: 0 10px">     return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] === Pseudos.ELEMENT;
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],13:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],13:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = Selector;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4310,8 +4310,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> Selector.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> Selector.prototype.constructor = Selector;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6,"./Specificity":16}],14:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6,"./Specificity":16}],14:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = SelectorPart;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4361,8 +4361,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> SelectorPart.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> SelectorPart.prototype.constructor = SelectorPart;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],15:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],15:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = SelectorSubPart;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4406,8 +4406,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> SelectorSubPart.prototype = new SyntaxUnit();
</span><span class="cx" style="display: block; padding: 0 10px"> SelectorSubPart.prototype.constructor = SelectorSubPart;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/SyntaxUnit":26,"./Parser":6}],16:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/SyntaxUnit":26,"./Parser":6}],16:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = Specificity;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4537,8 +4537,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     return new Specificity(0, b, c, d);
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./Pseudos":12,"./SelectorPart":14}],17:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./Pseudos":12,"./SelectorPart":14}],17:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = TokenStream;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5586,8 +5586,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> });
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"../util/TokenStreamBase":27,"./PropertyValuePart":11,"./Tokens":18}],18:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"../util/TokenStreamBase":27,"./PropertyValuePart":11,"./Tokens":18}],18:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> var Tokens = module.exports = [
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5797,8 +5797,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         return typeMap[c] || -1;
</span><span class="cx" style="display: block; padding: 0 10px">     };
</span><span class="cx" style="display: block; padding: 0 10px"> })();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],19:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],19:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /* exported Validation */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5865,8 +5865,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./Matcher":3,"./Properties":7,"./PropertyValueIterator":10,"./ValidationError":20,"./ValidationTypes":21}],20:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./Matcher":3,"./Properties":7,"./PropertyValueIterator":10,"./ValidationError":20,"./ValidationTypes":21}],20:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = ValidationError;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5907,8 +5907,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> //inherit from Error
</span><span class="cx" style="display: block; padding: 0 10px"> ValidationError.prototype = new Error();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],21:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],21:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> var ValidationTypes = module.exports;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6386,8 +6386,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                  "<font-variant-caps>",
</span><span class="cx" style="display: block; padding: 0 10px">                  { expand: "<font-variant-numeric>" },
</span><span class="cx" style="display: block; padding: 0 10px">                  { expand: "<font-variant-east-asian>" });
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./Matcher":3}],22:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./Matcher":3}],22:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6408,8 +6408,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     Tokens            : require("./Tokens"),
</span><span class="cx" style="display: block; padding: 0 10px">     ValidationError   : require("./ValidationError")
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./Colors":1,"./Combinator":2,"./Matcher":3,"./MediaFeature":4,"./MediaQuery":5,"./Parser":6,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./Specificity":16,"./TokenStream":17,"./Tokens":18,"./ValidationError":20}],23:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./Colors":1,"./Combinator":2,"./Matcher":3,"./MediaFeature":4,"./MediaQuery":5,"./Parser":6,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./Specificity":16,"./TokenStream":17,"./Tokens":18,"./ValidationError":20}],23:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = EventTarget;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6501,8 +6501,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],24:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],24:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = StringReader;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6774,8 +6774,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],25:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],25:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = SyntaxError;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6819,8 +6819,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> //inherit from Error
</span><span class="cx" style="display: block; padding: 0 10px"> SyntaxError.prototype = Object.create(Error.prototype); // jshint ignore:line
</span><span class="cx" style="display: block; padding: 0 10px"> SyntaxError.prototype.constructor = SyntaxError; // jshint ignore:line
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],26:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],26:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = SyntaxUnit;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6903,8 +6903,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">     }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{}],27:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{}],27:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = TokenStreamBase;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7305,8 +7305,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./StringReader":24,"./SyntaxError":25}],28:[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./StringReader":24,"./SyntaxError":25}],28:[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7316,3544 +7316,3544 @@
</span><span class="cx" style="display: block; padding: 0 10px">     EventTarget     : require("./EventTarget"),
</span><span class="cx" style="display: block; padding: 0 10px">     TokenStreamBase : require("./TokenStreamBase")
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./EventTarget":23,"./StringReader":24,"./SyntaxError":25,"./SyntaxUnit":26,"./TokenStreamBase":27}],"parserlib":[function(require,module,exports){
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./EventTarget":23,"./StringReader":24,"./SyntaxError":25,"./SyntaxUnit":26,"./TokenStreamBase":27}],"parserlib":[function(require,module,exports){
</ins><span class="cx" style="display: block; padding: 0 10px"> "use strict";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> module.exports = {
</span><span class="cx" style="display: block; padding: 0 10px">     css  : require("./css"),
</span><span class="cx" style="display: block; padding: 0 10px">     util : require("./util")
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-},{"./css":22,"./util":28}]},{},[]);
-
-return require('parserlib');
-})();
-var clone = (function() {
-'use strict';
-
-var nativeMap;
-try {
-  nativeMap = Map;
-} catch(_) {
-  // maybe a reference error because no `Map`. Give it a dummy value that no
-  // value will ever be an instanceof.
-  nativeMap = function() {};
-}
-
-var nativeSet;
-try {
-  nativeSet = Set;
-} catch(_) {
-  nativeSet = function() {};
-}
-
-var nativePromise;
-try {
-  nativePromise = Promise;
-} catch(_) {
-  nativePromise = function() {};
-}
-
-/**
- * Clones (copies) an Object using deep copying.
- *
- * This function supports circular references by default, but if you are certain
- * there are no circular references in your object, you can save some CPU time
- * by calling clone(obj, false).
- *
- * Caution: if `circular` is false and `parent` contains circular references,
- * your program may enter an infinite loop and crash.
- *
- * @param `parent` - the object to be cloned
- * @param `circular` - set to true if the object to be cloned may contain
- *    circular references. (optional - true by default)
- * @param `depth` - set to a number if the object is only to be cloned to
- *    a particular depth. (optional - defaults to Infinity)
- * @param `prototype` - sets the prototype to be used when cloning an object.
- *    (optional - defaults to parent prototype).
- * @param `includeNonEnumerable` - set to true if the non-enumerable properties
- *    should be cloned as well. Non-enumerable properties on the prototype
- *    chain will be ignored. (optional - false by default)
-*/
-function clone(parent, circular, depth, prototype, includeNonEnumerable) {
-  if (typeof circular === 'object') {
-    depth = circular.depth;
-    prototype = circular.prototype;
-    includeNonEnumerable = circular.includeNonEnumerable;
-    circular = circular.circular;
-  }
-  // maintain two arrays for circular references, where corresponding parents
-  // and children have the same index
-  var allParents = [];
-  var allChildren = [];
-
-  var useBuffer = typeof Buffer != 'undefined';
-
-  if (typeof circular == 'undefined')
-    circular = true;
-
-  if (typeof depth == 'undefined')
-    depth = Infinity;
-
-  // recurse this function so we don't reset allParents and allChildren
-  function _clone(parent, depth) {
-    // cloning null always returns null
-    if (parent === null)
-      return null;
-
-    if (depth === 0)
-      return parent;
-
-    var child;
-    var proto;
-    if (typeof parent != 'object') {
-      return parent;
-    }
-
-    if (parent instanceof nativeMap) {
-      child = new nativeMap();
-    } else if (parent instanceof nativeSet) {
-      child = new nativeSet();
-    } else if (parent instanceof nativePromise) {
-      child = new nativePromise(function (resolve, reject) {
-        parent.then(function(value) {
-          resolve(_clone(value, depth - 1));
-        }, function(err) {
-          reject(_clone(err, depth - 1));
-        });
-      });
-    } else if (clone.__isArray(parent)) {
-      child = [];
-    } else if (clone.__isRegExp(parent)) {
-      child = new RegExp(parent.source, __getRegExpFlags(parent));
-      if (parent.lastIndex) child.lastIndex = parent.lastIndex;
-    } else if (clone.__isDate(parent)) {
-      child = new Date(parent.getTime());
-    } else if (useBuffer && Buffer.isBuffer(parent)) {
-      child = new Buffer(parent.length);
-      parent.copy(child);
-      return child;
-    } else if (parent instanceof Error) {
-      child = Object.create(parent);
-    } else {
-      if (typeof prototype == 'undefined') {
-        proto = Object.getPrototypeOf(parent);
-        child = Object.create(proto);
-      }
-      else {
-        child = Object.create(prototype);
-        proto = prototype;
-      }
-    }
-
-    if (circular) {
-      var index = allParents.indexOf(parent);
-
-      if (index != -1) {
-        return allChildren[index];
-      }
-      allParents.push(parent);
-      allChildren.push(child);
-    }
-
-    if (parent instanceof nativeMap) {
-      var keyIterator = parent.keys();
-      while(true) {
-        var next = keyIterator.next();
-        if (next.done) {
-          break;
-        }
-        var keyChild = _clone(next.value, depth - 1);
-        var valueChild = _clone(parent.get(next.value), depth - 1);
-        child.set(keyChild, valueChild);
-      }
-    }
-    if (parent instanceof nativeSet) {
-      var iterator = parent.keys();
-      while(true) {
-        var next = iterator.next();
-        if (next.done) {
-          break;
-        }
-        var entryChild = _clone(next.value, depth - 1);
-        child.add(entryChild);
-      }
-    }
-
-    for (var i in parent) {
-      var attrs;
-      if (proto) {
-        attrs = Object.getOwnPropertyDescriptor(proto, i);
-      }
-
-      if (attrs && attrs.set == null) {
-        continue;
-      }
-      child[i] = _clone(parent[i], depth - 1);
-    }
-
-    if (Object.getOwnPropertySymbols) {
-      var symbols = Object.getOwnPropertySymbols(parent);
-      for (var i = 0; i < symbols.length; i++) {
-        // Don't need to worry about cloning a symbol because it is a primitive,
-        // like a number or string.
-        var symbol = symbols[i];
-        var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
-        if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
-          continue;
-        }
-        child[symbol] = _clone(parent[symbol], depth - 1);
-        if (!descriptor.enumerable) {
-          Object.defineProperty(child, symbol, {
-            enumerable: false
-          });
-        }
-      }
-    }
-
-    if (includeNonEnumerable) {
-      var allPropertyNames = Object.getOwnPropertyNames(parent);
-      for (var i = 0; i < allPropertyNames.length; i++) {
-        var propertyName = allPropertyNames[i];
-        var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
-        if (descriptor && descriptor.enumerable) {
-          continue;
-        }
-        child[propertyName] = _clone(parent[propertyName], depth - 1);
-        Object.defineProperty(child, propertyName, {
-          enumerable: false
-        });
-      }
-    }
-
-    return child;
-  }
-
-  return _clone(parent, depth);
-}
-
-/**
- * Simple flat clone using prototype, accepts only objects, usefull for property
- * override on FLAT configuration object (no nested props).
- *
- * USE WITH CAUTION! This may not behave as you wish if you do not know how this
- * works.
- */
-clone.clonePrototype = function clonePrototype(parent) {
-  if (parent === null)
-    return null;
-
-  var c = function () {};
-  c.prototype = parent;
-  return new c();
-};
-
-// private utility functions
-
-function __objToStr(o) {
-  return Object.prototype.toString.call(o);
-}
-clone.__objToStr = __objToStr;
-
-function __isDate(o) {
-  return typeof o === 'object' && __objToStr(o) === '[object Date]';
-}
-clone.__isDate = __isDate;
-
-function __isArray(o) {
-  return typeof o === 'object' && __objToStr(o) === '[object Array]';
-}
-clone.__isArray = __isArray;
-
-function __isRegExp(o) {
-  return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
-}
-clone.__isRegExp = __isRegExp;
-
-function __getRegExpFlags(re) {
-  var flags = '';
-  if (re.global) flags += 'g';
-  if (re.ignoreCase) flags += 'i';
-  if (re.multiline) flags += 'm';
-  return flags;
-}
-clone.__getRegExpFlags = __getRegExpFlags;
-
-return clone;
-})();
-
-if (typeof module === 'object' && module.exports) {
-  module.exports = clone;
-}
-
-/**
- * Main CSSLint object.
- * @class CSSLint
- * @static
- * @extends parserlib.util.EventTarget
- */
-
-/* global parserlib, clone, Reporter */
-/* exported CSSLint */
-
-var CSSLint = (function() {
-    "use strict";
-
-    var rules           = [],
-        formatters      = [],
-        embeddedRuleset = /\/\*\s*csslint([^\*]*)\*\//,
-        api             = new parserlib.util.EventTarget();
-
-    api.version = "1.0.4";
-
-    //-------------------------------------------------------------------------
-    // Rule Management
-    //-------------------------------------------------------------------------
-
-    /**
-     * Adds a new rule to the engine.
-     * @param {Object} rule The rule to add.
-     * @method addRule
-     */
-    api.addRule = function(rule) {
-        rules.push(rule);
-        rules[rule.id] = rule;
-    };
-
-    /**
-     * Clears all rule from the engine.
-     * @method clearRules
-     */
-    api.clearRules = function() {
-        rules = [];
-    };
-
-    /**
-     * Returns the rule objects.
-     * @return An array of rule objects.
-     * @method getRules
-     */
-    api.getRules = function() {
-        return [].concat(rules).sort(function(a, b) {
-            return a.id > b.id ? 1 : 0;
-        });
-    };
-
-    /**
-     * Returns a ruleset configuration object with all current rules.
-     * @return A ruleset object.
-     * @method getRuleset
-     */
-    api.getRuleset = function() {
-        var ruleset = {},
-            i = 0,
-            len = rules.length;
-
-        while (i < len) {
-            ruleset[rules[i++].id] = 1;    // by default, everything is a warning
-        }
-
-        return ruleset;
-    };
-
-    /**
-     * Returns a ruleset object based on embedded rules.
-     * @param {String} text A string of css containing embedded rules.
-     * @param {Object} ruleset A ruleset object to modify.
-     * @return {Object} A ruleset object.
-     * @method getEmbeddedRuleset
-     */
-    function applyEmbeddedRuleset(text, ruleset) {
-        var valueMap,
-            embedded = text && text.match(embeddedRuleset),
-            rules = embedded && embedded[1];
-
-        if (rules) {
-            valueMap = {
-                "true": 2,  // true is error
-                "": 1,      // blank is warning
-                "false": 0, // false is ignore
-
-                "2": 2,     // explicit error
-                "1": 1,     // explicit warning
-                "0": 0      // explicit ignore
-            };
-
-            rules.toLowerCase().split(",").forEach(function(rule) {
-                var pair = rule.split(":"),
-                    property = pair[0] || "",
-                    value = pair[1] || "";
-
-                ruleset[property.trim()] = valueMap[value.trim()];
-            });
-        }
-
-        return ruleset;
-    }
-
-    //-------------------------------------------------------------------------
-    // Formatters
-    //-------------------------------------------------------------------------
-
-    /**
-     * Adds a new formatter to the engine.
-     * @param {Object} formatter The formatter to add.
-     * @method addFormatter
-     */
-    api.addFormatter = function(formatter) {
-        // formatters.push(formatter);
-        formatters[formatter.id] = formatter;
-    };
-
-    /**
-     * Retrieves a formatter for use.
-     * @param {String} formatId The name of the format to retrieve.
-     * @return {Object} The formatter or undefined.
-     * @method getFormatter
-     */
-    api.getFormatter = function(formatId) {
-        return formatters[formatId];
-    };
-
-    /**
-     * Formats the results in a particular format for a single file.
-     * @param {Object} result The results returned from CSSLint.verify().
-     * @param {String} filename The filename for which the results apply.
-     * @param {String} formatId The name of the formatter to use.
-     * @param {Object} options (Optional) for special output handling.
-     * @return {String} A formatted string for the results.
-     * @method format
-     */
-    api.format = function(results, filename, formatId, options) {
-        var formatter = this.getFormatter(formatId),
-            result = null;
-
-        if (formatter) {
-            result = formatter.startFormat();
-            result += formatter.formatResults(results, filename, options || {});
-            result += formatter.endFormat();
-        }
-
-        return result;
-    };
-
-    /**
-     * Indicates if the given format is supported.
-     * @param {String} formatId The ID of the format to check.
-     * @return {Boolean} True if the format exists, false if not.
-     * @method hasFormat
-     */
-    api.hasFormat = function(formatId) {
-        return formatters.hasOwnProperty(formatId);
-    };
-
-    //-------------------------------------------------------------------------
-    // Verification
-    //-------------------------------------------------------------------------
-
-    /**
-     * Starts the verification process for the given CSS text.
-     * @param {String} text The CSS text to verify.
-     * @param {Object} ruleset (Optional) List of rules to apply. If null, then
-     *      all rules are used. If a rule has a value of 1 then it's a warning,
-     *      a value of 2 means it's an error.
-     * @return {Object} Results of the verification.
-     * @method verify
-     */
-    api.verify = function(text, ruleset) {
-
-        var i = 0,
-            reporter,
-            lines,
-            allow = {},
-            ignore = [],
-            report,
-            parser = new parserlib.css.Parser({
-                starHack: true,
-                ieFilters: true,
-                underscoreHack: true,
-                strict: false
-            });
-
-        // normalize line endings
-        lines = text.replace(/\n\r?/g, "$split$").split("$split$");
-
-        // find 'allow' comments
-        CSSLint.Util.forEach(lines, function (line, lineno) {
-            var allowLine = line && line.match(/\/\*[ \t]*csslint[ \t]+allow:[ \t]*([^\*]*)\*\//i),
-                allowRules = allowLine && allowLine[1],
-                allowRuleset = {};
-
-            if (allowRules) {
-                allowRules.toLowerCase().split(",").forEach(function(allowRule) {
-                    allowRuleset[allowRule.trim()] = true;
-                });
-                if (Object.keys(allowRuleset).length > 0) {
-                    allow[lineno + 1] = allowRuleset;
-                }
-            }
-        });
-
-        var ignoreStart = null,
-            ignoreEnd = null;
-        CSSLint.Util.forEach(lines, function (line, lineno) {
-            // Keep oldest, "unclosest" ignore:start
-            if (ignoreStart === null && line.match(/\/\*[ \t]*csslint[ \t]+ignore:start[ \t]*\*\//i)) {
-                ignoreStart = lineno;
-            }
-
-            if (line.match(/\/\*[ \t]*csslint[ \t]+ignore:end[ \t]*\*\//i)) {
-                ignoreEnd = lineno;
-            }
-
-            if (ignoreStart !== null && ignoreEnd !== null) {
-                ignore.push([ignoreStart, ignoreEnd]);
-                ignoreStart = ignoreEnd = null;
-            }
-        });
-
-        // Close remaining ignore block, if any
-        if (ignoreStart !== null) {
-            ignore.push([ignoreStart, lines.length]);
-        }
-
-        if (!ruleset) {
-            ruleset = this.getRuleset();
-        }
-
-        if (embeddedRuleset.test(text)) {
-            // defensively copy so that caller's version does not get modified
-            ruleset = clone(ruleset);
-            ruleset = applyEmbeddedRuleset(text, ruleset);
-        }
-
-        reporter = new Reporter(lines, ruleset, allow, ignore);
-
-        ruleset.errors = 2;       // always report parsing errors as errors
-        for (i in ruleset) {
-            if (ruleset.hasOwnProperty(i) && ruleset[i]) {
-                if (rules[i]) {
-                    rules[i].init(parser, reporter);
-                }
-            }
-        }
-
-
-        // capture most horrible error type
-        try {
-            parser.parse(text);
-        } catch (ex) {
-            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});
-        }
-
-        report = {
-            messages    : reporter.messages,
-            stats       : reporter.stats,
-            ruleset     : reporter.ruleset,
-            allow       : reporter.allow,
-            ignore      : reporter.ignore
-        };
-
-        // sort by line numbers, rollups at the bottom
-        report.messages.sort(function (a, b) {
-            if (a.rollup && !b.rollup) {
-                return 1;
-            } else if (!a.rollup && b.rollup) {
-                return -1;
-            } else {
-                return a.line - b.line;
-            }
-        });
-
-        return report;
-    };
-
-    //-------------------------------------------------------------------------
-    // Publish the API
-    //-------------------------------------------------------------------------
-
-    return api;
-
-})();
-
-/**
- * An instance of Report is used to report results of the
- * verification back to the main API.
- * @class Reporter
- * @constructor
- * @param {String[]} lines The text lines of the source.
- * @param {Object} ruleset The set of rules to work with, including if
- *      they are errors or warnings.
- * @param {Object} explicitly allowed lines
- * @param {[][]} ingore list of line ranges to be ignored
- */
-function Reporter(lines, ruleset, allow, ignore) {
-    "use strict";
-
-    /**
-     * List of messages being reported.
-     * @property messages
-     * @type String[]
-     */
-    this.messages = [];
-
-    /**
-     * List of statistics being reported.
-     * @property stats
-     * @type String[]
-     */
-    this.stats = [];
-
-    /**
-     * Lines of code being reported on. Used to provide contextual information
-     * for messages.
-     * @property lines
-     * @type String[]
-     */
-    this.lines = lines;
-
-    /**
-     * Information about the rules. Used to determine whether an issue is an
-     * error or warning.
-     * @property ruleset
-     * @type Object
-     */
-    this.ruleset = ruleset;
-
-    /**
-     * Lines with specific rule messages to leave out of the report.
-     * @property allow
-     * @type Object
-     */
-    this.allow = allow;
-    if (!this.allow) {
-        this.allow = {};
-    }
-
-    /**
-     * Linesets not to include in the report.
-     * @property ignore
-     * @type [][]
-     */
-    this.ignore = ignore;
-    if (!this.ignore) {
-        this.ignore = [];
-    }
-}
-
-Reporter.prototype = {
-
-    // restore constructor
-    constructor: Reporter,
-
-    /**
-     * Report an error.
-     * @param {String} message The message to store.
-     * @param {int} line The line number.
-     * @param {int} col The column number.
-     * @param {Object} rule The rule this message relates to.
-     * @method error
-     */
-    error: function(message, line, col, rule) {
-        "use strict";
-        this.messages.push({
-            type    : "error",
-            line    : line,
-            col     : col,
-            message : message,
-            evidence: this.lines[line-1],
-            rule    : rule || {}
-        });
-    },
-
-    /**
-     * Report an warning.
-     * @param {String} message The message to store.
-     * @param {int} line The line number.
-     * @param {int} col The column number.
-     * @param {Object} rule The rule this message relates to.
-     * @method warn
-     * @deprecated Use report instead.
-     */
-    warn: function(message, line, col, rule) {
-        "use strict";
-        this.report(message, line, col, rule);
-    },
-
-    /**
-     * Report an issue.
-     * @param {String} message The message to store.
-     * @param {int} line The line number.
-     * @param {int} col The column number.
-     * @param {Object} rule The rule this message relates to.
-     * @method report
-     */
-    report: function(message, line, col, rule) {
-        "use strict";
-
-        // Check if rule violation should be allowed
-        if (this.allow.hasOwnProperty(line) && this.allow[line].hasOwnProperty(rule.id)) {
-            return;
-        }
-
-        var ignore = false;
-        CSSLint.Util.forEach(this.ignore, function (range) {
-            if (range[0] <= line && line <= range[1]) {
-                ignore = true;
-            }
-        });
-        if (ignore) {
-            return;
-        }
-
-        this.messages.push({
-            type    : this.ruleset[rule.id] === 2 ? "error" : "warning",
-            line    : line,
-            col     : col,
-            message : message,
-            evidence: this.lines[line-1],
-            rule    : rule
-        });
-    },
-
-    /**
-     * Report some informational text.
-     * @param {String} message The message to store.
-     * @param {int} line The line number.
-     * @param {int} col The column number.
-     * @param {Object} rule The rule this message relates to.
-     * @method info
-     */
-    info: function(message, line, col, rule) {
-        "use strict";
-        this.messages.push({
-            type    : "info",
-            line    : line,
-            col     : col,
-            message : message,
-            evidence: this.lines[line-1],
-            rule    : rule
-        });
-    },
-
-    /**
-     * Report some rollup error information.
-     * @param {String} message The message to store.
-     * @param {Object} rule The rule this message relates to.
-     * @method rollupError
-     */
-    rollupError: function(message, rule) {
-        "use strict";
-        this.messages.push({
-            type    : "error",
-            rollup  : true,
-            message : message,
-            rule    : rule
-        });
-    },
-
-    /**
-     * Report some rollup warning information.
-     * @param {String} message The message to store.
-     * @param {Object} rule The rule this message relates to.
-     * @method rollupWarn
-     */
-    rollupWarn: function(message, rule) {
-        "use strict";
-        this.messages.push({
-            type    : "warning",
-            rollup  : true,
-            message : message,
-            rule    : rule
-        });
-    },
-
-    /**
-     * Report a statistic.
-     * @param {String} name The name of the stat to store.
-     * @param {Variant} value The value of the stat.
-     * @method stat
-     */
-    stat: function(name, value) {
-        "use strict";
-        this.stats[name] = value;
-    }
-};
-
-// expose for testing purposes
-CSSLint._Reporter = Reporter;
-
-/*
- * Utility functions that make life easier.
- */
-CSSLint.Util = {
-    /*
-     * Adds all properties from supplier onto receiver,
-     * overwriting if the same name already exists on
-     * receiver.
-     * @param {Object} The object to receive the properties.
-     * @param {Object} The object to provide the properties.
-     * @return {Object} The receiver
-     */
-    mix: function(receiver, supplier) {
-        "use strict";
-        var prop;
-
-        for (prop in supplier) {
-            if (supplier.hasOwnProperty(prop)) {
-                receiver[prop] = supplier[prop];
-            }
-        }
-
-        return prop;
-    },
-
-    /*
-     * Polyfill for array indexOf() method.
-     * @param {Array} values The array to search.
-     * @param {Variant} value The value to search for.
-     * @return {int} The index of the value if found, -1 if not.
-     */
-    indexOf: function(values, value) {
-        "use strict";
-        if (values.indexOf) {
-            return values.indexOf(value);
-        } else {
-            for (var i=0, len=values.length; i < len; i++) {
-                if (values[i] === value) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-    },
-
-    /*
-     * Polyfill for array forEach() method.
-     * @param {Array} values The array to operate on.
-     * @param {Function} func The function to call on each item.
-     * @return {void}
-     */
-    forEach: function(values, func) {
-        "use strict";
-        if (values.forEach) {
-            return values.forEach(func);
-        } else {
-            for (var i=0, len=values.length; i < len; i++) {
-                func(values[i], i, values);
-            }
-        }
-    }
-};
-
-/*
- * Rule: Don't use adjoining classes (.foo.bar).
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "adjoining-classes",
-    name: "Disallow adjoining classes",
-    desc: "Don't use adjoining classes.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-adjoining-classes",
-    browsers: "IE6",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                modifier,
-                classCount,
-                i, j, k;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-                for (j=0; j < selector.parts.length; j++) {
-                    part = selector.parts[j];
-                    if (part.type === parser.SELECTOR_PART_TYPE) {
-                        classCount = 0;
-                        for (k=0; k < part.modifiers.length; k++) {
-                            modifier = part.modifiers[k];
-                            if (modifier.type === "class") {
-                                classCount++;
-                            }
-                            if (classCount > 1){
-                                reporter.report("Adjoining classes: "+selectors[i].text, part.line, part.col, rule);
-                            }
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Don't use width or height when using padding or border.
- */
-CSSLint.addRule({
-
-    // rule information
-    id: "box-model",
-    name: "Beware of broken box size",
-    desc: "Don't use width or height when using padding or border.",
-    url: "https://github.com/CSSLint/csslint/wiki/Beware-of-box-model-size",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            widthProperties = {
-                border: 1,
-                "border-left": 1,
-                "border-right": 1,
-                padding: 1,
-                "padding-left": 1,
-                "padding-right": 1
-            },
-            heightProperties = {
-                border: 1,
-                "border-bottom": 1,
-                "border-top": 1,
-                padding: 1,
-                "padding-bottom": 1,
-                "padding-top": 1
-            },
-            properties,
-            boxSizing = false;
-
-        function startRule() {
-            properties = {};
-            boxSizing = false;
-        }
-
-        function endRule() {
-            var prop, value;
-
-            if (!boxSizing) {
-                if (properties.height) {
-                    for (prop in heightProperties) {
-                        if (heightProperties.hasOwnProperty(prop) && properties[prop]) {
-                            value = properties[prop].value;
-                            // special case for padding
-                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[0].value === 0)) {
-                                reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
-                            }
-                        }
-                    }
-                }
-
-                if (properties.width) {
-                    for (prop in widthProperties) {
-                        if (widthProperties.hasOwnProperty(prop) && properties[prop]) {
-                            value = properties[prop].value;
-
-                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[1].value === 0)) {
-                                reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text.toLowerCase();
-
-            if (heightProperties[name] || widthProperties[name]) {
-                if (!/^0\S*$/.test(event.value) && !(name === "border" && event.value.toString() === "none")) {
-                    properties[name] = {
-                        line: event.property.line,
-                        col: event.property.col,
-                        value: event.value
-                    };
-                }
-            } else {
-                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)) {
-                    properties[name] = 1;
-                } else if (name === "box-sizing") {
-                    boxSizing = true;
-                }
-            }
-
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-        parser.addListener("endpage", endRule);
-        parser.addListener("endpagemargin", endRule);
-        parser.addListener("endkeyframerule", endRule);
-        parser.addListener("endviewport", endRule);
-    }
-
-});
-
-/*
- * Rule: box-sizing doesn't work in IE6 and IE7.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "box-sizing",
-    name: "Disallow use of box-sizing",
-    desc: "The box-sizing properties isn't supported in IE6 and IE7.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-box-sizing",
-    browsers: "IE6, IE7",
-    tags: ["Compatibility"],
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text.toLowerCase();
-
-            if (name === "box-sizing") {
-                reporter.report("The box-sizing property isn't supported in IE6 and IE7.", event.line, event.col, rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Use the bulletproof @font-face syntax to avoid 404's in old IE
- * (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax)
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "bulletproof-font-face",
-    name: "Use the bulletproof @font-face syntax",
-    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).",
-    url: "https://github.com/CSSLint/csslint/wiki/Bulletproof-font-face",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            fontFaceRule = false,
-            firstSrc = true,
-            ruleFailed = false,
-            line, col;
-
-        // Mark the start of a @font-face declaration so we only test properties inside it
-        parser.addListener("startfontface", function() {
-            fontFaceRule = true;
-        });
-
-        parser.addListener("property", function(event) {
-            // If we aren't inside an @font-face declaration then just return
-            if (!fontFaceRule) {
-                return;
-            }
-
-            var propertyName = event.property.toString().toLowerCase(),
-                value = event.value.toString();
-
-            // Set the line and col numbers for use in the endfontface listener
-            line = event.line;
-            col = event.col;
-
-            // This is the property that we care about, we can ignore the rest
-            if (propertyName === "src") {
-                var regex = /^\s?url\(['"].+\.eot\?.*['"]\)\s*format\(['"]embedded-opentype['"]\).*$/i;
-
-                // We need to handle the advanced syntax with two src properties
-                if (!value.match(regex) && firstSrc) {
-                    ruleFailed = true;
-                    firstSrc = false;
-                } else if (value.match(regex) && !firstSrc) {
-                    ruleFailed = false;
-                }
-            }
-
-
-        });
-
-        // Back to normal rules that we don't need to test
-        parser.addListener("endfontface", function() {
-            fontFaceRule = false;
-
-            if (ruleFailed) {
-                reporter.report("@font-face declaration doesn't follow the fontspring bulletproof syntax.", line, col, rule);
-            }
-        });
-    }
-});
-
-/*
- * Rule: Include all compatible vendor prefixes to reach a wider
- * range of users.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "compatible-vendor-prefixes",
-    name: "Require compatible vendor prefixes",
-    desc: "Include all compatible vendor prefixes to reach a wider range of users.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-compatible-vendor-prefixes",
-    browsers: "All",
-
-    // initialization
-    init: function (parser, reporter) {
-        "use strict";
-        var rule = this,
-            compatiblePrefixes,
-            properties,
-            prop,
-            variations,
-            prefixed,
-            i,
-            len,
-            inKeyFrame = false,
-            arrayPush = Array.prototype.push,
-            applyTo = [];
-
-        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details
-        compatiblePrefixes = {
-            "animation"                  : "webkit",
-            "animation-delay"            : "webkit",
-            "animation-direction"        : "webkit",
-            "animation-duration"         : "webkit",
-            "animation-fill-mode"        : "webkit",
-            "animation-iteration-count"  : "webkit",
-            "animation-name"             : "webkit",
-            "animation-play-state"       : "webkit",
-            "animation-timing-function"  : "webkit",
-            "appearance"                 : "webkit moz",
-            "border-end"                 : "webkit moz",
-            "border-end-color"           : "webkit moz",
-            "border-end-style"           : "webkit moz",
-            "border-end-width"           : "webkit moz",
-            "border-image"               : "webkit moz o",
-            "border-radius"              : "webkit",
-            "border-start"               : "webkit moz",
-            "border-start-color"         : "webkit moz",
-            "border-start-style"         : "webkit moz",
-            "border-start-width"         : "webkit moz",
-            "box-align"                  : "webkit moz ms",
-            "box-direction"              : "webkit moz ms",
-            "box-flex"                   : "webkit moz ms",
-            "box-lines"                  : "webkit ms",
-            "box-ordinal-group"          : "webkit moz ms",
-            "box-orient"                 : "webkit moz ms",
-            "box-pack"                   : "webkit moz ms",
-            "box-sizing"                 : "",
-            "box-shadow"                 : "",
-            "column-count"               : "webkit moz ms",
-            "column-gap"                 : "webkit moz ms",
-            "column-rule"                : "webkit moz ms",
-            "column-rule-color"          : "webkit moz ms",
-            "column-rule-style"          : "webkit moz ms",
-            "column-rule-width"          : "webkit moz ms",
-            "column-width"               : "webkit moz ms",
-            "hyphens"                    : "epub moz",
-            "line-break"                 : "webkit ms",
-            "margin-end"                 : "webkit moz",
-            "margin-start"               : "webkit moz",
-            "marquee-speed"              : "webkit wap",
-            "marquee-style"              : "webkit wap",
-            "padding-end"                : "webkit moz",
-            "padding-start"              : "webkit moz",
-            "tab-size"                   : "moz o",
-            "text-size-adjust"           : "webkit ms",
-            "transform"                  : "webkit ms",
-            "transform-origin"           : "webkit ms",
-            "transition"                 : "",
-            "transition-delay"           : "",
-            "transition-duration"        : "",
-            "transition-property"        : "",
-            "transition-timing-function" : "",
-            "user-modify"                : "webkit moz",
-            "user-select"                : "webkit moz ms",
-            "word-break"                 : "epub ms",
-            "writing-mode"               : "epub ms"
-        };
-
-
-        for (prop in compatiblePrefixes) {
-            if (compatiblePrefixes.hasOwnProperty(prop)) {
-                variations = [];
-                prefixed = compatiblePrefixes[prop].split(" ");
-                for (i = 0, len = prefixed.length; i < len; i++) {
-                    variations.push("-" + prefixed[i] + "-" + prop);
-                }
-                compatiblePrefixes[prop] = variations;
-                arrayPush.apply(applyTo, variations);
-            }
-        }
-
-        parser.addListener("startrule", function () {
-            properties = [];
-        });
-
-        parser.addListener("startkeyframes", function (event) {
-            inKeyFrame = event.prefix || true;
-        });
-
-        parser.addListener("endkeyframes", function () {
-            inKeyFrame = false;
-        });
-
-        parser.addListener("property", function (event) {
-            var name = event.property;
-            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {
-
-                // e.g., -moz-transform is okay to be alone in @-moz-keyframes
-                if (!inKeyFrame || typeof inKeyFrame !== "string" ||
-                        name.text.indexOf("-" + inKeyFrame + "-") !== 0) {
-                    properties.push(name);
-                }
-            }
-        });
-
-        parser.addListener("endrule", function () {
-            if (!properties.length) {
-                return;
-            }
-
-            var propertyGroups = {},
-                i,
-                len,
-                name,
-                prop,
-                variations,
-                value,
-                full,
-                actual,
-                item,
-                propertiesSpecified;
-
-            for (i = 0, len = properties.length; i < len; i++) {
-                name = properties[i];
-
-                for (prop in compatiblePrefixes) {
-                    if (compatiblePrefixes.hasOwnProperty(prop)) {
-                        variations = compatiblePrefixes[prop];
-                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {
-                            if (!propertyGroups[prop]) {
-                                propertyGroups[prop] = {
-                                    full: variations.slice(0),
-                                    actual: [],
-                                    actualNodes: []
-                                };
-                            }
-                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {
-                                propertyGroups[prop].actual.push(name.text);
-                                propertyGroups[prop].actualNodes.push(name);
-                            }
-                        }
-                    }
-                }
-            }
-
-            for (prop in propertyGroups) {
-                if (propertyGroups.hasOwnProperty(prop)) {
-                    value = propertyGroups[prop];
-                    full = value.full;
-                    actual = value.actual;
-
-                    if (full.length > actual.length) {
-                        for (i = 0, len = full.length; i < len; i++) {
-                            item = full[i];
-                            if (CSSLint.Util.indexOf(actual, item) === -1) {
-                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length === 2) ? actual.join(" and ") : actual.join(", ");
-                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule);
-                            }
-                        }
-
-                    }
-                }
-            }
-        });
-    }
-});
-
-/*
- * Rule: Certain properties don't play well with certain display values.
- * - float should not be used with inline-block
- * - height, width, margin-top, margin-bottom, float should not be used with inline
- * - vertical-align should not be used with block
- * - margin, float should not be used with table-*
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "display-property-grouping",
-    name: "Require properties appropriate for display",
-    desc: "Certain properties shouldn't be used with certain display property values.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-properties-appropriate-for-display",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        var propertiesToCheck = {
-                display: 1,
-                "float": "none",
-                height: 1,
-                width: 1,
-                margin: 1,
-                "margin-left": 1,
-                "margin-right": 1,
-                "margin-bottom": 1,
-                "margin-top": 1,
-                padding: 1,
-                "padding-left": 1,
-                "padding-right": 1,
-                "padding-bottom": 1,
-                "padding-top": 1,
-                "vertical-align": 1
-            },
-            properties;
-
-        function reportProperty(name, display, msg) {
-            if (properties[name]) {
-                if (typeof propertiesToCheck[name] !== "string" || properties[name].value.toLowerCase() !== propertiesToCheck[name]) {
-                    reporter.report(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
-                }
-            }
-        }
-
-        function startRule() {
-            properties = {};
-        }
-
-        function endRule() {
-
-            var display = properties.display ? properties.display.value : null;
-            if (display) {
-                switch (display) {
-
-                    case "inline":
-                        // height, width, margin-top, margin-bottom, float should not be used with inline
-                        reportProperty("height", display);
-                        reportProperty("width", display);
-                        reportProperty("margin", display);
-                        reportProperty("margin-top", display);
-                        reportProperty("margin-bottom", display);
-                        reportProperty("float", display, "display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");
-                        break;
-
-                    case "block":
-                        // vertical-align should not be used with block
-                        reportProperty("vertical-align", display);
-                        break;
-
-                    case "inline-block":
-                        // float should not be used with inline-block
-                        reportProperty("float", display);
-                        break;
-
-                    default:
-                        // margin, float should not be used with table
-                        if (display.indexOf("table-") === 0) {
-                            reportProperty("margin", display);
-                            reportProperty("margin-left", display);
-                            reportProperty("margin-right", display);
-                            reportProperty("margin-top", display);
-                            reportProperty("margin-bottom", display);
-                            reportProperty("float", display);
-                        }
-
-                        // otherwise do nothing
-                }
-            }
-
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text.toLowerCase();
-
-            if (propertiesToCheck[name]) {
-                properties[name] = {
-                    value: event.value.text,
-                    line: event.property.line,
-                    col: event.property.col
-                };
-            }
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-        parser.addListener("endkeyframerule", endRule);
-        parser.addListener("endpagemargin", endRule);
-        parser.addListener("endpage", endRule);
-        parser.addListener("endviewport", endRule);
-
-    }
-
-});
-
-/*
- * Rule: Disallow duplicate background-images (using url).
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "duplicate-background-images",
-    name: "Disallow duplicate background images",
-    desc: "Every background-image should be unique. Use a common class for e.g. sprites.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-background-images",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            stack = {};
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text,
-                value = event.value,
-                i, len;
-
-            if (name.match(/background/i)) {
-                for (i=0, len=value.parts.length; i < len; i++) {
-                    if (value.parts[i].type === "uri") {
-                        if (typeof stack[value.parts[i].uri] === "undefined") {
-                            stack[value.parts[i].uri] = event;
-                        } else {
-                            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);
-                        }
-                    }
-                }
-            }
-        });
-    }
-});
-
-/*
- * Rule: Duplicate properties must appear one after the other. If an already-defined
- * property appears somewhere else in the rule, then it's likely an error.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "duplicate-properties",
-    name: "Disallow duplicate properties",
-    desc: "Duplicate properties must appear one after the other.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-properties",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            properties,
-            lastProperty;
-
-        function startRule() {
-            properties = {};
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var property = event.property,
-                name = property.text.toLowerCase();
-
-            if (properties[name] && (lastProperty !== name || properties[name] === event.value.text)) {
-                reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
-            }
-
-            properties[name] = event.value.text;
-            lastProperty = name;
-
-        });
-
-
-    }
-
-});
-
-/*
- * Rule: Style rules without any properties defined should be removed.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "empty-rules",
-    name: "Disallow empty rules",
-    desc: "Rules without any properties specified should be removed.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-empty-rules",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            count = 0;
-
-        parser.addListener("startrule", function() {
-            count=0;
-        });
-
-        parser.addListener("property", function() {
-            count++;
-        });
-
-        parser.addListener("endrule", function(event) {
-            var selectors = event.selectors;
-            if (count === 0) {
-                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: There should be no syntax errors. (Duh.)
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "errors",
-    name: "Parsing Errors",
-    desc: "This rule looks for recoverable syntax errors.",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("error", function(event) {
-            reporter.error(event.message, event.line, event.col, rule);
-        });
-
-    }
-
-});
-
-CSSLint.addRule({
-
-    // rule information
-    id: "fallback-colors",
-    name: "Require fallback colors",
-    desc: "For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-fallback-colors",
-    browsers: "IE6,IE7,IE8",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            lastProperty,
-            propertiesToCheck = {
-                color: 1,
-                background: 1,
-                "border-color": 1,
-                "border-top-color": 1,
-                "border-right-color": 1,
-                "border-bottom-color": 1,
-                "border-left-color": 1,
-                border: 1,
-                "border-top": 1,
-                "border-right": 1,
-                "border-bottom": 1,
-                "border-left": 1,
-                "background-color": 1
-            };
-
-        function startRule() {
-            lastProperty = null;
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var property = event.property,
-                name = property.text.toLowerCase(),
-                parts = event.value.parts,
-                i = 0,
-                colorType = "",
-                len = parts.length;
-
-            if (propertiesToCheck[name]) {
-                while (i < len) {
-                    if (parts[i].type === "color") {
-                        if ("alpha" in parts[i] || "hue" in parts[i]) {
-
-                            if (/([^\)]+)\(/.test(parts[i])) {
-                                colorType = RegExp.$1.toUpperCase();
-                            }
-
-                            if (!lastProperty || (lastProperty.property.text.toLowerCase() !== name || lastProperty.colorType !== "compat")) {
-                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
-                            }
-                        } else {
-                            event.colorType = "compat";
-                        }
-                    }
-
-                    i++;
-                }
-            }
-
-            lastProperty = event;
-        });
-
-    }
-
-});
-
-/*
- * Rule: You shouldn't use more than 10 floats. If you do, there's probably
- * room for some abstraction.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "floats",
-    name: "Disallow too many floats",
-    desc: "This rule tests if the float property is used too many times",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-too-many-floats",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-        var count = 0;
-
-        // count how many times "float" is used
-        parser.addListener("property", function(event) {
-            if (event.property.text.toLowerCase() === "float" &&
-                    event.value.text.toLowerCase() !== "none") {
-                count++;
-            }
-        });
-
-        // report the results
-        parser.addListener("endstylesheet", function() {
-            reporter.stat("floats", count);
-            if (count >= 10) {
-                reporter.rollupWarn("Too many floats (" + count + "), you're probably using them for layout. Consider using a grid system instead.", rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Avoid too many @font-face declarations in the same stylesheet.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "font-faces",
-    name: "Don't use too many web fonts",
-    desc: "Too many different web fonts in the same stylesheet.",
-    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-web-fonts",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            count = 0;
-
-
-        parser.addListener("startfontface", function() {
-            count++;
-        });
-
-        parser.addListener("endstylesheet", function() {
-            if (count > 5) {
-                reporter.rollupWarn("Too many @font-face declarations (" + count + ").", rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: You shouldn't need more than 9 font-size declarations.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "font-sizes",
-    name: "Disallow too many font sizes",
-    desc: "Checks the number of font-size declarations.",
-    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-font-size-declarations",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            count = 0;
-
-        // check for use of "font-size"
-        parser.addListener("property", function(event) {
-            if (event.property.toString() === "font-size") {
-                count++;
-            }
-        });
-
-        // report the results
-        parser.addListener("endstylesheet", function() {
-            reporter.stat("font-sizes", count);
-            if (count >= 10) {
-                reporter.rollupWarn("Too many font-size declarations (" + count + "), abstraction needed.", rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: When using a vendor-prefixed gradient, make sure to use them all.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "gradients",
-    name: "Require all gradient definitions",
-    desc: "When using a vendor-prefixed gradient, make sure to use them all.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-all-gradient-definitions",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            gradients;
-
-        parser.addListener("startrule", function() {
-            gradients = {
-                moz: 0,
-                webkit: 0,
-                oldWebkit: 0,
-                o: 0
-            };
-        });
-
-        parser.addListener("property", function(event) {
-
-            if (/\-(moz|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)) {
-                gradients[RegExp.$1] = 1;
-            } else if (/\-webkit\-gradient/i.test(event.value)) {
-                gradients.oldWebkit = 1;
-            }
-
-        });
-
-        parser.addListener("endrule", function(event) {
-            var missing = [];
-
-            if (!gradients.moz) {
-                missing.push("Firefox 3.6+");
-            }
-
-            if (!gradients.webkit) {
-                missing.push("Webkit (Safari 5+, Chrome)");
-            }
-
-            if (!gradients.oldWebkit) {
-                missing.push("Old Webkit (Safari 4+, Chrome)");
-            }
-
-            if (!gradients.o) {
-                missing.push("Opera 11.1+");
-            }
-
-            if (missing.length && missing.length < 4) {
-                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule);
-            }
-
-        });
-
-    }
-
-});
-
-/*
- * Rule: Don't use IDs for selectors.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "ids",
-    name: "Disallow IDs in selectors",
-    desc: "Selectors should not contain IDs.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-IDs-in-selectors",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                modifier,
-                idCount,
-                i, j, k;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-                idCount = 0;
-
-                for (j=0; j < selector.parts.length; j++) {
-                    part = selector.parts[j];
-                    if (part.type === parser.SELECTOR_PART_TYPE) {
-                        for (k=0; k < part.modifiers.length; k++) {
-                            modifier = part.modifiers[k];
-                            if (modifier.type === "id") {
-                                idCount++;
-                            }
-                        }
-                    }
-                }
-
-                if (idCount === 1) {
-                    reporter.report("Don't use IDs in selectors.", selector.line, selector.col, rule);
-                } else if (idCount > 1) {
-                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
-                }
-            }
-
-        });
-    }
-
-});
-
-/*
- * Rule: IE6-9 supports up to 31 stylesheet import.
- * Reference:
- * http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "import-ie-limit",
-    name: "@import limit on IE6-IE9",
-    desc: "IE6-9 supports up to 31 @import per stylesheet",
-    browsers: "IE6, IE7, IE8, IE9",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            MAX_IMPORT_COUNT = 31,
-            count = 0;
-
-        function startPage() {
-            count = 0;
-        }
-
-        parser.addListener("startpage", startPage);
-
-        parser.addListener("import", function() {
-            count++;
-        });
-
-        parser.addListener("endstylesheet", function() {
-            if (count > MAX_IMPORT_COUNT) {
-                reporter.rollupError(
-                    "Too many @import rules (" + count + "). IE6-9 supports up to 31 import per stylesheet.",
-                    rule
-                );
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Don't use @import, use <link> instead.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "import",
-    name: "Disallow @import",
-    desc: "Don't use @import, use <link> instead.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%40import",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("import", function(event) {
-            reporter.report("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
-        });
-
-    }
-
-});
-
-/*
- * Rule: Make sure !important is not overused, this could lead to specificity
- * war. Display a warning on !important declarations, an error if it's
- * used more at least 10 times.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "important",
-    name: "Disallow !important",
-    desc: "Be careful when using !important declaration",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%21important",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            count = 0;
-
-        // warn that important is used and increment the declaration counter
-        parser.addListener("property", function(event) {
-            if (event.important === true) {
-                count++;
-                reporter.report("Use of !important", event.line, event.col, rule);
-            }
-        });
-
-        // if there are more than 10, show an error
-        parser.addListener("endstylesheet", function() {
-            reporter.stat("important", count);
-            if (count >= 10) {
-                reporter.rollupWarn("Too many !important declarations (" + count + "), try to use less than 10 to avoid specificity issues.", rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Properties should be known (listed in CSS3 specification) or
- * be a vendor-prefixed property.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "known-properties",
-    name: "Require use of known properties",
-    desc: "Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-use-of-known-properties",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("property", function(event) {
-
-            // the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)
-            if (event.invalid) {
-                reporter.report(event.invalid.message, event.line, event.col, rule);
-            }
-
-        });
-    }
-
-});
-
-/*
- * Rule: All properties should be in alphabetical order.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "order-alphabetical",
-    name: "Alphabetical order",
-    desc: "Assure properties are in alphabetical order",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            properties;
-
-        var startRule = function () {
-            properties = [];
-        };
-
-        var endRule = function(event) {
-            var currentProperties = properties.join(","),
-                expectedProperties = properties.sort().join(",");
-
-            if (currentProperties !== expectedProperties) {
-                reporter.report("Rule doesn't have all its properties in alphabetical order.", event.line, event.col, rule);
-            }
-        };
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text,
-                lowerCasePrefixLessName = name.toLowerCase().replace(/^-.*?-/, "");
-
-            properties.push(lowerCasePrefixLessName);
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-        parser.addListener("endpage", endRule);
-        parser.addListener("endpagemargin", endRule);
-        parser.addListener("endkeyframerule", endRule);
-        parser.addListener("endviewport", endRule);
-    }
-
-});
-
-/*
- * Rule: outline: none or outline: 0 should only be used in a :focus rule
- *       and only if there are other properties in the same rule.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "outline-none",
-    name: "Disallow outline: none",
-    desc: "Use of outline: none or outline: 0 should be limited to :focus rules.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone",
-    browsers: "All",
-    tags: ["Accessibility"],
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            lastRule;
-
-        function startRule(event) {
-            if (event.selectors) {
-                lastRule = {
-                    line: event.line,
-                    col: event.col,
-                    selectors: event.selectors,
-                    propCount: 0,
-                    outline: false
-                };
-            } else {
-                lastRule = null;
-            }
-        }
-
-        function endRule() {
-            if (lastRule) {
-                if (lastRule.outline) {
-                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) {
-                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);
-                    } else if (lastRule.propCount === 1) {
-                        reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);
-                    }
-                }
-            }
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text.toLowerCase(),
-                value = event.value;
-
-            if (lastRule) {
-                lastRule.propCount++;
-                if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) {
-                    lastRule.outline = true;
-                }
-            }
-
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-        parser.addListener("endpage", endRule);
-        parser.addListener("endpagemargin", endRule);
-        parser.addListener("endkeyframerule", endRule);
-        parser.addListener("endviewport", endRule);
-
-    }
-
-});
-
-/*
- * Rule: Don't use classes or IDs with elements (a.foo or a#foo).
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "overqualified-elements",
-    name: "Disallow overqualified elements",
-    desc: "Don't use classes or IDs with elements (a.foo or a#foo).",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-overqualified-elements",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            classes = {};
-
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                modifier,
-                i, j, k;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-
-                for (j=0; j < selector.parts.length; j++) {
-                    part = selector.parts[j];
-                    if (part.type === parser.SELECTOR_PART_TYPE) {
-                        for (k=0; k < part.modifiers.length; k++) {
-                            modifier = part.modifiers[k];
-                            if (part.elementName && modifier.type === "id") {
-                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
-                            } else if (modifier.type === "class") {
-
-                                if (!classes[modifier]) {
-                                    classes[modifier] = [];
-                                }
-                                classes[modifier].push({
-                                    modifier: modifier,
-                                    part: part
-                                });
-                            }
-                        }
-                    }
-                }
-            }
-        });
-
-        parser.addListener("endstylesheet", function() {
-
-            var prop;
-            for (prop in classes) {
-                if (classes.hasOwnProperty(prop)) {
-
-                    // one use means that this is overqualified
-                    if (classes[prop].length === 1 && classes[prop][0].part.elementName) {
-                        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);
-                    }
-                }
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Headings (h1-h6) should not be qualified (namespaced).
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "qualified-headings",
-    name: "Disallow qualified headings",
-    desc: "Headings should not be qualified (namespaced).",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-qualified-headings",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                i, j;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-
-                for (j=0; j < selector.parts.length; j++) {
-                    part = selector.parts[j];
-                    if (part.type === parser.SELECTOR_PART_TYPE) {
-                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0) {
-                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Selectors that look like regular expressions are slow and should be avoided.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "regex-selectors",
-    name: "Disallow selectors that look like regexs",
-    desc: "Selectors that look like regular expressions are slow and should be avoided.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-selectors-that-look-like-regular-expressions",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                modifier,
-                i, j, k;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-                for (j=0; j < selector.parts.length; j++) {
-                    part = selector.parts[j];
-                    if (part.type === parser.SELECTOR_PART_TYPE) {
-                        for (k=0; k < part.modifiers.length; k++) {
-                            modifier = part.modifiers[k];
-                            if (modifier.type === "attribute") {
-                                if (/([~\|\^\$\*]=)/.test(modifier)) {
-                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
-                                }
-                            }
-
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Total number of rules should not exceed x.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "rules-count",
-    name: "Rules Count",
-    desc: "Track how many rules there are.",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var count = 0;
-
-        // count each rule
-        parser.addListener("startrule", function() {
-            count++;
-        });
-
-        parser.addListener("endstylesheet", function() {
-            reporter.stat("rule-count", count);
-        });
-    }
-
-});
-
-/*
- * Rule: Warn people with approaching the IE 4095 limit
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "selector-max-approaching",
-    name: "Warn when approaching the 4095 selector limit for IE",
-    desc: "Will warn when selector count is >= 3800 selectors.",
-    browsers: "IE",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this, count = 0;
-
-        parser.addListener("startrule", function(event) {
-            count += event.selectors.length;
-        });
-
-        parser.addListener("endstylesheet", function() {
-            if (count >= 3800) {
-                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Warn people past the IE 4095 limit
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "selector-max",
-    name: "Error when past the 4095 selector limit for IE",
-    desc: "Will error when selector count is > 4095.",
-    browsers: "IE",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this, count = 0;
-
-        parser.addListener("startrule", function(event) {
-            count += event.selectors.length;
-        });
-
-        parser.addListener("endstylesheet", function() {
-            if (count > 4095) {
-                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Avoid new-line characters in selectors.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "selector-newline",
-    name: "Disallow new-line characters in selectors",
-    desc: "New-line characters in selectors are usually a forgotten comma and not a descendant combinator.",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        function startRule(event) {
-            var i, len, selector, p, n, pLen, part, part2, type, currentLine, nextLine,
-                selectors = event.selectors;
-
-            for (i = 0, len = selectors.length; i < len; i++) {
-                selector = selectors[i];
-                for (p = 0, pLen = selector.parts.length; p < pLen; p++) {
-                    for (n = p + 1; n < pLen; n++) {
-                        part = selector.parts[p];
-                        part2 = selector.parts[n];
-                        type = part.type;
-                        currentLine = part.line;
-                        nextLine = part2.line;
-
-                        if (type === "descendant" && nextLine > currentLine) {
-                            reporter.report("newline character found in selector (forgot a comma?)", currentLine, selectors[i].parts[0].col, rule);
-                        }
-                    }
-                }
-
-            }
-        }
-
-        parser.addListener("startrule", startRule);
-
-    }
-});
-
-/*
- * Rule: Use shorthand properties where possible.
- *
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "shorthand",
-    name: "Require shorthand properties",
-    desc: "Use shorthand properties where possible.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-shorthand-properties",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            prop, i, len,
-            propertiesToCheck = {},
-            properties,
-            mapping = {
-                "margin": [
-                    "margin-top",
-                    "margin-bottom",
-                    "margin-left",
-                    "margin-right"
-                ],
-                "padding": [
-                    "padding-top",
-                    "padding-bottom",
-                    "padding-left",
-                    "padding-right"
-                ]
-            };
-
-        // initialize propertiesToCheck
-        for (prop in mapping) {
-            if (mapping.hasOwnProperty(prop)) {
-                for (i=0, len=mapping[prop].length; i < len; i++) {
-                    propertiesToCheck[mapping[prop][i]] = prop;
-                }
-            }
-        }
-
-        function startRule() {
-            properties = {};
-        }
-
-        // event handler for end of rules
-        function endRule(event) {
-
-            var prop, i, len, total;
-
-            // check which properties this rule has
-            for (prop in mapping) {
-                if (mapping.hasOwnProperty(prop)) {
-                    total=0;
-
-                    for (i=0, len=mapping[prop].length; i < len; i++) {
-                        total += properties[mapping[prop][i]] ? 1 : 0;
-                    }
-
-                    if (total === mapping[prop].length) {
-                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
-                    }
-                }
-            }
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-
-        // check for use of "font-size"
-        parser.addListener("property", function(event) {
-            var name = event.property.toString().toLowerCase();
-
-            if (propertiesToCheck[name]) {
-                properties[name] = 1;
-            }
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-
-    }
-
-});
-
-/*
- * Rule: Don't use properties with a star prefix.
- *
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "star-property-hack",
-    name: "Disallow properties with a star prefix",
-    desc: "Checks for the star property hack (targets IE6/7)",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-star-hack",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        // check if property name starts with "*"
-        parser.addListener("property", function(event) {
-            var property = event.property;
-
-            if (property.hack === "*") {
-                reporter.report("Property with star prefix found.", event.property.line, event.property.col, rule);
-            }
-        });
-    }
-});
-
-/*
- * Rule: Don't use text-indent for image replacement if you need to support rtl.
- *
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "text-indent",
-    name: "Disallow negative text-indent",
-    desc: "Checks for text indent less than -99px",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-negative-text-indent",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            textIndent,
-            direction;
-
-
-        function startRule() {
-            textIndent = false;
-            direction = "inherit";
-        }
-
-        // event handler for end of rules
-        function endRule() {
-            if (textIndent && direction !== "ltr") {
-                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);
-            }
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-
-        // check for use of "font-size"
-        parser.addListener("property", function(event) {
-            var name = event.property.toString().toLowerCase(),
-                value = event.value;
-
-            if (name === "text-indent" && value.parts[0].value < -99) {
-                textIndent = event.property;
-            } else if (name === "direction" && value.toString() === "ltr") {
-                direction = "ltr";
-            }
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-
-    }
-
-});
-
-/*
- * Rule: Don't use properties with a underscore prefix.
- *
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "underscore-property-hack",
-    name: "Disallow properties with an underscore prefix",
-    desc: "Checks for the underscore property hack (targets IE6)",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-underscore-hack",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        // check if property name starts with "_"
-        parser.addListener("property", function(event) {
-            var property = event.property;
-
-            if (property.hack === "_") {
-                reporter.report("Property with underscore prefix found.", event.property.line, event.property.col, rule);
-            }
-        });
-    }
-});
-
-/*
- * Rule: Headings (h1-h6) should be defined only once.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "unique-headings",
-    name: "Headings should only be defined once",
-    desc: "Headings should be defined only once.",
-    url: "https://github.com/CSSLint/csslint/wiki/Headings-should-only-be-defined-once",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        var headings = {
-            h1: 0,
-            h2: 0,
-            h3: 0,
-            h4: 0,
-            h5: 0,
-            h6: 0
-        };
-
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                pseudo,
-                i, j;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-                part = selector.parts[selector.parts.length-1];
-
-                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())) {
-
-                    for (j=0; j < part.modifiers.length; j++) {
-                        if (part.modifiers[j].type === "pseudo") {
-                            pseudo = true;
-                            break;
-                        }
-                    }
-
-                    if (!pseudo) {
-                        headings[RegExp.$1]++;
-                        if (headings[RegExp.$1] > 1) {
-                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
-                        }
-                    }
-                }
-            }
-        });
-
-        parser.addListener("endstylesheet", function() {
-            var prop,
-                messages = [];
-
-            for (prop in headings) {
-                if (headings.hasOwnProperty(prop)) {
-                    if (headings[prop] > 1) {
-                        messages.push(headings[prop] + " " + prop + "s");
-                    }
-                }
-            }
-
-            if (messages.length) {
-                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Don't use universal selector because it's slow.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "universal-selector",
-    name: "Disallow universal selector",
-    desc: "The universal selector (*) is known to be slow.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-universal-selector",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        parser.addListener("startrule", function(event) {
-            var selectors = event.selectors,
-                selector,
-                part,
-                i;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-
-                part = selector.parts[selector.parts.length-1];
-                if (part.elementName === "*") {
-                    reporter.report(rule.desc, part.line, part.col, rule);
-                }
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "unqualified-attributes",
-    name: "Disallow unqualified attribute selectors",
-    desc: "Unqualified attribute selectors are known to be slow.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-unqualified-attribute-selectors",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-
-        var rule = this;
-
-        parser.addListener("startrule", function(event) {
-
-            var selectors = event.selectors,
-                selectorContainsClassOrId = false,
-                selector,
-                part,
-                modifier,
-                i, k;
-
-            for (i=0; i < selectors.length; i++) {
-                selector = selectors[i];
-
-                part = selector.parts[selector.parts.length-1];
-                if (part.type === parser.SELECTOR_PART_TYPE) {
-                    for (k=0; k < part.modifiers.length; k++) {
-                        modifier = part.modifiers[k];
-
-                        if (modifier.type === "class" || modifier.type === "id") {
-                            selectorContainsClassOrId = true;
-                            break;
-                        }
-                    }
-
-                    if (!selectorContainsClassOrId) {
-                        for (k=0; k < part.modifiers.length; k++) {
-                            modifier = part.modifiers[k];
-                            if (modifier.type === "attribute" && (!part.elementName || part.elementName === "*")) {
-                                reporter.report(rule.desc, part.line, part.col, rule);
-                            }
-                        }
-                    }
-                }
-
-            }
-        });
-    }
-
-});
-
-/*
- * Rule: When using a vendor-prefixed property, make sure to
- * include the standard one.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "vendor-prefix",
-    name: "Require standard property with vendor prefix",
-    desc: "When using a vendor-prefixed property, make sure to include the standard one.",
-    url: "https://github.com/CSSLint/csslint/wiki/Require-standard-property-with-vendor-prefix",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this,
-            properties,
-            num,
-            propertiesToCheck = {
-                "-webkit-border-radius": "border-radius",
-                "-webkit-border-top-left-radius": "border-top-left-radius",
-                "-webkit-border-top-right-radius": "border-top-right-radius",
-                "-webkit-border-bottom-left-radius": "border-bottom-left-radius",
-                "-webkit-border-bottom-right-radius": "border-bottom-right-radius",
-
-                "-o-border-radius": "border-radius",
-                "-o-border-top-left-radius": "border-top-left-radius",
-                "-o-border-top-right-radius": "border-top-right-radius",
-                "-o-border-bottom-left-radius": "border-bottom-left-radius",
-                "-o-border-bottom-right-radius": "border-bottom-right-radius",
-
-                "-moz-border-radius": "border-radius",
-                "-moz-border-radius-topleft": "border-top-left-radius",
-                "-moz-border-radius-topright": "border-top-right-radius",
-                "-moz-border-radius-bottomleft": "border-bottom-left-radius",
-                "-moz-border-radius-bottomright": "border-bottom-right-radius",
-
-                "-moz-column-count": "column-count",
-                "-webkit-column-count": "column-count",
-
-                "-moz-column-gap": "column-gap",
-                "-webkit-column-gap": "column-gap",
-
-                "-moz-column-rule": "column-rule",
-                "-webkit-column-rule": "column-rule",
-
-                "-moz-column-rule-style": "column-rule-style",
-                "-webkit-column-rule-style": "column-rule-style",
-
-                "-moz-column-rule-color": "column-rule-color",
-                "-webkit-column-rule-color": "column-rule-color",
-
-                "-moz-column-rule-width": "column-rule-width",
-                "-webkit-column-rule-width": "column-rule-width",
-
-                "-moz-column-width": "column-width",
-                "-webkit-column-width": "column-width",
-
-                "-webkit-column-span": "column-span",
-                "-webkit-columns": "columns",
-
-                "-moz-box-shadow": "box-shadow",
-                "-webkit-box-shadow": "box-shadow",
-
-                "-moz-transform": "transform",
-                "-webkit-transform": "transform",
-                "-o-transform": "transform",
-                "-ms-transform": "transform",
-
-                "-moz-transform-origin": "transform-origin",
-                "-webkit-transform-origin": "transform-origin",
-                "-o-transform-origin": "transform-origin",
-                "-ms-transform-origin": "transform-origin",
-
-                "-moz-box-sizing": "box-sizing",
-                "-webkit-box-sizing": "box-sizing"
-            };
-
-        // event handler for beginning of rules
-        function startRule() {
-            properties = {};
-            num = 1;
-        }
-
-        // event handler for end of rules
-        function endRule() {
-            var prop,
-                i,
-                len,
-                needed,
-                actual,
-                needsStandard = [];
-
-            for (prop in properties) {
-                if (propertiesToCheck[prop]) {
-                    needsStandard.push({
-                        actual: prop,
-                        needed: propertiesToCheck[prop]
-                    });
-                }
-            }
-
-            for (i=0, len=needsStandard.length; i < len; i++) {
-                needed = needsStandard[i].needed;
-                actual = needsStandard[i].actual;
-
-                if (!properties[needed]) {
-                    reporter.report("Missing standard property '" + needed + "' to go along with '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
-                } else {
-                    // make sure standard property is last
-                    if (properties[needed][0].pos < properties[actual][0].pos) {
-                        reporter.report("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
-                    }
-                }
-            }
-
-        }
-
-        parser.addListener("startrule", startRule);
-        parser.addListener("startfontface", startRule);
-        parser.addListener("startpage", startRule);
-        parser.addListener("startpagemargin", startRule);
-        parser.addListener("startkeyframerule", startRule);
-        parser.addListener("startviewport", startRule);
-
-        parser.addListener("property", function(event) {
-            var name = event.property.text.toLowerCase();
-
-            if (!properties[name]) {
-                properties[name] = [];
-            }
-
-            properties[name].push({
-                name: event.property,
-                value: event.value,
-                pos: num++
-            });
-        });
-
-        parser.addListener("endrule", endRule);
-        parser.addListener("endfontface", endRule);
-        parser.addListener("endpage", endRule);
-        parser.addListener("endpagemargin", endRule);
-        parser.addListener("endkeyframerule", endRule);
-        parser.addListener("endviewport", endRule);
-    }
-
-});
-
-/*
- * Rule: You don't need to specify units when a value is 0.
- */
-
-CSSLint.addRule({
-
-    // rule information
-    id: "zero-units",
-    name: "Disallow units for 0 values",
-    desc: "You don't need to specify units when a value is 0.",
-    url: "https://github.com/CSSLint/csslint/wiki/Disallow-units-for-zero-values",
-    browsers: "All",
-
-    // initialization
-    init: function(parser, reporter) {
-        "use strict";
-        var rule = this;
-
-        // count how many times "float" is used
-        parser.addListener("property", function(event) {
-            var parts = event.value.parts,
-                i = 0,
-                len = parts.length;
-
-            while (i < len) {
-                if ((parts[i].units || parts[i].type === "percentage") && parts[i].value === 0 && parts[i].type !== "time") {
-                    reporter.report("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
-                }
-                i++;
-            }
-
-        });
-
-    }
-
-});
-
-(function() {
-    "use strict";
-
-    /**
-     * Replace special characters before write to output.
-     *
-     * Rules:
-     *  - single quotes is the escape sequence for double-quotes
-     *  - &amp; is the escape sequence for &
-     *  - &lt; is the escape sequence for <
-     *  - &gt; is the escape sequence for >
-     *
-     * @param {String} message to escape
-     * @return escaped message as {String}
-     */
-    var xmlEscape = function(str) {
-        if (!str || str.constructor !== String) {
-            return "";
-        }
-
-        return str.replace(/["&><]/g, function(match) {
-            switch (match) {
-                case "\"":
-                    return "&quot;";
-                case "&":
-                    return "&amp;";
-                case "<":
-                    return "&lt;";
-                case ">":
-                    return "&gt;";
-            }
-        });
-    };
-
-    CSSLint.addFormatter({
-        // format information
-        id: "checkstyle-xml",
-        name: "Checkstyle XML format",
-
-        /**
-         * Return opening root XML tag.
-         * @return {String} to prepend before all results
-         */
-        startFormat: function() {
-            return "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
-        },
-
-        /**
-         * Return closing root XML tag.
-         * @return {String} to append after all results
-         */
-        endFormat: function() {
-            return "</checkstyle>";
-        },
-
-        /**
-         * Returns message when there is a file read error.
-         * @param {String} filename The name of the file that caused the error.
-         * @param {String} message The error message
-         * @return {String} The error message.
-         */
-        readError: function(filename, message) {
-            return "<file name=\"" + xmlEscape(filename) + "\"><error line=\"0\" column=\"0\" severty=\"error\" message=\"" + xmlEscape(message) + "\"></error></file>";
-        },
-
-        /**
-         * Given CSS Lint results for a file, return output for this format.
-         * @param results {Object} with error and warning messages
-         * @param filename {String} relative file path
-         * @param options {Object} (UNUSED for now) specifies special handling of output
-         * @return {String} output for results
-         */
-        formatResults: function(results, filename/*, options*/) {
-            var messages = results.messages,
-                output = [];
-
-            /**
-             * Generate a source string for a rule.
-             * Checkstyle source strings usually resemble Java class names e.g
-             * net.csslint.SomeRuleName
-             * @param {Object} rule
-             * @return rule source as {String}
-             */
-            var generateSource = function(rule) {
-                if (!rule || !("name" in rule)) {
-                    return "";
-                }
-                return "net.csslint." + rule.name.replace(/\s/g, "");
-            };
-
-
-            if (messages.length > 0) {
-                output.push("<file name=\""+filename+"\">");
-                CSSLint.Util.forEach(messages, function (message) {
-                    // ignore rollups for now
-                    if (!message.rollup) {
-                        output.push("<error line=\"" + message.line + "\" column=\"" + message.col + "\" severity=\"" + message.type + "\"" +
-                          " message=\"" + xmlEscape(message.message) + "\" source=\"" + generateSource(message.rule) +"\"/>");
-                    }
-                });
-                output.push("</file>");
-            }
-
-            return output.join("");
-        }
-    });
-
-}());
-
-CSSLint.addFormatter({
-    // format information
-    id: "compact",
-    name: "Compact, 'porcelain' format",
-
-    /**
-     * Return content to be printed before all file results.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        return "";
-    },
-
-    /**
-     * Return content to be printed after all file results.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        return "";
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path
-     * @param options {Object} (Optional) specifies special handling of output
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename, options) {
-        "use strict";
-        var messages = results.messages,
-            output = "";
-        options = options || {};
-
-        /**
-         * Capitalize and return given string.
-         * @param str {String} to capitalize
-         * @return {String} capitalized
-         */
-        var capitalize = function(str) {
-            return str.charAt(0).toUpperCase() + str.slice(1);
-        };
-
-        if (messages.length === 0) {
-            return options.quiet ? "" : filename + ": Lint Free!";
-        }
-
-        CSSLint.Util.forEach(messages, function(message) {
-            if (message.rollup) {
-                output += filename + ": " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
-            } else {
-                output += filename + ": line " + message.line +
-                    ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
-            }
-        });
-
-        return output;
-    }
-});
-
-CSSLint.addFormatter({
-    // format information
-    id: "csslint-xml",
-    name: "CSSLint XML format",
-
-    /**
-     * Return opening root XML tag.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><csslint>";
-    },
-
-    /**
-     * Return closing root XML tag.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        return "</csslint>";
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path
-     * @param options {Object} (UNUSED for now) specifies special handling of output
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename/*, options*/) {
-        "use strict";
-        var messages = results.messages,
-            output = [];
-
-        /**
-         * Replace special characters before write to output.
-         *
-         * Rules:
-         *  - single quotes is the escape sequence for double-quotes
-         *  - &amp; is the escape sequence for &
-         *  - &lt; is the escape sequence for <
-         *  - &gt; is the escape sequence for >
-         *
-         * @param {String} message to escape
-         * @return escaped message as {String}
-         */
-        var escapeSpecialCharacters = function(str) {
-            if (!str || str.constructor !== String) {
-                return "";
-            }
-            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-        };
-
-        if (messages.length > 0) {
-            output.push("<file name=\""+filename+"\">");
-            CSSLint.Util.forEach(messages, function (message) {
-                if (message.rollup) {
-                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
-                } else {
-                    output.push("<issue line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
-                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
-                }
-            });
-            output.push("</file>");
-        }
-
-        return output.join("");
-    }
-});
-
-/* globals JSON: true */
-
-CSSLint.addFormatter({
-    // format information
-    id: "json",
-    name: "JSON",
-
-    /**
-     * Return content to be printed before all file results.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        this.json = [];
-        return "";
-    },
-
-    /**
-     * Return content to be printed after all file results.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        var ret = "";
-        if (this.json.length > 0) {
-            if (this.json.length === 1) {
-                ret = JSON.stringify(this.json[0]);
-            } else {
-                ret = JSON.stringify(this.json);
-            }
-        }
-        return ret;
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path (Unused)
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename, options) {
-        "use strict";
-        if (results.messages.length > 0 || !options.quiet) {
-            this.json.push({
-                filename: filename,
-                messages: results.messages,
-                stats: results.stats
-            });
-        }
-        return "";
-    }
-});
-
-CSSLint.addFormatter({
-    // format information
-    id: "junit-xml",
-    name: "JUNIT XML format",
-
-    /**
-     * Return opening root XML tag.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>";
-    },
-
-    /**
-     * Return closing root XML tag.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        return "</testsuites>";
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path
-     * @param options {Object} (UNUSED for now) specifies special handling of output
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename/*, options*/) {
-        "use strict";
-
-        var messages = results.messages,
-            output = [],
-            tests = {
-                "error": 0,
-                "failure": 0
-            };
-
-        /**
-         * Generate a source string for a rule.
-         * JUNIT source strings usually resemble Java class names e.g
-         * net.csslint.SomeRuleName
-         * @param {Object} rule
-         * @return rule source as {String}
-         */
-        var generateSource = function(rule) {
-            if (!rule || !("name" in rule)) {
-                return "";
-            }
-            return "net.csslint." + rule.name.replace(/\s/g, "");
-        };
-
-        /**
-         * Replace special characters before write to output.
-         *
-         * Rules:
-         *  - single quotes is the escape sequence for double-quotes
-         *  - &lt; is the escape sequence for <
-         *  - &gt; is the escape sequence for >
-         *
-         * @param {String} message to escape
-         * @return escaped message as {String}
-         */
-        var escapeSpecialCharacters = function(str) {
-
-            if (!str || str.constructor !== String) {
-                return "";
-            }
-
-            return str.replace(/"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-
-        };
-
-        if (messages.length > 0) {
-
-            messages.forEach(function (message) {
-
-                // since junit has no warning class
-                // all issues as errors
-                var type = message.type === "warning" ? "error" : message.type;
-
-                // ignore rollups for now
-                if (!message.rollup) {
-
-                    // build the test case separately, once joined
-                    // we'll add it to a custom array filtered by type
-                    output.push("<testcase time=\"0\" name=\"" + generateSource(message.rule) + "\">");
-                    output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\"><![CDATA[" + message.line + ":" + message.col + ":" + escapeSpecialCharacters(message.evidence) + "]]></" + type + ">");
-                    output.push("</testcase>");
-
-                    tests[type] += 1;
-
-                }
-
-            });
-
-            output.unshift("<testsuite time=\"0\" tests=\"" + messages.length + "\" skipped=\"0\" errors=\"" + tests.error + "\" failures=\"" + tests.failure + "\" package=\"net.csslint\" name=\"" + filename + "\">");
-            output.push("</testsuite>");
-
-        }
-
-        return output.join("");
-
-    }
-});
-
-CSSLint.addFormatter({
-    // format information
-    id: "lint-xml",
-    name: "Lint XML format",
-
-    /**
-     * Return opening root XML tag.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><lint>";
-    },
-
-    /**
-     * Return closing root XML tag.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        return "</lint>";
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path
-     * @param options {Object} (UNUSED for now) specifies special handling of output
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename/*, options*/) {
-        "use strict";
-        var messages = results.messages,
-            output = [];
-
-        /**
-         * Replace special characters before write to output.
-         *
-         * Rules:
-         *  - single quotes is the escape sequence for double-quotes
-         *  - &amp; is the escape sequence for &
-         *  - &lt; is the escape sequence for <
-         *  - &gt; is the escape sequence for >
-         *
-         * @param {String} message to escape
-         * @return escaped message as {String}
-         */
-        var escapeSpecialCharacters = function(str) {
-            if (!str || str.constructor !== String) {
-                return "";
-            }
-            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-        };
-
-        if (messages.length > 0) {
-
-            output.push("<file name=\""+filename+"\">");
-            CSSLint.Util.forEach(messages, function (message) {
-                if (message.rollup) {
-                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
-                } else {
-                    var rule = "";
-                    if (message.rule && message.rule.id) {
-                        rule = "rule=\"" + escapeSpecialCharacters(message.rule.id) + "\" ";
-                    }
-                    output.push("<issue " + rule + "line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
-                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
-                }
-            });
-            output.push("</file>");
-        }
-
-        return output.join("");
-    }
-});
-
-CSSLint.addFormatter({
-    // format information
-    id: "text",
-    name: "Plain Text",
-
-    /**
-     * Return content to be printed before all file results.
-     * @return {String} to prepend before all results
-     */
-    startFormat: function() {
-        "use strict";
-        return "";
-    },
-
-    /**
-     * Return content to be printed after all file results.
-     * @return {String} to append after all results
-     */
-    endFormat: function() {
-        "use strict";
-        return "";
-    },
-
-    /**
-     * Given CSS Lint results for a file, return output for this format.
-     * @param results {Object} with error and warning messages
-     * @param filename {String} relative file path
-     * @param options {Object} (Optional) specifies special handling of output
-     * @return {String} output for results
-     */
-    formatResults: function(results, filename, options) {
-        "use strict";
-        var messages = results.messages,
-            output = "";
-        options = options || {};
-
-        if (messages.length === 0) {
-            return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + ".";
-        }
-
-        output = "\n\ncsslint: There ";
-        if (messages.length === 1) {
-            output += "is 1 problem";
-        } else {
-            output += "are " + messages.length + " problems";
-        }
-        output += " in " + filename + ".";
-
-        var pos = filename.lastIndexOf("/"),
-            shortFilename = filename;
-
-        if (pos === -1) {
-            pos = filename.lastIndexOf("\\");
-        }
-        if (pos > -1) {
-            shortFilename = filename.substring(pos+1);
-        }
-
-        CSSLint.Util.forEach(messages, function (message, i) {
-            output = output + "\n\n" + shortFilename;
-            if (message.rollup) {
-                output += "\n" + (i+1) + ": " + message.type;
-                output += "\n" + message.message;
-            } else {
-                output += "\n" + (i+1) + ": " + message.type + " at line " + message.line + ", col " + message.col;
-                output += "\n" + message.message;
-                output += "\n" + message.evidence;
-            }
-        });
-
-        return output;
-    }
-});
-
-return CSSLint;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+},{"./css":22,"./util":28}]},{},[]);
+
+return require('parserlib');
+})();
+var clone = (function() {
+'use strict';
+
+var nativeMap;
+try {
+  nativeMap = Map;
+} catch(_) {
+  // maybe a reference error because no `Map`. Give it a dummy value that no
+  // value will ever be an instanceof.
+  nativeMap = function() {};
+}
+
+var nativeSet;
+try {
+  nativeSet = Set;
+} catch(_) {
+  nativeSet = function() {};
+}
+
+var nativePromise;
+try {
+  nativePromise = Promise;
+} catch(_) {
+  nativePromise = function() {};
+}
+
+/**
+ * Clones (copies) an Object using deep copying.
+ *
+ * This function supports circular references by default, but if you are certain
+ * there are no circular references in your object, you can save some CPU time
+ * by calling clone(obj, false).
+ *
+ * Caution: if `circular` is false and `parent` contains circular references,
+ * your program may enter an infinite loop and crash.
+ *
+ * @param `parent` - the object to be cloned
+ * @param `circular` - set to true if the object to be cloned may contain
+ *    circular references. (optional - true by default)
+ * @param `depth` - set to a number if the object is only to be cloned to
+ *    a particular depth. (optional - defaults to Infinity)
+ * @param `prototype` - sets the prototype to be used when cloning an object.
+ *    (optional - defaults to parent prototype).
+ * @param `includeNonEnumerable` - set to true if the non-enumerable properties
+ *    should be cloned as well. Non-enumerable properties on the prototype
+ *    chain will be ignored. (optional - false by default)
+*/
+function clone(parent, circular, depth, prototype, includeNonEnumerable) {
+  if (typeof circular === 'object') {
+    depth = circular.depth;
+    prototype = circular.prototype;
+    includeNonEnumerable = circular.includeNonEnumerable;
+    circular = circular.circular;
+  }
+  // maintain two arrays for circular references, where corresponding parents
+  // and children have the same index
+  var allParents = [];
+  var allChildren = [];
+
+  var useBuffer = typeof Buffer != 'undefined';
+
+  if (typeof circular == 'undefined')
+    circular = true;
+
+  if (typeof depth == 'undefined')
+    depth = Infinity;
+
+  // recurse this function so we don't reset allParents and allChildren
+  function _clone(parent, depth) {
+    // cloning null always returns null
+    if (parent === null)
+      return null;
+
+    if (depth === 0)
+      return parent;
+
+    var child;
+    var proto;
+    if (typeof parent != 'object') {
+      return parent;
+    }
+
+    if (parent instanceof nativeMap) {
+      child = new nativeMap();
+    } else if (parent instanceof nativeSet) {
+      child = new nativeSet();
+    } else if (parent instanceof nativePromise) {
+      child = new nativePromise(function (resolve, reject) {
+        parent.then(function(value) {
+          resolve(_clone(value, depth - 1));
+        }, function(err) {
+          reject(_clone(err, depth - 1));
+        });
+      });
+    } else if (clone.__isArray(parent)) {
+      child = [];
+    } else if (clone.__isRegExp(parent)) {
+      child = new RegExp(parent.source, __getRegExpFlags(parent));
+      if (parent.lastIndex) child.lastIndex = parent.lastIndex;
+    } else if (clone.__isDate(parent)) {
+      child = new Date(parent.getTime());
+    } else if (useBuffer && Buffer.isBuffer(parent)) {
+      child = new Buffer(parent.length);
+      parent.copy(child);
+      return child;
+    } else if (parent instanceof Error) {
+      child = Object.create(parent);
+    } else {
+      if (typeof prototype == 'undefined') {
+        proto = Object.getPrototypeOf(parent);
+        child = Object.create(proto);
+      }
+      else {
+        child = Object.create(prototype);
+        proto = prototype;
+      }
+    }
+
+    if (circular) {
+      var index = allParents.indexOf(parent);
+
+      if (index != -1) {
+        return allChildren[index];
+      }
+      allParents.push(parent);
+      allChildren.push(child);
+    }
+
+    if (parent instanceof nativeMap) {
+      var keyIterator = parent.keys();
+      while(true) {
+        var next = keyIterator.next();
+        if (next.done) {
+          break;
+        }
+        var keyChild = _clone(next.value, depth - 1);
+        var valueChild = _clone(parent.get(next.value), depth - 1);
+        child.set(keyChild, valueChild);
+      }
+    }
+    if (parent instanceof nativeSet) {
+      var iterator = parent.keys();
+      while(true) {
+        var next = iterator.next();
+        if (next.done) {
+          break;
+        }
+        var entryChild = _clone(next.value, depth - 1);
+        child.add(entryChild);
+      }
+    }
+
+    for (var i in parent) {
+      var attrs;
+      if (proto) {
+        attrs = Object.getOwnPropertyDescriptor(proto, i);
+      }
+
+      if (attrs && attrs.set == null) {
+        continue;
+      }
+      child[i] = _clone(parent[i], depth - 1);
+    }
+
+    if (Object.getOwnPropertySymbols) {
+      var symbols = Object.getOwnPropertySymbols(parent);
+      for (var i = 0; i < symbols.length; i++) {
+        // Don't need to worry about cloning a symbol because it is a primitive,
+        // like a number or string.
+        var symbol = symbols[i];
+        var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
+        if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
+          continue;
+        }
+        child[symbol] = _clone(parent[symbol], depth - 1);
+        if (!descriptor.enumerable) {
+          Object.defineProperty(child, symbol, {
+            enumerable: false
+          });
+        }
+      }
+    }
+
+    if (includeNonEnumerable) {
+      var allPropertyNames = Object.getOwnPropertyNames(parent);
+      for (var i = 0; i < allPropertyNames.length; i++) {
+        var propertyName = allPropertyNames[i];
+        var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
+        if (descriptor && descriptor.enumerable) {
+          continue;
+        }
+        child[propertyName] = _clone(parent[propertyName], depth - 1);
+        Object.defineProperty(child, propertyName, {
+          enumerable: false
+        });
+      }
+    }
+
+    return child;
+  }
+
+  return _clone(parent, depth);
+}
+
+/**
+ * Simple flat clone using prototype, accepts only objects, usefull for property
+ * override on FLAT configuration object (no nested props).
+ *
+ * USE WITH CAUTION! This may not behave as you wish if you do not know how this
+ * works.
+ */
+clone.clonePrototype = function clonePrototype(parent) {
+  if (parent === null)
+    return null;
+
+  var c = function () {};
+  c.prototype = parent;
+  return new c();
+};
+
+// private utility functions
+
+function __objToStr(o) {
+  return Object.prototype.toString.call(o);
+}
+clone.__objToStr = __objToStr;
+
+function __isDate(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object Date]';
+}
+clone.__isDate = __isDate;
+
+function __isArray(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object Array]';
+}
+clone.__isArray = __isArray;
+
+function __isRegExp(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
+}
+clone.__isRegExp = __isRegExp;
+
+function __getRegExpFlags(re) {
+  var flags = '';
+  if (re.global) flags += 'g';
+  if (re.ignoreCase) flags += 'i';
+  if (re.multiline) flags += 'm';
+  return flags;
+}
+clone.__getRegExpFlags = __getRegExpFlags;
+
+return clone;
+})();
+
+if (typeof module === 'object' && module.exports) {
+  module.exports = clone;
+}
+
+/**
+ * Main CSSLint object.
+ * @class CSSLint
+ * @static
+ * @extends parserlib.util.EventTarget
+ */
+
+/* global parserlib, clone, Reporter */
+/* exported CSSLint */
+
+var CSSLint = (function() {
+    "use strict";
+
+    var rules           = [],
+        formatters      = [],
+        embeddedRuleset = /\/\*\s*csslint([^\*]*)\*\//,
+        api             = new parserlib.util.EventTarget();
+
+    api.version = "1.0.4";
+
+    //-------------------------------------------------------------------------
+    // Rule Management
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new rule to the engine.
+     * @param {Object} rule The rule to add.
+     * @method addRule
+     */
+    api.addRule = function(rule) {
+        rules.push(rule);
+        rules[rule.id] = rule;
+    };
+
+    /**
+     * Clears all rule from the engine.
+     * @method clearRules
+     */
+    api.clearRules = function() {
+        rules = [];
+    };
+
+    /**
+     * Returns the rule objects.
+     * @return An array of rule objects.
+     * @method getRules
+     */
+    api.getRules = function() {
+        return [].concat(rules).sort(function(a, b) {
+            return a.id > b.id ? 1 : 0;
+        });
+    };
+
+    /**
+     * Returns a ruleset configuration object with all current rules.
+     * @return A ruleset object.
+     * @method getRuleset
+     */
+    api.getRuleset = function() {
+        var ruleset = {},
+            i = 0,
+            len = rules.length;
+
+        while (i < len) {
+            ruleset[rules[i++].id] = 1;    // by default, everything is a warning
+        }
+
+        return ruleset;
+    };
+
+    /**
+     * Returns a ruleset object based on embedded rules.
+     * @param {String} text A string of css containing embedded rules.
+     * @param {Object} ruleset A ruleset object to modify.
+     * @return {Object} A ruleset object.
+     * @method getEmbeddedRuleset
+     */
+    function applyEmbeddedRuleset(text, ruleset) {
+        var valueMap,
+            embedded = text && text.match(embeddedRuleset),
+            rules = embedded && embedded[1];
+
+        if (rules) {
+            valueMap = {
+                "true": 2,  // true is error
+                "": 1,      // blank is warning
+                "false": 0, // false is ignore
+
+                "2": 2,     // explicit error
+                "1": 1,     // explicit warning
+                "0": 0      // explicit ignore
+            };
+
+            rules.toLowerCase().split(",").forEach(function(rule) {
+                var pair = rule.split(":"),
+                    property = pair[0] || "",
+                    value = pair[1] || "";
+
+                ruleset[property.trim()] = valueMap[value.trim()];
+            });
+        }
+
+        return ruleset;
+    }
+
+    //-------------------------------------------------------------------------
+    // Formatters
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new formatter to the engine.
+     * @param {Object} formatter The formatter to add.
+     * @method addFormatter
+     */
+    api.addFormatter = function(formatter) {
+        // formatters.push(formatter);
+        formatters[formatter.id] = formatter;
+    };
+
+    /**
+     * Retrieves a formatter for use.
+     * @param {String} formatId The name of the format to retrieve.
+     * @return {Object} The formatter or undefined.
+     * @method getFormatter
+     */
+    api.getFormatter = function(formatId) {
+        return formatters[formatId];
+    };
+
+    /**
+     * Formats the results in a particular format for a single file.
+     * @param {Object} result The results returned from CSSLint.verify().
+     * @param {String} filename The filename for which the results apply.
+     * @param {String} formatId The name of the formatter to use.
+     * @param {Object} options (Optional) for special output handling.
+     * @return {String} A formatted string for the results.
+     * @method format
+     */
+    api.format = function(results, filename, formatId, options) {
+        var formatter = this.getFormatter(formatId),
+            result = null;
+
+        if (formatter) {
+            result = formatter.startFormat();
+            result += formatter.formatResults(results, filename, options || {});
+            result += formatter.endFormat();
+        }
+
+        return result;
+    };
+
+    /**
+     * Indicates if the given format is supported.
+     * @param {String} formatId The ID of the format to check.
+     * @return {Boolean} True if the format exists, false if not.
+     * @method hasFormat
+     */
+    api.hasFormat = function(formatId) {
+        return formatters.hasOwnProperty(formatId);
+    };
+
+    //-------------------------------------------------------------------------
+    // Verification
+    //-------------------------------------------------------------------------
+
+    /**
+     * Starts the verification process for the given CSS text.
+     * @param {String} text The CSS text to verify.
+     * @param {Object} ruleset (Optional) List of rules to apply. If null, then
+     *      all rules are used. If a rule has a value of 1 then it's a warning,
+     *      a value of 2 means it's an error.
+     * @return {Object} Results of the verification.
+     * @method verify
+     */
+    api.verify = function(text, ruleset) {
+
+        var i = 0,
+            reporter,
+            lines,
+            allow = {},
+            ignore = [],
+            report,
+            parser = new parserlib.css.Parser({
+                starHack: true,
+                ieFilters: true,
+                underscoreHack: true,
+                strict: false
+            });
+
+        // normalize line endings
+        lines = text.replace(/\n\r?/g, "$split$").split("$split$");
+
+        // find 'allow' comments
+        CSSLint.Util.forEach(lines, function (line, lineno) {
+            var allowLine = line && line.match(/\/\*[ \t]*csslint[ \t]+allow:[ \t]*([^\*]*)\*\//i),
+                allowRules = allowLine && allowLine[1],
+                allowRuleset = {};
+
+            if (allowRules) {
+                allowRules.toLowerCase().split(",").forEach(function(allowRule) {
+                    allowRuleset[allowRule.trim()] = true;
+                });
+                if (Object.keys(allowRuleset).length > 0) {
+                    allow[lineno + 1] = allowRuleset;
+                }
+            }
+        });
+
+        var ignoreStart = null,
+            ignoreEnd = null;
+        CSSLint.Util.forEach(lines, function (line, lineno) {
+            // Keep oldest, "unclosest" ignore:start
+            if (ignoreStart === null && line.match(/\/\*[ \t]*csslint[ \t]+ignore:start[ \t]*\*\//i)) {
+                ignoreStart = lineno;
+            }
+
+            if (line.match(/\/\*[ \t]*csslint[ \t]+ignore:end[ \t]*\*\//i)) {
+                ignoreEnd = lineno;
+            }
+
+            if (ignoreStart !== null && ignoreEnd !== null) {
+                ignore.push([ignoreStart, ignoreEnd]);
+                ignoreStart = ignoreEnd = null;
+            }
+        });
+
+        // Close remaining ignore block, if any
+        if (ignoreStart !== null) {
+            ignore.push([ignoreStart, lines.length]);
+        }
+
+        if (!ruleset) {
+            ruleset = this.getRuleset();
+        }
+
+        if (embeddedRuleset.test(text)) {
+            // defensively copy so that caller's version does not get modified
+            ruleset = clone(ruleset);
+            ruleset = applyEmbeddedRuleset(text, ruleset);
+        }
+
+        reporter = new Reporter(lines, ruleset, allow, ignore);
+
+        ruleset.errors = 2;       // always report parsing errors as errors
+        for (i in ruleset) {
+            if (ruleset.hasOwnProperty(i) && ruleset[i]) {
+                if (rules[i]) {
+                    rules[i].init(parser, reporter);
+                }
+            }
+        }
+
+
+        // capture most horrible error type
+        try {
+            parser.parse(text);
+        } catch (ex) {
+            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});
+        }
+
+        report = {
+            messages    : reporter.messages,
+            stats       : reporter.stats,
+            ruleset     : reporter.ruleset,
+            allow       : reporter.allow,
+            ignore      : reporter.ignore
+        };
+
+        // sort by line numbers, rollups at the bottom
+        report.messages.sort(function (a, b) {
+            if (a.rollup && !b.rollup) {
+                return 1;
+            } else if (!a.rollup && b.rollup) {
+                return -1;
+            } else {
+                return a.line - b.line;
+            }
+        });
+
+        return report;
+    };
+
+    //-------------------------------------------------------------------------
+    // Publish the API
+    //-------------------------------------------------------------------------
+
+    return api;
+
+})();
+
+/**
+ * An instance of Report is used to report results of the
+ * verification back to the main API.
+ * @class Reporter
+ * @constructor
+ * @param {String[]} lines The text lines of the source.
+ * @param {Object} ruleset The set of rules to work with, including if
+ *      they are errors or warnings.
+ * @param {Object} explicitly allowed lines
+ * @param {[][]} ingore list of line ranges to be ignored
+ */
+function Reporter(lines, ruleset, allow, ignore) {
+    "use strict";
+
+    /**
+     * List of messages being reported.
+     * @property messages
+     * @type String[]
+     */
+    this.messages = [];
+
+    /**
+     * List of statistics being reported.
+     * @property stats
+     * @type String[]
+     */
+    this.stats = [];
+
+    /**
+     * Lines of code being reported on. Used to provide contextual information
+     * for messages.
+     * @property lines
+     * @type String[]
+     */
+    this.lines = lines;
+
+    /**
+     * Information about the rules. Used to determine whether an issue is an
+     * error or warning.
+     * @property ruleset
+     * @type Object
+     */
+    this.ruleset = ruleset;
+
+    /**
+     * Lines with specific rule messages to leave out of the report.
+     * @property allow
+     * @type Object
+     */
+    this.allow = allow;
+    if (!this.allow) {
+        this.allow = {};
+    }
+
+    /**
+     * Linesets not to include in the report.
+     * @property ignore
+     * @type [][]
+     */
+    this.ignore = ignore;
+    if (!this.ignore) {
+        this.ignore = [];
+    }
+}
+
+Reporter.prototype = {
+
+    // restore constructor
+    constructor: Reporter,
+
+    /**
+     * Report an error.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method error
+     */
+    error: function(message, line, col, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "error",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule || {}
+        });
+    },
+
+    /**
+     * Report an warning.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method warn
+     * @deprecated Use report instead.
+     */
+    warn: function(message, line, col, rule) {
+        "use strict";
+        this.report(message, line, col, rule);
+    },
+
+    /**
+     * Report an issue.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method report
+     */
+    report: function(message, line, col, rule) {
+        "use strict";
+
+        // Check if rule violation should be allowed
+        if (this.allow.hasOwnProperty(line) && this.allow[line].hasOwnProperty(rule.id)) {
+            return;
+        }
+
+        var ignore = false;
+        CSSLint.Util.forEach(this.ignore, function (range) {
+            if (range[0] <= line && line <= range[1]) {
+                ignore = true;
+            }
+        });
+        if (ignore) {
+            return;
+        }
+
+        this.messages.push({
+            type    : this.ruleset[rule.id] === 2 ? "error" : "warning",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some informational text.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method info
+     */
+    info: function(message, line, col, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "info",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some rollup error information.
+     * @param {String} message The message to store.
+     * @param {Object} rule The rule this message relates to.
+     * @method rollupError
+     */
+    rollupError: function(message, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "error",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some rollup warning information.
+     * @param {String} message The message to store.
+     * @param {Object} rule The rule this message relates to.
+     * @method rollupWarn
+     */
+    rollupWarn: function(message, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "warning",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report a statistic.
+     * @param {String} name The name of the stat to store.
+     * @param {Variant} value The value of the stat.
+     * @method stat
+     */
+    stat: function(name, value) {
+        "use strict";
+        this.stats[name] = value;
+    }
+};
+
+// expose for testing purposes
+CSSLint._Reporter = Reporter;
+
+/*
+ * Utility functions that make life easier.
+ */
+CSSLint.Util = {
+    /*
+     * Adds all properties from supplier onto receiver,
+     * overwriting if the same name already exists on
+     * receiver.
+     * @param {Object} The object to receive the properties.
+     * @param {Object} The object to provide the properties.
+     * @return {Object} The receiver
+     */
+    mix: function(receiver, supplier) {
+        "use strict";
+        var prop;
+
+        for (prop in supplier) {
+            if (supplier.hasOwnProperty(prop)) {
+                receiver[prop] = supplier[prop];
+            }
+        }
+
+        return prop;
+    },
+
+    /*
+     * Polyfill for array indexOf() method.
+     * @param {Array} values The array to search.
+     * @param {Variant} value The value to search for.
+     * @return {int} The index of the value if found, -1 if not.
+     */
+    indexOf: function(values, value) {
+        "use strict";
+        if (values.indexOf) {
+            return values.indexOf(value);
+        } else {
+            for (var i=0, len=values.length; i < len; i++) {
+                if (values[i] === value) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    },
+
+    /*
+     * Polyfill for array forEach() method.
+     * @param {Array} values The array to operate on.
+     * @param {Function} func The function to call on each item.
+     * @return {void}
+     */
+    forEach: function(values, func) {
+        "use strict";
+        if (values.forEach) {
+            return values.forEach(func);
+        } else {
+            for (var i=0, len=values.length; i < len; i++) {
+                func(values[i], i, values);
+            }
+        }
+    }
+};
+
+/*
+ * Rule: Don't use adjoining classes (.foo.bar).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "adjoining-classes",
+    name: "Disallow adjoining classes",
+    desc: "Don't use adjoining classes.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-adjoining-classes",
+    browsers: "IE6",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                classCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        classCount = 0;
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "class") {
+                                classCount++;
+                            }
+                            if (classCount > 1){
+                                reporter.report("Adjoining classes: "+selectors[i].text, part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use width or height when using padding or border.
+ */
+CSSLint.addRule({
+
+    // rule information
+    id: "box-model",
+    name: "Beware of broken box size",
+    desc: "Don't use width or height when using padding or border.",
+    url: "https://github.com/CSSLint/csslint/wiki/Beware-of-box-model-size",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            widthProperties = {
+                border: 1,
+                "border-left": 1,
+                "border-right": 1,
+                padding: 1,
+                "padding-left": 1,
+                "padding-right": 1
+            },
+            heightProperties = {
+                border: 1,
+                "border-bottom": 1,
+                "border-top": 1,
+                padding: 1,
+                "padding-bottom": 1,
+                "padding-top": 1
+            },
+            properties,
+            boxSizing = false;
+
+        function startRule() {
+            properties = {};
+            boxSizing = false;
+        }
+
+        function endRule() {
+            var prop, value;
+
+            if (!boxSizing) {
+                if (properties.height) {
+                    for (prop in heightProperties) {
+                        if (heightProperties.hasOwnProperty(prop) && properties[prop]) {
+                            value = properties[prop].value;
+                            // special case for padding
+                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[0].value === 0)) {
+                                reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+
+                if (properties.width) {
+                    for (prop in widthProperties) {
+                        if (widthProperties.hasOwnProperty(prop) && properties[prop]) {
+                            value = properties[prop].value;
+
+                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[1].value === 0)) {
+                                reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (heightProperties[name] || widthProperties[name]) {
+                if (!/^0\S*$/.test(event.value) && !(name === "border" && event.value.toString() === "none")) {
+                    properties[name] = {
+                        line: event.property.line,
+                        col: event.property.col,
+                        value: event.value
+                    };
+                }
+            } else {
+                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)) {
+                    properties[name] = 1;
+                } else if (name === "box-sizing") {
+                    boxSizing = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: box-sizing doesn't work in IE6 and IE7.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "box-sizing",
+    name: "Disallow use of box-sizing",
+    desc: "The box-sizing properties isn't supported in IE6 and IE7.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-box-sizing",
+    browsers: "IE6, IE7",
+    tags: ["Compatibility"],
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (name === "box-sizing") {
+                reporter.report("The box-sizing property isn't supported in IE6 and IE7.", event.line, event.col, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Use the bulletproof @font-face syntax to avoid 404's in old IE
+ * (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax)
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "bulletproof-font-face",
+    name: "Use the bulletproof @font-face syntax",
+    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).",
+    url: "https://github.com/CSSLint/csslint/wiki/Bulletproof-font-face",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            fontFaceRule = false,
+            firstSrc = true,
+            ruleFailed = false,
+            line, col;
+
+        // Mark the start of a @font-face declaration so we only test properties inside it
+        parser.addListener("startfontface", function() {
+            fontFaceRule = true;
+        });
+
+        parser.addListener("property", function(event) {
+            // If we aren't inside an @font-face declaration then just return
+            if (!fontFaceRule) {
+                return;
+            }
+
+            var propertyName = event.property.toString().toLowerCase(),
+                value = event.value.toString();
+
+            // Set the line and col numbers for use in the endfontface listener
+            line = event.line;
+            col = event.col;
+
+            // This is the property that we care about, we can ignore the rest
+            if (propertyName === "src") {
+                var regex = /^\s?url\(['"].+\.eot\?.*['"]\)\s*format\(['"]embedded-opentype['"]\).*$/i;
+
+                // We need to handle the advanced syntax with two src properties
+                if (!value.match(regex) && firstSrc) {
+                    ruleFailed = true;
+                    firstSrc = false;
+                } else if (value.match(regex) && !firstSrc) {
+                    ruleFailed = false;
+                }
+            }
+
+
+        });
+
+        // Back to normal rules that we don't need to test
+        parser.addListener("endfontface", function() {
+            fontFaceRule = false;
+
+            if (ruleFailed) {
+                reporter.report("@font-face declaration doesn't follow the fontspring bulletproof syntax.", line, col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Include all compatible vendor prefixes to reach a wider
+ * range of users.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "compatible-vendor-prefixes",
+    name: "Require compatible vendor prefixes",
+    desc: "Include all compatible vendor prefixes to reach a wider range of users.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-compatible-vendor-prefixes",
+    browsers: "All",
+
+    // initialization
+    init: function (parser, reporter) {
+        "use strict";
+        var rule = this,
+            compatiblePrefixes,
+            properties,
+            prop,
+            variations,
+            prefixed,
+            i,
+            len,
+            inKeyFrame = false,
+            arrayPush = Array.prototype.push,
+            applyTo = [];
+
+        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details
+        compatiblePrefixes = {
+            "animation"                  : "webkit",
+            "animation-delay"            : "webkit",
+            "animation-direction"        : "webkit",
+            "animation-duration"         : "webkit",
+            "animation-fill-mode"        : "webkit",
+            "animation-iteration-count"  : "webkit",
+            "animation-name"             : "webkit",
+            "animation-play-state"       : "webkit",
+            "animation-timing-function"  : "webkit",
+            "appearance"                 : "webkit moz",
+            "border-end"                 : "webkit moz",
+            "border-end-color"           : "webkit moz",
+            "border-end-style"           : "webkit moz",
+            "border-end-width"           : "webkit moz",
+            "border-image"               : "webkit moz o",
+            "border-radius"              : "webkit",
+            "border-start"               : "webkit moz",
+            "border-start-color"         : "webkit moz",
+            "border-start-style"         : "webkit moz",
+            "border-start-width"         : "webkit moz",
+            "box-align"                  : "webkit moz ms",
+            "box-direction"              : "webkit moz ms",
+            "box-flex"                   : "webkit moz ms",
+            "box-lines"                  : "webkit ms",
+            "box-ordinal-group"          : "webkit moz ms",
+            "box-orient"                 : "webkit moz ms",
+            "box-pack"                   : "webkit moz ms",
+            "box-sizing"                 : "",
+            "box-shadow"                 : "",
+            "column-count"               : "webkit moz ms",
+            "column-gap"                 : "webkit moz ms",
+            "column-rule"                : "webkit moz ms",
+            "column-rule-color"          : "webkit moz ms",
+            "column-rule-style"          : "webkit moz ms",
+            "column-rule-width"          : "webkit moz ms",
+            "column-width"               : "webkit moz ms",
+            "hyphens"                    : "epub moz",
+            "line-break"                 : "webkit ms",
+            "margin-end"                 : "webkit moz",
+            "margin-start"               : "webkit moz",
+            "marquee-speed"              : "webkit wap",
+            "marquee-style"              : "webkit wap",
+            "padding-end"                : "webkit moz",
+            "padding-start"              : "webkit moz",
+            "tab-size"                   : "moz o",
+            "text-size-adjust"           : "webkit ms",
+            "transform"                  : "webkit ms",
+            "transform-origin"           : "webkit ms",
+            "transition"                 : "",
+            "transition-delay"           : "",
+            "transition-duration"        : "",
+            "transition-property"        : "",
+            "transition-timing-function" : "",
+            "user-modify"                : "webkit moz",
+            "user-select"                : "webkit moz ms",
+            "word-break"                 : "epub ms",
+            "writing-mode"               : "epub ms"
+        };
+
+
+        for (prop in compatiblePrefixes) {
+            if (compatiblePrefixes.hasOwnProperty(prop)) {
+                variations = [];
+                prefixed = compatiblePrefixes[prop].split(" ");
+                for (i = 0, len = prefixed.length; i < len; i++) {
+                    variations.push("-" + prefixed[i] + "-" + prop);
+                }
+                compatiblePrefixes[prop] = variations;
+                arrayPush.apply(applyTo, variations);
+            }
+        }
+
+        parser.addListener("startrule", function () {
+            properties = [];
+        });
+
+        parser.addListener("startkeyframes", function (event) {
+            inKeyFrame = event.prefix || true;
+        });
+
+        parser.addListener("endkeyframes", function () {
+            inKeyFrame = false;
+        });
+
+        parser.addListener("property", function (event) {
+            var name = event.property;
+            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {
+
+                // e.g., -moz-transform is okay to be alone in @-moz-keyframes
+                if (!inKeyFrame || typeof inKeyFrame !== "string" ||
+                        name.text.indexOf("-" + inKeyFrame + "-") !== 0) {
+                    properties.push(name);
+                }
+            }
+        });
+
+        parser.addListener("endrule", function () {
+            if (!properties.length) {
+                return;
+            }
+
+            var propertyGroups = {},
+                i,
+                len,
+                name,
+                prop,
+                variations,
+                value,
+                full,
+                actual,
+                item,
+                propertiesSpecified;
+
+            for (i = 0, len = properties.length; i < len; i++) {
+                name = properties[i];
+
+                for (prop in compatiblePrefixes) {
+                    if (compatiblePrefixes.hasOwnProperty(prop)) {
+                        variations = compatiblePrefixes[prop];
+                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {
+                            if (!propertyGroups[prop]) {
+                                propertyGroups[prop] = {
+                                    full: variations.slice(0),
+                                    actual: [],
+                                    actualNodes: []
+                                };
+                            }
+                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {
+                                propertyGroups[prop].actual.push(name.text);
+                                propertyGroups[prop].actualNodes.push(name);
+                            }
+                        }
+                    }
+                }
+            }
+
+            for (prop in propertyGroups) {
+                if (propertyGroups.hasOwnProperty(prop)) {
+                    value = propertyGroups[prop];
+                    full = value.full;
+                    actual = value.actual;
+
+                    if (full.length > actual.length) {
+                        for (i = 0, len = full.length; i < len; i++) {
+                            item = full[i];
+                            if (CSSLint.Util.indexOf(actual, item) === -1) {
+                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length === 2) ? actual.join(" and ") : actual.join(", ");
+                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule);
+                            }
+                        }
+
+                    }
+                }
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Certain properties don't play well with certain display values.
+ * - float should not be used with inline-block
+ * - height, width, margin-top, margin-bottom, float should not be used with inline
+ * - vertical-align should not be used with block
+ * - margin, float should not be used with table-*
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "display-property-grouping",
+    name: "Require properties appropriate for display",
+    desc: "Certain properties shouldn't be used with certain display property values.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-properties-appropriate-for-display",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        var propertiesToCheck = {
+                display: 1,
+                "float": "none",
+                height: 1,
+                width: 1,
+                margin: 1,
+                "margin-left": 1,
+                "margin-right": 1,
+                "margin-bottom": 1,
+                "margin-top": 1,
+                padding: 1,
+                "padding-left": 1,
+                "padding-right": 1,
+                "padding-bottom": 1,
+                "padding-top": 1,
+                "vertical-align": 1
+            },
+            properties;
+
+        function reportProperty(name, display, msg) {
+            if (properties[name]) {
+                if (typeof propertiesToCheck[name] !== "string" || properties[name].value.toLowerCase() !== propertiesToCheck[name]) {
+                    reporter.report(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
+                }
+            }
+        }
+
+        function startRule() {
+            properties = {};
+        }
+
+        function endRule() {
+
+            var display = properties.display ? properties.display.value : null;
+            if (display) {
+                switch (display) {
+
+                    case "inline":
+                        // height, width, margin-top, margin-bottom, float should not be used with inline
+                        reportProperty("height", display);
+                        reportProperty("width", display);
+                        reportProperty("margin", display);
+                        reportProperty("margin-top", display);
+                        reportProperty("margin-bottom", display);
+                        reportProperty("float", display, "display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");
+                        break;
+
+                    case "block":
+                        // vertical-align should not be used with block
+                        reportProperty("vertical-align", display);
+                        break;
+
+                    case "inline-block":
+                        // float should not be used with inline-block
+                        reportProperty("float", display);
+                        break;
+
+                    default:
+                        // margin, float should not be used with table
+                        if (display.indexOf("table-") === 0) {
+                            reportProperty("margin", display);
+                            reportProperty("margin-left", display);
+                            reportProperty("margin-right", display);
+                            reportProperty("margin-top", display);
+                            reportProperty("margin-bottom", display);
+                            reportProperty("float", display);
+                        }
+
+                        // otherwise do nothing
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (propertiesToCheck[name]) {
+                properties[name] = {
+                    value: event.value.text,
+                    line: event.property.line,
+                    col: event.property.col
+                };
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endviewport", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Disallow duplicate background-images (using url).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "duplicate-background-images",
+    name: "Disallow duplicate background images",
+    desc: "Every background-image should be unique. Use a common class for e.g. sprites.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-background-images",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            stack = {};
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text,
+                value = event.value,
+                i, len;
+
+            if (name.match(/background/i)) {
+                for (i=0, len=value.parts.length; i < len; i++) {
+                    if (value.parts[i].type === "uri") {
+                        if (typeof stack[value.parts[i].uri] === "undefined") {
+                            stack[value.parts[i].uri] = event;
+                        } else {
+                            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);
+                        }
+                    }
+                }
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Duplicate properties must appear one after the other. If an already-defined
+ * property appears somewhere else in the rule, then it's likely an error.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "duplicate-properties",
+    name: "Disallow duplicate properties",
+    desc: "Duplicate properties must appear one after the other.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties,
+            lastProperty;
+
+        function startRule() {
+            properties = {};
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var property = event.property,
+                name = property.text.toLowerCase();
+
+            if (properties[name] && (lastProperty !== name || properties[name] === event.value.text)) {
+                reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
+            }
+
+            properties[name] = event.value.text;
+            lastProperty = name;
+
+        });
+
+
+    }
+
+});
+
+/*
+ * Rule: Style rules without any properties defined should be removed.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "empty-rules",
+    name: "Disallow empty rules",
+    desc: "Rules without any properties specified should be removed.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-empty-rules",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        parser.addListener("startrule", function() {
+            count=0;
+        });
+
+        parser.addListener("property", function() {
+            count++;
+        });
+
+        parser.addListener("endrule", function(event) {
+            var selectors = event.selectors;
+            if (count === 0) {
+                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: There should be no syntax errors. (Duh.)
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "errors",
+    name: "Parsing Errors",
+    desc: "This rule looks for recoverable syntax errors.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("error", function(event) {
+            reporter.error(event.message, event.line, event.col, rule);
+        });
+
+    }
+
+});
+
+CSSLint.addRule({
+
+    // rule information
+    id: "fallback-colors",
+    name: "Require fallback colors",
+    desc: "For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-fallback-colors",
+    browsers: "IE6,IE7,IE8",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            lastProperty,
+            propertiesToCheck = {
+                color: 1,
+                background: 1,
+                "border-color": 1,
+                "border-top-color": 1,
+                "border-right-color": 1,
+                "border-bottom-color": 1,
+                "border-left-color": 1,
+                border: 1,
+                "border-top": 1,
+                "border-right": 1,
+                "border-bottom": 1,
+                "border-left": 1,
+                "background-color": 1
+            };
+
+        function startRule() {
+            lastProperty = null;
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var property = event.property,
+                name = property.text.toLowerCase(),
+                parts = event.value.parts,
+                i = 0,
+                colorType = "",
+                len = parts.length;
+
+            if (propertiesToCheck[name]) {
+                while (i < len) {
+                    if (parts[i].type === "color") {
+                        if ("alpha" in parts[i] || "hue" in parts[i]) {
+
+                            if (/([^\)]+)\(/.test(parts[i])) {
+                                colorType = RegExp.$1.toUpperCase();
+                            }
+
+                            if (!lastProperty || (lastProperty.property.text.toLowerCase() !== name || lastProperty.colorType !== "compat")) {
+                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
+                            }
+                        } else {
+                            event.colorType = "compat";
+                        }
+                    }
+
+                    i++;
+                }
+            }
+
+            lastProperty = event;
+        });
+
+    }
+
+});
+
+/*
+ * Rule: You shouldn't use more than 10 floats. If you do, there's probably
+ * room for some abstraction.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "floats",
+    name: "Disallow too many floats",
+    desc: "This rule tests if the float property is used too many times",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-too-many-floats",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        var count = 0;
+
+        // count how many times "float" is used
+        parser.addListener("property", function(event) {
+            if (event.property.text.toLowerCase() === "float" &&
+                    event.value.text.toLowerCase() !== "none") {
+                count++;
+            }
+        });
+
+        // report the results
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("floats", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many floats (" + count + "), you're probably using them for layout. Consider using a grid system instead.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Avoid too many @font-face declarations in the same stylesheet.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "font-faces",
+    name: "Don't use too many web fonts",
+    desc: "Too many different web fonts in the same stylesheet.",
+    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-web-fonts",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+
+        parser.addListener("startfontface", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > 5) {
+                reporter.rollupWarn("Too many @font-face declarations (" + count + ").", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: You shouldn't need more than 9 font-size declarations.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "font-sizes",
+    name: "Disallow too many font sizes",
+    desc: "Checks the number of font-size declarations.",
+    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-font-size-declarations",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            if (event.property.toString() === "font-size") {
+                count++;
+            }
+        });
+
+        // report the results
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("font-sizes", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many font-size declarations (" + count + "), abstraction needed.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: When using a vendor-prefixed gradient, make sure to use them all.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "gradients",
+    name: "Require all gradient definitions",
+    desc: "When using a vendor-prefixed gradient, make sure to use them all.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-all-gradient-definitions",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            gradients;
+
+        parser.addListener("startrule", function() {
+            gradients = {
+                moz: 0,
+                webkit: 0,
+                oldWebkit: 0,
+                o: 0
+            };
+        });
+
+        parser.addListener("property", function(event) {
+
+            if (/\-(moz|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)) {
+                gradients[RegExp.$1] = 1;
+            } else if (/\-webkit\-gradient/i.test(event.value)) {
+                gradients.oldWebkit = 1;
+            }
+
+        });
+
+        parser.addListener("endrule", function(event) {
+            var missing = [];
+
+            if (!gradients.moz) {
+                missing.push("Firefox 3.6+");
+            }
+
+            if (!gradients.webkit) {
+                missing.push("Webkit (Safari 5+, Chrome)");
+            }
+
+            if (!gradients.oldWebkit) {
+                missing.push("Old Webkit (Safari 4+, Chrome)");
+            }
+
+            if (!gradients.o) {
+                missing.push("Opera 11.1+");
+            }
+
+            if (missing.length && missing.length < 4) {
+                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule);
+            }
+
+        });
+
+    }
+
+});
+
+/*
+ * Rule: Don't use IDs for selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "ids",
+    name: "Disallow IDs in selectors",
+    desc: "Selectors should not contain IDs.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-IDs-in-selectors",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                idCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                idCount = 0;
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "id") {
+                                idCount++;
+                            }
+                        }
+                    }
+                }
+
+                if (idCount === 1) {
+                    reporter.report("Don't use IDs in selectors.", selector.line, selector.col, rule);
+                } else if (idCount > 1) {
+                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
+                }
+            }
+
+        });
+    }
+
+});
+
+/*
+ * Rule: IE6-9 supports up to 31 stylesheet import.
+ * Reference:
+ * http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "import-ie-limit",
+    name: "@import limit on IE6-IE9",
+    desc: "IE6-9 supports up to 31 @import per stylesheet",
+    browsers: "IE6, IE7, IE8, IE9",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            MAX_IMPORT_COUNT = 31,
+            count = 0;
+
+        function startPage() {
+            count = 0;
+        }
+
+        parser.addListener("startpage", startPage);
+
+        parser.addListener("import", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > MAX_IMPORT_COUNT) {
+                reporter.rollupError(
+                    "Too many @import rules (" + count + "). IE6-9 supports up to 31 import per stylesheet.",
+                    rule
+                );
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use @import, use <link> instead.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "import",
+    name: "Disallow @import",
+    desc: "Don't use @import, use <link> instead.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%40import",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("import", function(event) {
+            reporter.report("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
+        });
+
+    }
+
+});
+
+/*
+ * Rule: Make sure !important is not overused, this could lead to specificity
+ * war. Display a warning on !important declarations, an error if it's
+ * used more at least 10 times.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "important",
+    name: "Disallow !important",
+    desc: "Be careful when using !important declaration",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%21important",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        // warn that important is used and increment the declaration counter
+        parser.addListener("property", function(event) {
+            if (event.important === true) {
+                count++;
+                reporter.report("Use of !important", event.line, event.col, rule);
+            }
+        });
+
+        // if there are more than 10, show an error
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("important", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many !important declarations (" + count + "), try to use less than 10 to avoid specificity issues.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Properties should be known (listed in CSS3 specification) or
+ * be a vendor-prefixed property.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "known-properties",
+    name: "Require use of known properties",
+    desc: "Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-use-of-known-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("property", function(event) {
+
+            // the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)
+            if (event.invalid) {
+                reporter.report(event.invalid.message, event.line, event.col, rule);
+            }
+
+        });
+    }
+
+});
+
+/*
+ * Rule: All properties should be in alphabetical order.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "order-alphabetical",
+    name: "Alphabetical order",
+    desc: "Assure properties are in alphabetical order",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties;
+
+        var startRule = function () {
+            properties = [];
+        };
+
+        var endRule = function(event) {
+            var currentProperties = properties.join(","),
+                expectedProperties = properties.sort().join(",");
+
+            if (currentProperties !== expectedProperties) {
+                reporter.report("Rule doesn't have all its properties in alphabetical order.", event.line, event.col, rule);
+            }
+        };
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text,
+                lowerCasePrefixLessName = name.toLowerCase().replace(/^-.*?-/, "");
+
+            properties.push(lowerCasePrefixLessName);
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: outline: none or outline: 0 should only be used in a :focus rule
+ *       and only if there are other properties in the same rule.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "outline-none",
+    name: "Disallow outline: none",
+    desc: "Use of outline: none or outline: 0 should be limited to :focus rules.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone",
+    browsers: "All",
+    tags: ["Accessibility"],
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            lastRule;
+
+        function startRule(event) {
+            if (event.selectors) {
+                lastRule = {
+                    line: event.line,
+                    col: event.col,
+                    selectors: event.selectors,
+                    propCount: 0,
+                    outline: false
+                };
+            } else {
+                lastRule = null;
+            }
+        }
+
+        function endRule() {
+            if (lastRule) {
+                if (lastRule.outline) {
+                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) {
+                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);
+                    } else if (lastRule.propCount === 1) {
+                        reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase(),
+                value = event.value;
+
+            if (lastRule) {
+                lastRule.propCount++;
+                if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) {
+                    lastRule.outline = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use classes or IDs with elements (a.foo or a#foo).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "overqualified-elements",
+    name: "Disallow overqualified elements",
+    desc: "Don't use classes or IDs with elements (a.foo or a#foo).",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-overqualified-elements",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            classes = {};
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (part.elementName && modifier.type === "id") {
+                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
+                            } else if (modifier.type === "class") {
+
+                                if (!classes[modifier]) {
+                                    classes[modifier] = [];
+                                }
+                                classes[modifier].push({
+                                    modifier: modifier,
+                                    part: part
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+        });
+
+        parser.addListener("endstylesheet", function() {
+
+            var prop;
+            for (prop in classes) {
+                if (classes.hasOwnProperty(prop)) {
+
+                    // one use means that this is overqualified
+                    if (classes[prop].length === 1 && classes[prop][0].part.elementName) {
+                        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);
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Headings (h1-h6) should not be qualified (namespaced).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "qualified-headings",
+    name: "Disallow qualified headings",
+    desc: "Headings should not be qualified (namespaced).",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-qualified-headings",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                i, j;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0) {
+                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Selectors that look like regular expressions are slow and should be avoided.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "regex-selectors",
+    name: "Disallow selectors that look like regexs",
+    desc: "Selectors that look like regular expressions are slow and should be avoided.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-selectors-that-look-like-regular-expressions",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "attribute") {
+                                if (/([~\|\^\$\*]=)/.test(modifier)) {
+                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
+                                }
+                            }
+
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Total number of rules should not exceed x.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "rules-count",
+    name: "Rules Count",
+    desc: "Track how many rules there are.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var count = 0;
+
+        // count each rule
+        parser.addListener("startrule", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("rule-count", count);
+        });
+    }
+
+});
+
+/*
+ * Rule: Warn people with approaching the IE 4095 limit
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-max-approaching",
+    name: "Warn when approaching the 4095 selector limit for IE",
+    desc: "Will warn when selector count is >= 3800 selectors.",
+    browsers: "IE",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this, count = 0;
+
+        parser.addListener("startrule", function(event) {
+            count += event.selectors.length;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count >= 3800) {
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Warn people past the IE 4095 limit
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-max",
+    name: "Error when past the 4095 selector limit for IE",
+    desc: "Will error when selector count is > 4095.",
+    browsers: "IE",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this, count = 0;
+
+        parser.addListener("startrule", function(event) {
+            count += event.selectors.length;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > 4095) {
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Avoid new-line characters in selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-newline",
+    name: "Disallow new-line characters in selectors",
+    desc: "New-line characters in selectors are usually a forgotten comma and not a descendant combinator.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        function startRule(event) {
+            var i, len, selector, p, n, pLen, part, part2, type, currentLine, nextLine,
+                selectors = event.selectors;
+
+            for (i = 0, len = selectors.length; i < len; i++) {
+                selector = selectors[i];
+                for (p = 0, pLen = selector.parts.length; p < pLen; p++) {
+                    for (n = p + 1; n < pLen; n++) {
+                        part = selector.parts[p];
+                        part2 = selector.parts[n];
+                        type = part.type;
+                        currentLine = part.line;
+                        nextLine = part2.line;
+
+                        if (type === "descendant" && nextLine > currentLine) {
+                            reporter.report("newline character found in selector (forgot a comma?)", currentLine, selectors[i].parts[0].col, rule);
+                        }
+                    }
+                }
+
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+
+    }
+});
+
+/*
+ * Rule: Use shorthand properties where possible.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "shorthand",
+    name: "Require shorthand properties",
+    desc: "Use shorthand properties where possible.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-shorthand-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            prop, i, len,
+            propertiesToCheck = {},
+            properties,
+            mapping = {
+                "margin": [
+                    "margin-top",
+                    "margin-bottom",
+                    "margin-left",
+                    "margin-right"
+                ],
+                "padding": [
+                    "padding-top",
+                    "padding-bottom",
+                    "padding-left",
+                    "padding-right"
+                ]
+            };
+
+        // initialize propertiesToCheck
+        for (prop in mapping) {
+            if (mapping.hasOwnProperty(prop)) {
+                for (i=0, len=mapping[prop].length; i < len; i++) {
+                    propertiesToCheck[mapping[prop][i]] = prop;
+                }
+            }
+        }
+
+        function startRule() {
+            properties = {};
+        }
+
+        // event handler for end of rules
+        function endRule(event) {
+
+            var prop, i, len, total;
+
+            // check which properties this rule has
+            for (prop in mapping) {
+                if (mapping.hasOwnProperty(prop)) {
+                    total=0;
+
+                    for (i=0, len=mapping[prop].length; i < len; i++) {
+                        total += properties[mapping[prop][i]] ? 1 : 0;
+                    }
+
+                    if (total === mapping[prop].length) {
+                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            var name = event.property.toString().toLowerCase();
+
+            if (propertiesToCheck[name]) {
+                properties[name] = 1;
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use properties with a star prefix.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "star-property-hack",
+    name: "Disallow properties with a star prefix",
+    desc: "Checks for the star property hack (targets IE6/7)",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-star-hack",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // check if property name starts with "*"
+        parser.addListener("property", function(event) {
+            var property = event.property;
+
+            if (property.hack === "*") {
+                reporter.report("Property with star prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Don't use text-indent for image replacement if you need to support rtl.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "text-indent",
+    name: "Disallow negative text-indent",
+    desc: "Checks for text indent less than -99px",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-negative-text-indent",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            textIndent,
+            direction;
+
+
+        function startRule() {
+            textIndent = false;
+            direction = "inherit";
+        }
+
+        // event handler for end of rules
+        function endRule() {
+            if (textIndent && direction !== "ltr") {
+                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);
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            var name = event.property.toString().toLowerCase(),
+                value = event.value;
+
+            if (name === "text-indent" && value.parts[0].value < -99) {
+                textIndent = event.property;
+            } else if (name === "direction" && value.toString() === "ltr") {
+                direction = "ltr";
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use properties with a underscore prefix.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "underscore-property-hack",
+    name: "Disallow properties with an underscore prefix",
+    desc: "Checks for the underscore property hack (targets IE6)",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-underscore-hack",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // check if property name starts with "_"
+        parser.addListener("property", function(event) {
+            var property = event.property;
+
+            if (property.hack === "_") {
+                reporter.report("Property with underscore prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Headings (h1-h6) should be defined only once.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "unique-headings",
+    name: "Headings should only be defined once",
+    desc: "Headings should be defined only once.",
+    url: "https://github.com/CSSLint/csslint/wiki/Headings-should-only-be-defined-once",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        var headings = {
+            h1: 0,
+            h2: 0,
+            h3: 0,
+            h4: 0,
+            h5: 0,
+            h6: 0
+        };
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                pseudo,
+                i, j;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                part = selector.parts[selector.parts.length-1];
+
+                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())) {
+
+                    for (j=0; j < part.modifiers.length; j++) {
+                        if (part.modifiers[j].type === "pseudo") {
+                            pseudo = true;
+                            break;
+                        }
+                    }
+
+                    if (!pseudo) {
+                        headings[RegExp.$1]++;
+                        if (headings[RegExp.$1] > 1) {
+                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+
+        parser.addListener("endstylesheet", function() {
+            var prop,
+                messages = [];
+
+            for (prop in headings) {
+                if (headings.hasOwnProperty(prop)) {
+                    if (headings[prop] > 1) {
+                        messages.push(headings[prop] + " " + prop + "s");
+                    }
+                }
+            }
+
+            if (messages.length) {
+                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use universal selector because it's slow.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "universal-selector",
+    name: "Disallow universal selector",
+    desc: "The universal selector (*) is known to be slow.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-universal-selector",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                i;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.elementName === "*") {
+                    reporter.report(rule.desc, part.line, part.col, rule);
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "unqualified-attributes",
+    name: "Disallow unqualified attribute selectors",
+    desc: "Unqualified attribute selectors are known to be slow.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-unqualified-attribute-selectors",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+
+            var selectors = event.selectors,
+                selectorContainsClassOrId = false,
+                selector,
+                part,
+                modifier,
+                i, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.type === parser.SELECTOR_PART_TYPE) {
+                    for (k=0; k < part.modifiers.length; k++) {
+                        modifier = part.modifiers[k];
+
+                        if (modifier.type === "class" || modifier.type === "id") {
+                            selectorContainsClassOrId = true;
+                            break;
+                        }
+                    }
+
+                    if (!selectorContainsClassOrId) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "attribute" && (!part.elementName || part.elementName === "*")) {
+                                reporter.report(rule.desc, part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: When using a vendor-prefixed property, make sure to
+ * include the standard one.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "vendor-prefix",
+    name: "Require standard property with vendor prefix",
+    desc: "When using a vendor-prefixed property, make sure to include the standard one.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-standard-property-with-vendor-prefix",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties,
+            num,
+            propertiesToCheck = {
+                "-webkit-border-radius": "border-radius",
+                "-webkit-border-top-left-radius": "border-top-left-radius",
+                "-webkit-border-top-right-radius": "border-top-right-radius",
+                "-webkit-border-bottom-left-radius": "border-bottom-left-radius",
+                "-webkit-border-bottom-right-radius": "border-bottom-right-radius",
+
+                "-o-border-radius": "border-radius",
+                "-o-border-top-left-radius": "border-top-left-radius",
+                "-o-border-top-right-radius": "border-top-right-radius",
+                "-o-border-bottom-left-radius": "border-bottom-left-radius",
+                "-o-border-bottom-right-radius": "border-bottom-right-radius",
+
+                "-moz-border-radius": "border-radius",
+                "-moz-border-radius-topleft": "border-top-left-radius",
+                "-moz-border-radius-topright": "border-top-right-radius",
+                "-moz-border-radius-bottomleft": "border-bottom-left-radius",
+                "-moz-border-radius-bottomright": "border-bottom-right-radius",
+
+                "-moz-column-count": "column-count",
+                "-webkit-column-count": "column-count",
+
+                "-moz-column-gap": "column-gap",
+                "-webkit-column-gap": "column-gap",
+
+                "-moz-column-rule": "column-rule",
+                "-webkit-column-rule": "column-rule",
+
+                "-moz-column-rule-style": "column-rule-style",
+                "-webkit-column-rule-style": "column-rule-style",
+
+                "-moz-column-rule-color": "column-rule-color",
+                "-webkit-column-rule-color": "column-rule-color",
+
+                "-moz-column-rule-width": "column-rule-width",
+                "-webkit-column-rule-width": "column-rule-width",
+
+                "-moz-column-width": "column-width",
+                "-webkit-column-width": "column-width",
+
+                "-webkit-column-span": "column-span",
+                "-webkit-columns": "columns",
+
+                "-moz-box-shadow": "box-shadow",
+                "-webkit-box-shadow": "box-shadow",
+
+                "-moz-transform": "transform",
+                "-webkit-transform": "transform",
+                "-o-transform": "transform",
+                "-ms-transform": "transform",
+
+                "-moz-transform-origin": "transform-origin",
+                "-webkit-transform-origin": "transform-origin",
+                "-o-transform-origin": "transform-origin",
+                "-ms-transform-origin": "transform-origin",
+
+                "-moz-box-sizing": "box-sizing",
+                "-webkit-box-sizing": "box-sizing"
+            };
+
+        // event handler for beginning of rules
+        function startRule() {
+            properties = {};
+            num = 1;
+        }
+
+        // event handler for end of rules
+        function endRule() {
+            var prop,
+                i,
+                len,
+                needed,
+                actual,
+                needsStandard = [];
+
+            for (prop in properties) {
+                if (propertiesToCheck[prop]) {
+                    needsStandard.push({
+                        actual: prop,
+                        needed: propertiesToCheck[prop]
+                    });
+                }
+            }
+
+            for (i=0, len=needsStandard.length; i < len; i++) {
+                needed = needsStandard[i].needed;
+                actual = needsStandard[i].actual;
+
+                if (!properties[needed]) {
+                    reporter.report("Missing standard property '" + needed + "' to go along with '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                } else {
+                    // make sure standard property is last
+                    if (properties[needed][0].pos < properties[actual][0].pos) {
+                        reporter.report("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                    }
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (!properties[name]) {
+                properties[name] = [];
+            }
+
+            properties[name].push({
+                name: event.property,
+                value: event.value,
+                pos: num++
+            });
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: You don't need to specify units when a value is 0.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "zero-units",
+    name: "Disallow units for 0 values",
+    desc: "You don't need to specify units when a value is 0.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-units-for-zero-values",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // count how many times "float" is used
+        parser.addListener("property", function(event) {
+            var parts = event.value.parts,
+                i = 0,
+                len = parts.length;
+
+            while (i < len) {
+                if ((parts[i].units || parts[i].type === "percentage") && parts[i].value === 0 && parts[i].type !== "time") {
+                    reporter.report("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
+                }
+                i++;
+            }
+
+        });
+
+    }
+
+});
+
+(function() {
+    "use strict";
+
+    /**
+     * Replace special characters before write to output.
+     *
+     * Rules:
+     *  - single quotes is the escape sequence for double-quotes
+     *  - &amp; is the escape sequence for &
+     *  - &lt; is the escape sequence for <
+     *  - &gt; is the escape sequence for >
+     *
+     * @param {String} message to escape
+     * @return escaped message as {String}
+     */
+    var xmlEscape = function(str) {
+        if (!str || str.constructor !== String) {
+            return "";
+        }
+
+        return str.replace(/["&><]/g, function(match) {
+            switch (match) {
+                case "\"":
+                    return "&quot;";
+                case "&":
+                    return "&amp;";
+                case "<":
+                    return "&lt;";
+                case ">":
+                    return "&gt;";
+            }
+        });
+    };
+
+    CSSLint.addFormatter({
+        // format information
+        id: "checkstyle-xml",
+        name: "Checkstyle XML format",
+
+        /**
+         * Return opening root XML tag.
+         * @return {String} to prepend before all results
+         */
+        startFormat: function() {
+            return "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
+        },
+
+        /**
+         * Return closing root XML tag.
+         * @return {String} to append after all results
+         */
+        endFormat: function() {
+            return "</checkstyle>";
+        },
+
+        /**
+         * Returns message when there is a file read error.
+         * @param {String} filename The name of the file that caused the error.
+         * @param {String} message The error message
+         * @return {String} The error message.
+         */
+        readError: function(filename, message) {
+            return "<file name=\"" + xmlEscape(filename) + "\"><error line=\"0\" column=\"0\" severty=\"error\" message=\"" + xmlEscape(message) + "\"></error></file>";
+        },
+
+        /**
+         * Given CSS Lint results for a file, return output for this format.
+         * @param results {Object} with error and warning messages
+         * @param filename {String} relative file path
+         * @param options {Object} (UNUSED for now) specifies special handling of output
+         * @return {String} output for results
+         */
+        formatResults: function(results, filename/*, options*/) {
+            var messages = results.messages,
+                output = [];
+
+            /**
+             * Generate a source string for a rule.
+             * Checkstyle source strings usually resemble Java class names e.g
+             * net.csslint.SomeRuleName
+             * @param {Object} rule
+             * @return rule source as {String}
+             */
+            var generateSource = function(rule) {
+                if (!rule || !("name" in rule)) {
+                    return "";
+                }
+                return "net.csslint." + rule.name.replace(/\s/g, "");
+            };
+
+
+            if (messages.length > 0) {
+                output.push("<file name=\""+filename+"\">");
+                CSSLint.Util.forEach(messages, function (message) {
+                    // ignore rollups for now
+                    if (!message.rollup) {
+                        output.push("<error line=\"" + message.line + "\" column=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                          " message=\"" + xmlEscape(message.message) + "\" source=\"" + generateSource(message.rule) +"\"/>");
+                    }
+                });
+                output.push("</file>");
+            }
+
+            return output.join("");
+        }
+    });
+
+}());
+
+CSSLint.addFormatter({
+    // format information
+    id: "compact",
+    name: "Compact, 'porcelain' format",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        /**
+         * Capitalize and return given string.
+         * @param str {String} to capitalize
+         * @return {String} capitalized
+         */
+        var capitalize = function(str) {
+            return str.charAt(0).toUpperCase() + str.slice(1);
+        };
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : filename + ": Lint Free!";
+        }
+
+        CSSLint.Util.forEach(messages, function(message) {
+            if (message.rollup) {
+                output += filename + ": " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
+            } else {
+                output += filename + ": line " + message.line +
+                    ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
+            }
+        });
+
+        return output;
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "csslint-xml",
+    name: "CSSLint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><csslint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</csslint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &amp; is the escape sequence for &
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    output.push("<issue line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+
+/* globals JSON: true */
+
+CSSLint.addFormatter({
+    // format information
+    id: "json",
+    name: "JSON",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        this.json = [];
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        var ret = "";
+        if (this.json.length > 0) {
+            if (this.json.length === 1) {
+                ret = JSON.stringify(this.json[0]);
+            } else {
+                ret = JSON.stringify(this.json);
+            }
+        }
+        return ret;
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path (Unused)
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        if (results.messages.length > 0 || !options.quiet) {
+            this.json.push({
+                filename: filename,
+                messages: results.messages,
+                stats: results.stats
+            });
+        }
+        return "";
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "junit-xml",
+    name: "JUNIT XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</testsuites>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+
+        var messages = results.messages,
+            output = [],
+            tests = {
+                "error": 0,
+                "failure": 0
+            };
+
+        /**
+         * Generate a source string for a rule.
+         * JUNIT source strings usually resemble Java class names e.g
+         * net.csslint.SomeRuleName
+         * @param {Object} rule
+         * @return rule source as {String}
+         */
+        var generateSource = function(rule) {
+            if (!rule || !("name" in rule)) {
+                return "";
+            }
+            return "net.csslint." + rule.name.replace(/\s/g, "");
+        };
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+
+            return str.replace(/"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+
+        };
+
+        if (messages.length > 0) {
+
+            messages.forEach(function (message) {
+
+                // since junit has no warning class
+                // all issues as errors
+                var type = message.type === "warning" ? "error" : message.type;
+
+                // ignore rollups for now
+                if (!message.rollup) {
+
+                    // build the test case separately, once joined
+                    // we'll add it to a custom array filtered by type
+                    output.push("<testcase time=\"0\" name=\"" + generateSource(message.rule) + "\">");
+                    output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\"><![CDATA[" + message.line + ":" + message.col + ":" + escapeSpecialCharacters(message.evidence) + "]]></" + type + ">");
+                    output.push("</testcase>");
+
+                    tests[type] += 1;
+
+                }
+
+            });
+
+            output.unshift("<testsuite time=\"0\" tests=\"" + messages.length + "\" skipped=\"0\" errors=\"" + tests.error + "\" failures=\"" + tests.failure + "\" package=\"net.csslint\" name=\"" + filename + "\">");
+            output.push("</testsuite>");
+
+        }
+
+        return output.join("");
+
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "lint-xml",
+    name: "Lint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><lint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</lint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &amp; is the escape sequence for &
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    var rule = "";
+                    if (message.rule && message.rule.id) {
+                        rule = "rule=\"" + escapeSpecialCharacters(message.rule.id) + "\" ";
+                    }
+                    output.push("<issue " + rule + "line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "text",
+    name: "Plain Text",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + ".";
+        }
+
+        output = "\n\ncsslint: There ";
+        if (messages.length === 1) {
+            output += "is 1 problem";
+        } else {
+            output += "are " + messages.length + " problems";
+        }
+        output += " in " + filename + ".";
+
+        var pos = filename.lastIndexOf("/"),
+            shortFilename = filename;
+
+        if (pos === -1) {
+            pos = filename.lastIndexOf("\\");
+        }
+        if (pos > -1) {
+            shortFilename = filename.substring(pos+1);
+        }
+
+        CSSLint.Util.forEach(messages, function (message, i) {
+            output = output + "\n\n" + shortFilename;
+            if (message.rollup) {
+                output += "\n" + (i+1) + ": " + message.type;
+                output += "\n" + message.message;
+            } else {
+                output += "\n" + (i+1) + ": " + message.type + " at line " + message.line + ", col " + message.col;
+                output += "\n" + message.message;
+                output += "\n" + message.evidence;
+            }
+        });
+
+        return output;
+    }
+});
+
+return CSSLint;
</ins><span class="cx" style="display: block; padding: 0 10px"> })();
</span><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>