diff --git a/lib/ace/mode/css/csslint.js b/lib/ace/mode/css/csslint.js index 02d1ba15..9f4c3bc8 100644 --- a/lib/ace/mode/css/csslint.js +++ b/lib/ace/mode/css/csslint.js @@ -22,8 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 12-September-2012 01:46:26 */ - +/* Build time: 17-January-2013 10:55:01 */ /*! Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -47,7 +46,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v0.1.9, Build time: 23-July-2012 10:52:31 */ +/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */ var parserlib = {}; (function(){ @@ -934,7 +933,7 @@ TokenStreamBase : TokenStreamBase })(); -/* +/* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -957,7 +956,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v0.1.9, Build time: 23-July-2012 10:52:31 */ +/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1106,7 +1105,36 @@ var Colors = { white :"#ffffff", whitesmoke :"#f5f5f5", yellow :"#ffff00", - yellowgreen :"#9acd32" + yellowgreen :"#9acd32", + //CSS2 system colors http://www.w3.org/TR/css3-color/#css2-system + activeBorder :"Active window border.", + activecaption :"Active window caption.", + appworkspace :"Background color of multiple document interface.", + background :"Desktop background.", + buttonface :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonhighlight :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonshadow :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttontext :"Text on push buttons.", + captiontext :"Text in caption, size box, and scrollbar arrow box.", + graytext :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.", + highlight :"Item(s) selected in a control.", + highlighttext :"Text of item(s) selected in a control.", + inactiveborder :"Inactive window border.", + inactivecaption :"Inactive window caption.", + inactivecaptiontext :"Color of text in an inactive caption.", + infobackground :"Background color for tooltip controls.", + infotext :"Text color for tooltip controls.", + menu :"Menu background.", + menutext :"Text in menus.", + scrollbar :"Scroll bar gray area.", + threeddarkshadow :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedface :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedhighlight :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedlightshadow :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedshadow :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + window :"Window background.", + windowframe :"Window frame.", + windowtext :"Text in windows." }; /*global SyntaxUnit, Parser*/ /** @@ -1195,7 +1223,7 @@ MediaFeature.prototype.constructor = MediaFeature; */ function MediaQuery(modifier, mediaType, features, line, col){ - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") @@ -1934,18 +1962,21 @@ Parser.prototype = function(){ }); }, - _operator: function(){ + _operator: function(inFunction){ /* - * operator + * operator (outside function) * : '/' S* | ',' S* | /( empty )/ + * operator (inside function) + * : '/' S* | '+' S* | '*' S* | '-' S* /( empty )/ * ; */ var tokenStream = this._tokenStream, token = null; - if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){ + if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) || + (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){ token = tokenStream.token(); this._readWhitespace(); } @@ -2556,7 +2587,7 @@ Parser.prototype = function(){ while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, - Tokens.RESOLUTION])){ + Tokens.RESOLUTION, Tokens.SLASH])){ value += tokenStream.token().value; value += this._readWhitespace(); @@ -2732,7 +2763,7 @@ Parser.prototype = function(){ return result; }, - _expr: function(){ + _expr: function(inFunction){ /* * expr * : term [ operator term ]* @@ -2741,7 +2772,7 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, values = [], - //valueParts = [], + //valueParts = [], value = null, operator = null; @@ -2751,8 +2782,8 @@ Parser.prototype = function(){ values.push(value); do { - operator = this._operator(); - + operator = this._operator(inFunction); + //if there's an operator, keep building up the value parts if (operator){ values.push(operator); @@ -2888,7 +2919,7 @@ Parser.prototype = function(){ if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); - expr = this._expr(); + expr = this._expr(true); functionText += expr; //START: Horrible hack in case it's an IE filter @@ -3502,7 +3533,7 @@ var Properties = { "-o-animation-name" : { multi: "none | ", comma: true }, "-o-animation-play-state" : { multi: "running | paused", comma: true }, - "appearance" : "icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | inherit", + "appearance" : "icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | none | inherit", "azimuth" : function (expression) { var simple = " | leftwards | rightwards | inherit", direction = "left-side | far-left | left | center-left | center | center-right | right | far-right | right-side", @@ -3623,7 +3654,7 @@ var Properties = { valid = ValidationTypes.isAny(expression, numeric); if (!valid) { - if (expression.peek() == "/" && count > 1 && !slash) { + if (expression.peek() == "/" && count > 0 && !slash) { slash = true; max = count + 5; expression.next(); @@ -3711,7 +3742,7 @@ var Properties = { //D "direction" : "ltr | rtl | inherit", - "display" : "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit", + "display" : "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit | -moz-box | -moz-inline-block | -moz-inline-box | -moz-inline-grid | -moz-inline-stack | -moz-inline-table | -moz-grid | -moz-grid-group | -moz-grid-line | -moz-groupbox | -moz-deck | -moz-popup | -moz-stack | -moz-marker", "dominant-baseline" : 1, "drop-initial-after-adjust" : "central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | | ", "drop-initial-after-align" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical", @@ -3914,7 +3945,7 @@ var Properties = { "user-select" : "none | text | toggle | element | elements | all | inherit", //V - "vertical-align" : " | | baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit", + "vertical-align" : "auto | use-script | baseline | sub | super | top | text-top | central | middle | bottom | text-bottom | | ", "visibility" : "visible | hidden | collapse | inherit", "voice-balance" : 1, "voice-duration" : 1, @@ -3927,7 +3958,7 @@ var Properties = { "volume" : 1, //W - "white-space" : "normal | pre | nowrap | pre-wrap | pre-line | inherit", + "white-space" : "normal | pre | nowrap | pre-wrap | pre-line | inherit | -pre-wrap | -o-pre-wrap | -moz-pre-wrap | -hp-pre-wrap", //http://perishablepress.com/wrapping-content/ "white-space-collapse" : 1, "widows" : " | inherit", "width" : " | | auto | inherit" , @@ -6006,7 +6037,7 @@ var ValidationTypes = { }, /** - * Determines if the next part(s) of the given expresion + * Determines if the next part(s) of the given expression * are one of a group. */ isAnyOfGroup: function(expression, types) { @@ -6087,7 +6118,11 @@ var ValidationTypes = { }, "": function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + if (part.type == "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?calc/i.test(part)){ + return true; + }else{ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + } }, "": function(part){ @@ -6153,10 +6188,16 @@ var ValidationTypes = { var types = this, result = false, numeric = " | ", - xDir = "left | center | right", - yDir = "top | center | bottom", - part, - i, len; + xDir = "left | right", + yDir = "top | bottom", + count = 0, + hasNext = function() { + return expression.hasNext() && expression.peek() != ","; + }; + + while (expression.peek(count) && expression.peek(count) != ",") { + count++; + } /* = [ @@ -6168,40 +6209,48 @@ var ValidationTypes = { [ center | [ left | right ] [ | ]? ] && [ center | [ top | bottom ] [ | ]? ] ] +*/ -*/ - - if (ValidationTypes.isAny(expression, "top | bottom")) { - result = true; + if (count < 3) { + if (ValidationTypes.isAny(expression, xDir + " | center | " + numeric)) { + result = true; + ValidationTypes.isAny(expression, yDir + " | center | " + numeric); + } else if (ValidationTypes.isAny(expression, yDir)) { + result = true; + ValidationTypes.isAny(expression, xDir + " | center"); + } } else { - - //must be two-part - if (ValidationTypes.isAny(expression, numeric)){ - if (expression.hasNext()){ - result = ValidationTypes.isAny(expression, numeric + " | " + yDir); - } - } else if (ValidationTypes.isAny(expression, xDir)){ - if (expression.hasNext()){ - - //two- or three-part - if (ValidationTypes.isAny(expression, yDir)){ + if (ValidationTypes.isAny(expression, xDir)) { + if (ValidationTypes.isAny(expression, yDir)) { + result = true; + ValidationTypes.isAny(expression, numeric); + } else if (ValidationTypes.isAny(expression, numeric)) { + if (ValidationTypes.isAny(expression, yDir)) { result = true; - ValidationTypes.isAny(expression, numeric); - - } else if (ValidationTypes.isAny(expression, numeric)){ - - //could also be two-part, so check the next part - if (ValidationTypes.isAny(expression, yDir)){ - ValidationTypes.isAny(expression, numeric); - } - + } else if (ValidationTypes.isAny(expression, "center")) { result = true; } } - } - } - + } else if (ValidationTypes.isAny(expression, yDir)) { + if (ValidationTypes.isAny(expression, xDir)) { + result = true; + ValidationTypes.isAny(expression, numeric); + } else if (ValidationTypes.isAny(expression, numeric)) { + if (ValidationTypes.isAny(expression, xDir)) { + result = true; + ValidationTypes.isAny(expression, numeric); + } else if (ValidationTypes.isAny(expression, "center")) { + result = true; + } + } + } else if (ValidationTypes.isAny(expression, "center")) { + if (ValidationTypes.isAny(expression, xDir + " | " + yDir)) { + result = true; + ValidationTypes.isAny(expression, numeric); + } + } + } return result; }, @@ -6308,9 +6357,10 @@ var ValidationTypes = { }; + parserlib.css = { -Colors :Colors, -Combinator :Combinator, +Colors :Colors, +Combinator :Combinator, Parser :Parser, PropertyName :PropertyName, PropertyValue :PropertyValue, @@ -6328,7 +6378,6 @@ ValidationError :ValidationError })(); - /** * Main CSSLint object. * @class CSSLint @@ -6338,11 +6387,12 @@ ValidationError :ValidationError /*global parserlib, Reporter*/ var CSSLint = (function(){ - var rules = [], - formatters = [], - api = new parserlib.util.EventTarget(); - - api.version = "0.9.9"; + var rules = [], + formatters = [], + embeddedRuleset = /\/\*csslint([^\*]*)\*\//, + api = new parserlib.util.EventTarget(); + + api.version = "0.9.10"; //------------------------------------------------------------------------- // Rule Management @@ -6365,35 +6415,70 @@ var CSSLint = (function(){ api.clearRules = function(){ rules = []; }; - + /** * Returns the rule objects. - * @return {Array} An array of rule objects. + * @return An array of rule objects. * @method getRules */ api.getRules = function(){ - return [].concat(rules).sort(function(a,b){ + return [].concat(rules).sort(function(a,b){ return a.id > b.id ? 1 : 0; }); }; - + /** * Returns a ruleset configuration object with all current rules. - * @return {Object} A ruleset object. + * @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 //------------------------------------------------------------------------- @@ -6407,7 +6492,7 @@ var CSSLint = (function(){ // formatters.push(formatter); formatters[formatter.id] = formatter; }; - + /** * Retrieves a formatter for use. * @param {String} formatId The name of the format to retrieve. @@ -6417,7 +6502,7 @@ var CSSLint = (function(){ 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(). @@ -6430,16 +6515,16 @@ var CSSLint = (function(){ 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. @@ -6475,16 +6560,20 @@ var CSSLint = (function(){ // normalize line endings lines = text.replace(/\n\r?/g, "$split$").split('$split$'); - + if (!ruleset){ ruleset = this.getRuleset(); } - + + if (embeddedRuleset.test(text)){ + ruleset = applyEmbeddedRuleset(text, ruleset); + } + reporter = new Reporter(lines, ruleset); - + ruleset.errors = 2; //always report parsing errors as errors for (i in ruleset){ - if(ruleset.hasOwnProperty(i)){ + if(ruleset.hasOwnProperty(i) && ruleset[i]){ if (rules[i]){ rules[i].init(parser, reporter); } @@ -6501,9 +6590,10 @@ var CSSLint = (function(){ report = { messages : reporter.messages, - stats : reporter.stats + stats : reporter.stats, + ruleset : reporter.ruleset }; - + //sort by line numbers, rollups at the bottom report.messages.sort(function (a, b){ if (a.rollup && !b.rollup){ @@ -6513,8 +6603,8 @@ var CSSLint = (function(){ } else { return a.line - b.line; } - }); - + }); + return report; }; @@ -6525,7 +6615,6 @@ var CSSLint = (function(){ return api; })(); - /*global CSSLint*/ /** * An instance of Report is used to report results of the @@ -6923,6 +7012,72 @@ CSSLint.addRule({ } }); +/* + * 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) + */ +/*global CSSLint*/ +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).", + browsers: "All", + + //initialization + init: function(parser, reporter){ + var rule = this, + count = 0, + 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(event){ + 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(event){ + 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. @@ -6967,7 +7122,7 @@ CSSLint.addRule({ "border-end-style" : "webkit moz", "border-end-width" : "webkit moz", "border-image" : "webkit moz o", - "border-radius" : "webkit moz", + "border-radius" : "webkit", "border-start" : "webkit moz", "border-start-color" : "webkit moz", "border-start-style" : "webkit moz", @@ -7383,7 +7538,17 @@ CSSLint.addRule({ propertiesToCheck = { color: 1, background: 1, - "background-color": 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 }, properties; @@ -7556,14 +7721,13 @@ CSSLint.addRule({ moz: 0, webkit: 0, oldWebkit: 0, - ms: 0, o: 0 }; }); parser.addListener("property", function(event){ - if (/\-(moz|ms|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)){ + 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; @@ -7586,15 +7750,11 @@ CSSLint.addRule({ missing.push("Old Webkit (Safari 4+, Chrome)"); } - if (!gradients.ms){ - missing.push("Internet Explorer 10+"); - } - if (!gradients.o){ missing.push("Opera 11.1+"); } - if (missing.length && missing.length < 5){ + 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); } @@ -7987,6 +8147,62 @@ CSSLint.addRule({ }); } +}); +/* + * Rule: Warn people with approaching the IE 4095 limit + */ +/*global CSSLint*/ +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) { + 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 + */ +/*global CSSLint*/ +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){ + 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: Use shorthand properties where possible. @@ -8511,9 +8727,480 @@ CSSLint.addRule({ }); /*global CSSLint*/ +(function() { + /** + * Replace special characters before write to output. + * + * Rules: + * - single quotes is the escape sequence for double-quotes + * - & is the escape sequence for & + * - < is the escape sequence for < + * - > 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 """; + case "&": + return "&"; + case "<": + return "<"; + case ">": + return ">"; + } + }); + }; + + 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 ""; + }, + + /** + * Return closing root XML tag. + * @return {String} to append after all results + */ + endFormat: function(){ + return ""; + }, + + /** + * 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 ""; + }, + + /** + * 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(""); + CSSLint.Util.forEach(messages, function (message, i) { + //ignore rollups for now + if (!message.rollup) { + output.push(""); + } + }); + output.push(""); + } + + return output.join(""); + } + }); + +}()); +/*global CSSLint*/ +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() { + return ""; + }, + + /** + * Return content to be printed after all file results. + * @return {String} to append after all results + */ + endFormat: function() { + 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) { + 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, i) { + if (message.rollup) { + output += filename + ": " + capitalize(message.type) + " - " + message.message + "\n"; + } else { + output += filename + ": " + "line " + message.line + + ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + "\n"; + } + }); + + return output; + } +}); +/*global CSSLint*/ +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(){ + return ""; + }, + + /** + * Return closing root XML tag. + * @return {String} to append after all results + */ + endFormat: function(){ + 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} (UNUSED for now) specifies special handling of output + * @return {String} output for results + */ + formatResults: function(results, filename, options) { + var messages = results.messages, + output = []; + + /** + * Replace special characters before write to output. + * + * Rules: + * - single quotes is the escape sequence for double-quotes + * - & is the escape sequence for & + * - < is the escape sequence for < + * - > 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, "&").replace(//g, ">"); + }; + + if (messages.length > 0) { + output.push(""); + CSSLint.Util.forEach(messages, function (message, i) { + if (message.rollup) { + output.push(""); + } else { + output.push(""); + } + }); + output.push(""); + } + + return output.join(""); + } +}); +/*global CSSLint*/ +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(){ + return ""; + }, + + /** + * Return closing root XML tag. + * @return {String} to append after all results + */ + endFormat: function() { + 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} (UNUSED for now) specifies special handling of output + * @return {String} output for results + */ + formatResults: function(results, filename, options) { + + 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 + * - < is the escape sequence for < + * - > 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, ">"); + + }; + + if (messages.length > 0) { + + messages.forEach(function (message, i) { + + // 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 seperately, once joined + // we'll add it to a custom array filtered by type + output.push(""); + output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\">"); + output.push(""); + + tests[type] += 1; + + } + + }); + + output.unshift(""); + output.push(""); + + } + + return output.join(""); + + } +}); +/*global CSSLint*/ +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(){ + return ""; + }, + + /** + * Return closing root XML tag. + * @return {String} to append after all results + */ + endFormat: function(){ + 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} (UNUSED for now) specifies special handling of output + * @return {String} output for results + */ + formatResults: function(results, filename, options) { + var messages = results.messages, + output = []; + + /** + * Replace special characters before write to output. + * + * Rules: + * - single quotes is the escape sequence for double-quotes + * - & is the escape sequence for & + * - < is the escape sequence for < + * - > 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, "&").replace(//g, ">"); + }; + + if (messages.length > 0) { + + output.push(""); + CSSLint.Util.forEach(messages, function (message, i) { + if (message.rollup) { + output.push(""); + } else { + output.push(""); + } + }); + output.push(""); + } + + return output.join(""); + } +}); +/*global CSSLint*/ +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() { + return ""; + }, + + /** + * Return content to be printed after all file results. + * @return {String} to append after all results + */ + endFormat: function() { + 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) { + var messages = results.messages, + output = ""; + options = options || {}; + + if (messages.length === 0) { + return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + "."; + } + + output = "\n\ncsslint: There are " + messages.length + " problems 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; + } +}); exports.CSSLint = CSSLint; - -}); +}); \ No newline at end of file diff --git a/tool/update_deps.js b/tool/update_deps.js index 0f868dbc..b0c30c19 100644 --- a/tool/update_deps.js +++ b/tool/update_deps.js @@ -105,9 +105,8 @@ void function(){ if (!data) return if (x.name == "parser.js") { - console.log(data) data = data.replace("var parser = (function(){", "") - .replace(/\nreturn parser[\x00-\uffff]*$/, "\n\nmodule.exports = parser;\n\n") + .replace(/\nreturn (new Parser)[\s\S]*$/, "\n\nmodule.exports = $1;\n\n") } else { data = data.replace("(function() {", "") .replace(/}\).call\(this\);\s*$/, "")