diff --git a/.gitattributes b/.gitattributes
index dfe07704..bb1f0b47 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,3 @@
# Auto detect text files and perform LF normalization
-* text=auto
+* text eol=lf
+*.jar binary
diff --git a/.gitignore b/.gitignore
index 59ec0cb3..94b752cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,5 @@
-/build/
/node_modules/
/npm-debug.log
-/release/npm/README.md
csslint.pnproj
# Diff files
diff --git a/.jshintrc b/.jshintrc
index 4cf0db5e..1cc6261b 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -2,6 +2,7 @@
"camelcase": true,
"curly": true,
"eqeqeq": true,
+ "es3": true,
"forin": true,
"immed": true,
"indent": 4,
@@ -15,7 +16,6 @@
"undef": true,
"unused": true,
"globals": {
- "CSSLint": true,
- "YUITest": true
+ "CSSLint": true
}
-}
\ No newline at end of file
+}
diff --git a/Gruntfile.js b/Gruntfile.js
index 3a5efa19..1cf3cea4 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -4,18 +4,15 @@
module.exports = function(grunt) {
+ // Force use of Unix newlines
+ grunt.util.linefeed = "\n";
+
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON("package.json"),
- banner: {
- compact: "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " +
- "<%= grunt.template.today('yyyy-mm-dd') %>\n" +
- "<%= pkg.homepage ? '* ' + pkg.homepage + '\\n' : '' %>" +
- "* Copyright (c) <%= grunt.template.today('yyyy') %> Nicole Sullivan and Nicholas C. Zakas;\n" +
- "* Licensed <%= _.pluck(pkg.licenses, 'type').join(', ') %> <%= _.pluck(pkg.licenses, 'url').join(', ') %> */\n",
- full: "/*!\n" +
- "CSSLint\n" +
+ banner: "/*!\n" +
+ "CSSLint v<%= pkg.version %>\n" +
"Copyright (c) <%= grunt.template.today('yyyy') %> Nicole Sullivan and Nicholas C. Zakas. All rights reserved.\n" +
"\n" +
"Permission is hereby granted, free of charge, to any person obtaining a copy\n" +
@@ -35,10 +32,8 @@ module.exports = function(grunt) {
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" +
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n" +
"THE SOFTWARE.\n\n" +
- "*/\n" +
- "/* Build: v<%= pkg.version %> <%= grunt.template.today('dd-mmmm-yyyy hh:MM:ss') %> */"
- },
- build_dir: "build",
+ "*/\n",
+ build_dir: "dist",
//Parser lib copy for versions that can't use requirejs
parserlib: "node_modules/parserlib/lib/node-parserlib.js",
//clone copy for versions that can't use requirejs
@@ -56,27 +51,30 @@ module.exports = function(grunt) {
"<%= clone %>",
"<%= csslint_files %>"
],
+
// Task configuration.
clean: {
- build: ["<%= build_dir %>"],
- release: ["release"]
+ dist: "<%= build_dir %>"
},
+
changelog: {
dest: "CHANGELOG"
},
+
concat: {
core: {
options: {
- banner: "<%= banner.full %>\n" +
- //Hack for using the node version of parserlib
- "var exports = exports || {};\n" +
+ banner: "<%= banner %>\n" +
+ // Hack for using the node version of parserlib and clone
+ "var module = module || {},\n" +
+ " exports = exports || {};\n\n" +
"var CSSLint = (function(){\n",
footer: "\nreturn CSSLint;\n})();"
},
src: [
"<%= core_files %>"
],
- dest: "<%= build_dir %>/<%= pkg.name %>.js"
+ dest: "<%= build_dir %>/csslint.js"
},//Build environment workers
rhino: {
src: [
@@ -84,40 +82,39 @@ module.exports = function(grunt) {
"src/cli/common.js",
"src/cli/rhino.js"
],
- dest: "<%= build_dir %>/<%= pkg.name %>-rhino.js"
+ dest: "<%= build_dir %>/csslint-rhino.js"
},
node: {
options: {
- banner: "<%= banner.full %>\n" +
+ banner: "<%= banner %>" +
"var clone = require('clone');\n" +
"var parserlib = require('parserlib');\n",
footer: "\nexports.CSSLint = CSSLint;"
},
files: {
- "<%= build_dir %>/<%= pkg.name %>-node.js": ["<%= csslint_files %>"],
- "<%= build_dir %>/npm/lib/<%= pkg.name %>-node.js": ["<%= csslint_files %>"]
+ "<%= build_dir %>/csslint-node.js": ["<%= csslint_files %>"]
}
},
node_cli: {
options: {
- banner: "#!/usr/bin/env node\n<%= banner.full %>"
+ banner: "#!/usr/bin/env node\n<%= banner %>"
},
src: [
"src/cli/common.js",
"src/cli/node.js"
],
- dest: "<%= build_dir %>/npm/cli.js"
+ dest: "<%= build_dir %>/cli.js"
},
tests: {
src: [
"tests/**/*.js",
"!tests/all-rules.js"
],
- dest: "<%= build_dir %>/<%= pkg.name %>-tests.js"
+ dest: "<%= build_dir %>/csslint-tests.js"
},
worker: {
options: {
- banner: "<%= banner.full %>\n" +
+ banner: "<%= banner %>" +
//Hack for using the node version of parserlib
"var exports = exports || {};\n"
},
@@ -125,7 +122,7 @@ module.exports = function(grunt) {
"<%= core_files %>",
"src/worker/*.js"
],
- dest: "<%= build_dir %>/<%= pkg.name %>-worker.js"
+ dest: "<%= build_dir %>/csslint-worker.js"
},
wsh: {
src: [
@@ -133,24 +130,12 @@ module.exports = function(grunt) {
"src/cli/common.js",
"src/cli/wsh.js"
],
- dest: "<%= build_dir %>/<%= pkg.name %>-wsh.js"
- }
- },
- copy: {
- build: {
- expand: true,
- cwd: "<%= build_dir %>/",
- src: "**/*",
- dest: "release/"
- },
- npm: {
- expand: true,
- src: ["README.md", "package.json"],
- dest: "release/npm/"
+ dest: "<%= build_dir %>/csslint-wsh.js"
}
},
+
includereplace: {
- release: {
+ dist: {
options: {
// Global variables available in all files
globals: {
@@ -163,10 +148,11 @@ module.exports = function(grunt) {
expand: true,
cwd: "<%= build_dir %>/",
src: "**/*",
- dest: "release/"
+ dest: "<%= build_dir %>/"
}]
}
},
+
jshint: {
options: {
jshintrc: ".jshintrc"
@@ -174,30 +160,35 @@ module.exports = function(grunt) {
gruntfile: {
src: ["Gruntfile.js", "tasks/*.js"]
},
+ core: {
+ src: "src/**/*.js"
+ },
demo: {
src: "demos/*.js"
},
- all: {
- src: "src/**/*.js"
- },
tests: {
+ options: {
+ jshintrc: "tests/.jshintrc"
+ },
src: "tests/**/*.js"
}
},
+
watch: {
gruntfile: {
files: "<%= jshint.gruntfile.src %>",
- tasks: ["jshint"]
+ tasks: "jshint"
},
src: {
files: "<%= jshint.all.src %>",
- tasks: ["jshint:all"]
+ tasks: "jshint:core"
},
lib_test: {
files: "<%= jshint.tests.src %>",
- tasks: ["jshint:tests"]
+ tasks: "jshint:tests"
}
},
+
yuitest: {
tests: {
src: [
@@ -205,6 +196,7 @@ module.exports = function(grunt) {
]
}
},
+
test_rhino: {
tests: {
src: [
@@ -223,14 +215,17 @@ module.exports = function(grunt) {
grunt.loadTasks("tasks");
// Default task.
- grunt.registerTask("default", ["test"]);
+ grunt.registerTask("default", ["build", "test"]);
+
+ grunt.registerTask("build", ["clean", "concat", "includereplace"]);
- // Alias for
- grunt.registerTask("lint", ["jshint"]);
+ //Alias for
+ grunt.registerTask("dist", "build");
+ grunt.registerTask("lint", "jshint");
// Testing
- grunt.registerTask("test", ["clean:build", "jshint", "concat", "yuitest"]);
- grunt.registerTask("rhino", ["clean:build", "jshint", "concat", "test_rhino"]);
+ grunt.registerTask("test", ["build", "jshint", "yuitest"]);
+ grunt.registerTask("rhino", ["build", "jshint", "test_rhino"]);
- grunt.registerTask("release", ["test", "clean:release", "copy", "includereplace:release", "changelog"]);
+ grunt.registerTask("release", ["default", "changelog"]);
};
diff --git a/demos/CSSLintDemo.htm b/demos/CSSLintDemo.htm
index 89b5bd34..90cf2cf6 100644
--- a/demos/CSSLintDemo.htm
+++ b/demos/CSSLintDemo.htm
@@ -8,7 +8,7 @@
.error { color: #D9534F; font-weight: bold; }
.warning { color: #F0AD4E; }
-
+
diff --git a/release/npm/cli.js b/dist/cli.js
similarity index 84%
rename from release/npm/cli.js
rename to dist/cli.js
index f78d8dba..b68da989 100644
--- a/release/npm/cli.js
+++ b/dist/cli.js
@@ -1,10 +1,10 @@
#!/usr/bin/env node
/*!
-CSSLint
-Copyright (c) 2013 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
+CSSLint v0.10.0
+Copyright (c) 2015 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
+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
@@ -13,7 +13,7 @@ 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
+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
@@ -22,12 +22,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* Build: v0.10.0 15-August-2013 01:07:22 *//*
+/*
* Encapsulates all of the CLI functionality. The api argument simply
* provides environment-specific functionality.
*/
-/*global CSSLint*/
+
+/* global JSON */
+/* exported cli */
+
function cli(api){
+ "use strict";
var globalOptions = {
"help" : { "format" : "", "description" : "Displays this information."},
@@ -38,6 +42,7 @@ function cli(api){
"warnings" : { "format" : "", "description" : "Indicate which rules to include as warnings."},
"ignore" : { "format" : "", "description" : "Indicate which rules to ignore completely."},
"exclude-list": { "format" : "", "description" : "Indicate which files/directories to exclude from being linted."},
+ "config" : { "format" : "", "description" : "Reads csslint options from specified file."},
"version" : { "format" : "", "description" : "Outputs the current version number."}
};
@@ -195,8 +200,8 @@ function cli(api){
*/
function outputHelp(){
var lenToPad = 40,
- toPrint = '',
- formatString = '';
+ toPrint = "",
+ formatString = "";
api.print([
"\nUsage: csslint-rhino.js [options]* [file|dir]*",
@@ -209,14 +214,14 @@ function cli(api){
// Print the option name and the format if present
toPrint += " --" + optionName;
if (globalOptions[optionName].format !== "") {
- formatString = '=' + globalOptions[optionName].format;
+ formatString = "=" + globalOptions[optionName].format;
toPrint += formatString;
} else {
- formatString = '';
+ formatString = "";
}
// Pad out with the appropriate number of spaces
- toPrint += new Array(lenToPad - (optionName.length + formatString.length)).join(' ');
+ toPrint += new Array(lenToPad - (optionName.length + formatString.length)).join(" ");
// Print the description
toPrint += globalOptions[optionName].description + "\n";
@@ -272,8 +277,9 @@ function cli(api){
}
- function processArguments(args, options) {
+ function processArguments(args, extend) {
var arg = args.shift(),
+ options = extend || {},
argName,
parts,
files = [];
@@ -306,58 +312,84 @@ function cli(api){
}
function validateOptions(options) {
- for (var option_key in options) {
- if (!globalOptions.hasOwnProperty(option_key) && option_key !== 'files') {
- api.print(option_key + ' is not a valid option. Exiting...');
+ for (var optionKey in options) {
+ if (!globalOptions.hasOwnProperty(optionKey) && optionKey !== "files") {
+ api.print(optionKey + " is not a valid option. Exiting...");
outputHelp();
api.quit(0);
}
}
}
- function readConfigFile(options) {
- var data = api.readFile(api.getFullPath(".csslintrc"));
+ function readConfigFile(config) {
+ var csslintrc = config || ".csslintrc",
+ data = api.readFile(api.getFullPath(csslintrc));
+ return data;
+ }
+
+ function readConfigData(config) {
+ var data = readConfigFile(config),
+ json,
+ options = {};
if (data) {
- options = processArguments(data.split(/[\s\n\r]+/m), options);
+ if (data.charAt(0) === "{") {
+ try {
+ json = JSON.parse(data);
+ data = "";
+ for (var optionName in json) {
+ if (json.hasOwnProperty(optionName)) {
+ data += "--" + optionName + "=" + json[optionName].join();
+ }
+ }
+ } catch(e) {}
+ }
+ options = processArguments(data.split(/[\s\n\r]+/m));
}
return options;
}
-
-
//-----------------------------------------------------------------------------
// Process command line
//-----------------------------------------------------------------------------
var args = api.args,
argCount = args.length,
- options = {};
+ options,
+ rcOptions,
+ cliOptions;
- // first look for config file .csslintrc
- options = readConfigFile(options);
-
- // Command line arguments override config file
- options = processArguments(args, options);
+ // Preprocess command line arguments
+ cliOptions = processArguments(args);
- if (options.help || argCount === 0){
+ if (cliOptions.help || argCount === 0){
outputHelp();
api.quit(0);
}
- // Validate options
- validateOptions(options);
-
- if (options.version){
+ if (cliOptions.version){
api.print("v" + CSSLint.version);
api.quit(0);
}
- if (options["list-rules"]){
+ if (cliOptions["list-rules"]){
printRules();
api.quit(0);
}
+ // Look for config file
+ rcOptions = readConfigData(cliOptions.config);
+
+ // Command line arguments override config file
+ options = CSSLint.Util.mix(rcOptions, cliOptions);
+
+ // hot fix for CSSLint.Util.mix current behavior
+ // https://github.com/CSSLint/csslint/issues/501
+ options = rcOptions;
+
+ // Validate options
+ validateOptions(options);
+
api.quit(processFiles(options.files,options));
}
@@ -365,12 +397,14 @@ function cli(api){
* CSSLint Node.js Command Line Interface
*/
-/*jshint node:true*/
-/*global cli*/
+/* jshint node:true */
+/* global cli */
+/* exported CSSLint */
+"use strict";
var fs = require("fs"),
path = require("path"),
- CSSLint = require("./lib/csslint-node").CSSLint;
+ CSSLint = require("./csslint-node").CSSLint;
cli({
args: process.argv.slice(2),
@@ -406,7 +440,7 @@ cli({
var path = stack.concat([file]).join("/"),
stat = fs.statSync(path);
- if (file[0] == ".") {
+ if (file[0] === ".") {
return;
} else if (stat.isFile() && /\.css$/.test(file)){
files.push(path);
@@ -438,4 +472,3 @@ cli({
}
}
});
-
diff --git a/release/csslint-node.js b/dist/csslint-node.js
similarity index 88%
rename from release/csslint-node.js
rename to dist/csslint-node.js
index f800f974..76973b6f 100644
--- a/release/csslint-node.js
+++ b/dist/csslint-node.js
@@ -1,9 +1,9 @@
/*!
-CSSLint
-Copyright (c) 2013 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
+CSSLint v0.10.0
+Copyright (c) 2015 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
+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
@@ -12,7 +12,7 @@ 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
+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
@@ -21,16 +21,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* Build: v0.10.0 15-August-2013 01:07:22 */
-var parserlib = require("parserlib");
+var clone = require('clone');
+var parserlib = require('parserlib');
/**
* Main CSSLint object.
* @class CSSLint
* @static
* @extends parserlib.util.EventTarget
*/
-/*global parserlib, Reporter*/
+
+/* global parserlib, clone, Reporter */
+/* exported CSSLint */
+
var CSSLint = (function(){
+ "use strict";
var rules = [],
formatters = [],
@@ -195,8 +199,7 @@ var CSSLint = (function(){
*/
api.verify = function(text, ruleset){
- var i = 0,
- len = rules.length,
+ var i = 0,
reporter,
lines,
report,
@@ -204,13 +207,15 @@ var CSSLint = (function(){
underscoreHack: true, strict: false });
// normalize line endings
- lines = text.replace(/\n\r?/g, "$split$").split('$split$');
+ lines = text.replace(/\n\r?/g, "$split$").split("$split$");
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);
}
@@ -261,7 +266,6 @@ var CSSLint = (function(){
})();
-/*global CSSLint*/
/**
* An instance of Report is used to report results of the
* verification back to the main API.
@@ -272,6 +276,7 @@ var CSSLint = (function(){
* they are errors or warnings.
*/
function Reporter(lines, ruleset){
+ "use strict";
/**
* List of messages being reported.
@@ -318,6 +323,7 @@ Reporter.prototype = {
* @method error
*/
error: function(message, line, col, rule){
+ "use strict";
this.messages.push({
type : "error",
line : line,
@@ -338,6 +344,7 @@ Reporter.prototype = {
* @deprecated Use report instead.
*/
warn: function(message, line, col, rule){
+ "use strict";
this.report(message, line, col, rule);
},
@@ -350,8 +357,9 @@ Reporter.prototype = {
* @method report
*/
report: function(message, line, col, rule){
+ "use strict";
this.messages.push({
- type : this.ruleset[rule.id] == 2 ? "error" : "warning",
+ type : this.ruleset[rule.id] === 2 ? "error" : "warning",
line : line,
col : col,
message : message,
@@ -369,6 +377,7 @@ Reporter.prototype = {
* @method info
*/
info: function(message, line, col, rule){
+ "use strict";
this.messages.push({
type : "info",
line : line,
@@ -386,6 +395,7 @@ Reporter.prototype = {
* @method rollupError
*/
rollupError: function(message, rule){
+ "use strict";
this.messages.push({
type : "error",
rollup : true,
@@ -401,6 +411,7 @@ Reporter.prototype = {
* @method rollupWarn
*/
rollupWarn: function(message, rule){
+ "use strict";
this.messages.push({
type : "warning",
rollup : true,
@@ -416,6 +427,7 @@ Reporter.prototype = {
* @method stat
*/
stat: function(name, value){
+ "use strict";
this.stats[name] = value;
}
};
@@ -423,8 +435,6 @@ Reporter.prototype = {
//expose for testing purposes
CSSLint._Reporter = Reporter;
-/*global CSSLint*/
-
/*
* Utility functions that make life easier.
*/
@@ -438,6 +448,7 @@ CSSLint.Util = {
* @return {Object} The receiver
*/
mix: function(receiver, supplier){
+ "use strict";
var prop;
for (prop in supplier){
@@ -456,6 +467,7 @@ CSSLint.Util = {
* @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 {
@@ -475,6 +487,7 @@ CSSLint.Util = {
* @return {void}
*/
forEach: function(values, func) {
+ "use strict";
if (values.forEach){
return values.forEach(func);
} else {
@@ -484,10 +497,11 @@ CSSLint.Util = {
}
}
};
-/*global CSSLint*/
+
/*
* Rule: Don't use adjoining classes (.foo.bar).
*/
+
CSSLint.addRule({
//rule information
@@ -498,6 +512,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("startrule", function(event){
var selectors = event.selectors,
@@ -511,11 +526,11 @@ CSSLint.addRule({
selector = selectors[i];
for (j=0; j < selector.parts.length; j++){
part = selector.parts[j];
- if (part.type == parser.SELECTOR_PART_TYPE){
+ 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"){
+ if (modifier.type === "class"){
classCount++;
}
if (classCount > 1){
@@ -529,7 +544,6 @@ CSSLint.addRule({
}
});
-/*global CSSLint*/
/*
* Rule: Don't use width or height when using padding or border.
@@ -544,6 +558,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
widthProperties = {
border: 1,
@@ -578,7 +593,7 @@ CSSLint.addRule({
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)){
+ 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);
}
}
@@ -590,7 +605,7 @@ CSSLint.addRule({
if (widthProperties.hasOwnProperty(prop) && properties[prop]){
value = properties[prop].value;
- if (!(prop == "padding" && value.parts.length === 2 && value.parts[1].value === 0)){
+ 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);
}
}
@@ -604,18 +619,19 @@ CSSLint.addRule({
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 == "none")){
+ 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") {
+ } else if (name === "box-sizing") {
boxSizing = true;
}
}
@@ -627,14 +643,15 @@ CSSLint.addRule({
parser.addListener("endpage", endRule);
parser.addListener("endpagemargin", endRule);
parser.addListener("endkeyframerule", endRule);
+ parser.addListener("endviewport", endRule);
}
});
-/*global CSSLint*/
/*
* Rule: box-sizing doesn't work in IE6 and IE7.
*/
+
CSSLint.addRule({
//rule information
@@ -646,23 +663,25 @@ CSSLint.addRule({
//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"){
+ 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)
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -673,15 +692,15 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
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){
+ parser.addListener("startfontface", function(){
fontFaceRule = true;
});
@@ -699,7 +718,7 @@ CSSLint.addRule({
col = event.col;
// This is the property that we care about, we can ignore the rest
- if (propertyName === 'src') {
+ if (propertyName === "src") {
var regex = /^\s?url\(['"].+\.eot\?.*['"]\)\s*format\(['"]embedded-opentype['"]\).*$/i;
// We need to handle the advanced syntax with two src properties
@@ -715,7 +734,7 @@ CSSLint.addRule({
});
// Back to normal rules that we don't need to test
- parser.addListener("endfontface", function(event){
+ parser.addListener("endfontface", function(){
fontFaceRule = false;
if (ruleFailed) {
@@ -724,11 +743,12 @@ CSSLint.addRule({
});
}
});
+
/*
* Rule: Include all compatible vendor prefixes to reach a wider
* range of users.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -739,6 +759,7 @@ CSSLint.addRule({
//initialization
init: function (parser, reporter) {
+ "use strict";
var rule = this,
compatiblePrefixes,
properties,
@@ -816,9 +837,9 @@ CSSLint.addRule({
for (prop in compatiblePrefixes) {
if (compatiblePrefixes.hasOwnProperty(prop)) {
variations = [];
- prefixed = compatiblePrefixes[prop].split(' ');
+ prefixed = compatiblePrefixes[prop].split(" ");
for (i = 0, len = prefixed.length; i < len; i++) {
- variations.push('-' + prefixed[i] + '-' + prop);
+ variations.push("-" + prefixed[i] + "-" + prop);
}
compatiblePrefixes[prop] = variations;
arrayPush.apply(applyTo, variations);
@@ -833,7 +854,7 @@ CSSLint.addRule({
inKeyFrame = event.prefix || true;
});
- parser.addListener("endkeyframes", function (event) {
+ parser.addListener("endkeyframes", function () {
inKeyFrame = false;
});
@@ -842,14 +863,14 @@ CSSLint.addRule({
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" ||
+ if (!inKeyFrame || typeof inKeyFrame !== "string" ||
name.text.indexOf("-" + inKeyFrame + "-") !== 0) {
properties.push(name);
}
}
});
- parser.addListener("endrule", function (event) {
+ parser.addListener("endrule", function () {
if (!properties.length) {
return;
}
@@ -899,7 +920,7 @@ CSSLint.addRule({
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(", ");
+ 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);
}
}
@@ -910,6 +931,7 @@ CSSLint.addRule({
});
}
});
+
/*
* Rule: Certain properties don't play well with certain display values.
* - float should not be used with inline-block
@@ -917,7 +939,7 @@ CSSLint.addRule({
* - vertical-align should not be used with block
* - margin, float should not be used with table-*
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -928,6 +950,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
var propertiesToCheck = {
@@ -951,7 +974,7 @@ CSSLint.addRule({
function reportProperty(name, display, msg){
if (properties[name]){
- if (typeof propertiesToCheck[name] != "string" || properties[name].value.toLowerCase() != propertiesToCheck[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);
}
}
@@ -1009,6 +1032,7 @@ CSSLint.addRule({
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();
@@ -1023,14 +1047,16 @@ CSSLint.addRule({
parser.addListener("endkeyframerule", endRule);
parser.addListener("endpagemargin", endRule);
parser.addListener("endpage", endRule);
+ parser.addListener("endviewport", endRule);
}
});
+
/*
* Rule: Disallow duplicate background-images (using url).
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1041,6 +1067,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
stack = {};
@@ -1051,8 +1078,8 @@ CSSLint.addRule({
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') {
+ if (value.parts[i].type === "uri") {
+ if (typeof stack[value.parts[i].uri] === "undefined") {
stack[value.parts[i].uri] = event;
}
else {
@@ -1064,11 +1091,12 @@ CSSLint.addRule({
});
}
});
+
/*
* 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.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1079,11 +1107,12 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
properties,
lastProperty;
- function startRule(event){
+ function startRule(){
properties = {};
}
@@ -1092,12 +1121,13 @@ CSSLint.addRule({
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)){
+ if (properties[name] && (lastProperty !== name || properties[name] === event.value.text)){
reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
}
@@ -1110,10 +1140,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Style rules without any properties defined should be removed.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1124,6 +1155,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
count = 0;
@@ -1144,10 +1176,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: There should be no syntax errors. (Duh.)
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1158,6 +1191,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("error", function(event){
@@ -1168,7 +1202,6 @@ CSSLint.addRule({
});
-/*global CSSLint*/
CSSLint.addRule({
//rule information
@@ -1179,6 +1212,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
lastProperty,
propertiesToCheck = {
@@ -1198,7 +1232,7 @@ CSSLint.addRule({
},
properties;
- function startRule(event){
+ function startRule(){
properties = {};
lastProperty = null;
}
@@ -1208,6 +1242,7 @@ CSSLint.addRule({
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,
@@ -1219,14 +1254,14 @@ CSSLint.addRule({
if(propertiesToCheck[name]){
while(i < len){
- if (parts[i].type == "color"){
+ 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")){
+ 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 {
@@ -1244,11 +1279,12 @@ CSSLint.addRule({
}
});
+
/*
* Rule: You shouldn't use more than 10 floats. If you do, there's probably
* room for some abstraction.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1259,13 +1295,14 @@ CSSLint.addRule({
//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"){
+ if (event.property.text.toLowerCase() === "float" &&
+ event.value.text.toLowerCase() !== "none"){
count++;
}
});
@@ -1280,10 +1317,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Avoid too many @font-face declarations in the same stylesheet.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1294,6 +1332,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
count = 0;
@@ -1310,11 +1349,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: You shouldn't need more than 9 font-size declarations.
*/
-/*global CSSLint*/
CSSLint.addRule({
//rule information
@@ -1325,12 +1364,13 @@ CSSLint.addRule({
//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 == "font-size"){
+ if (event.property.toString() === "font-size"){
count++;
}
});
@@ -1345,10 +1385,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: When using a vendor-prefixed gradient, make sure to use them all.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1359,6 +1400,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
gradients;
@@ -1413,7 +1455,7 @@ CSSLint.addRule({
/*
* Rule: Don't use IDs for selectors.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1424,6 +1466,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("startrule", function(event){
var selectors = event.selectors,
@@ -1439,17 +1482,17 @@ CSSLint.addRule({
for (j=0; j < selector.parts.length; j++){
part = selector.parts[j];
- if (part.type == parser.SELECTOR_PART_TYPE){
+ if (part.type === parser.SELECTOR_PART_TYPE){
for (k=0; k < part.modifiers.length; k++){
modifier = part.modifiers[k];
- if (modifier.type == "id"){
+ if (modifier.type === "id"){
idCount++;
}
}
}
}
- if (idCount == 1){
+ 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);
@@ -1460,10 +1503,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Don't use @import, use instead.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1474,6 +1518,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("import", function(event){
@@ -1483,12 +1528,13 @@ CSSLint.addRule({
}
});
+
/*
* 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.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1499,6 +1545,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
count = 0;
@@ -1520,11 +1567,12 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Properties should be known (listed in CSS3 specification) or
* be a vendor-prefixed property.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1535,10 +1583,10 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("property", function(event){
- var name = event.property.text.toLowerCase();
// the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)
if (event.invalid) {
@@ -1549,11 +1597,67 @@ CSSLint.addRule({
}
});
+
+/*
+ * Rule: All properties should be in alphabetical order..
+ */
+/*global CSSLint*/
+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 ordered.", 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.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1565,6 +1669,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
lastRule;
@@ -1582,12 +1687,12 @@ CSSLint.addRule({
}
}
- function endRule(event){
+ function endRule(){
if (lastRule){
if (lastRule.outline){
- if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") == -1){
+ 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) {
+ } else if (lastRule.propCount === 1) {
reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);
}
}
@@ -1599,6 +1704,7 @@ CSSLint.addRule({
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(),
@@ -1606,7 +1712,7 @@ CSSLint.addRule({
if (lastRule){
lastRule.propCount++;
- if (name == "outline" && (value == "none" || value == "0")){
+ if (name === "outline" && (value.toString() === "none" || value.toString() === "0")){
lastRule.outline = true;
}
}
@@ -1618,14 +1724,16 @@ CSSLint.addRule({
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).
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1636,6 +1744,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
classes = {};
@@ -1651,12 +1760,12 @@ CSSLint.addRule({
for (j=0; j < selector.parts.length; j++){
part = selector.parts[j];
- if (part.type == parser.SELECTOR_PART_TYPE){
+ 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"){
+ 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"){
+ } else if (modifier.type === "class"){
if (!classes[modifier]){
classes[modifier] = [];
@@ -1676,7 +1785,7 @@ CSSLint.addRule({
if (classes.hasOwnProperty(prop)){
//one use means that this is overqualified
- if (classes[prop].length == 1 && classes[prop][0].part.elementName){
+ 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);
}
}
@@ -1685,10 +1794,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Headings (h1-h6) should not be qualified (namespaced).
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1699,6 +1809,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("startrule", function(event){
@@ -1712,7 +1823,7 @@ CSSLint.addRule({
for (j=0; j < selector.parts.length; j++){
part = selector.parts[j];
- if (part.type == parser.SELECTOR_PART_TYPE){
+ 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);
}
@@ -1723,10 +1834,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Selectors that look like regular expressions are slow and should be avoided.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1737,6 +1849,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("startrule", function(event){
@@ -1750,10 +1863,10 @@ CSSLint.addRule({
selector = selectors[i];
for (j=0; j < selector.parts.length; j++){
part = selector.parts[j];
- if (part.type == parser.SELECTOR_PART_TYPE){
+ if (part.type === parser.SELECTOR_PART_TYPE){
for (k=0; k < part.modifiers.length; k++){
modifier = part.modifiers[k];
- if (modifier.type == "attribute"){
+ if (modifier.type === "attribute"){
if (/([\~\|\^\$\*]=)/.test(modifier)){
reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
}
@@ -1767,10 +1880,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Total number of rules should not exceed x.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1781,8 +1895,8 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
- var rule = this,
- count = 0;
+ "use strict";
+ var count = 0;
//count each rule
parser.addListener("startrule", function(){
@@ -1795,10 +1909,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Warn people with approaching the IE 4095 limit
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1809,9 +1924,10 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter) {
+ "use strict";
var rule = this, count = 0;
- parser.addListener('startrule', function(event) {
+ parser.addListener("startrule", function(event) {
count += event.selectors.length;
});
@@ -1827,7 +1943,7 @@ CSSLint.addRule({
/*
* Rule: Warn people past the IE 4095 limit
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1838,9 +1954,10 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this, count = 0;
- parser.addListener('startrule',function(event) {
+ parser.addListener("startrule", function(event) {
count += event.selectors.length;
});
@@ -1852,11 +1969,57 @@ CSSLint.addRule({
}
});
+
+/*
+ * 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.
*
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1867,6 +2030,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
prop, i, len,
propertiesToCheck = {},
@@ -1895,7 +2059,7 @@ CSSLint.addRule({
}
}
- function startRule(event){
+ function startRule(){
properties = {};
}
@@ -1913,7 +2077,7 @@ CSSLint.addRule({
total += properties[mapping[prop][i]] ? 1 : 0;
}
- if (total == mapping[prop].length){
+ if (total === mapping[prop].length){
reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
}
}
@@ -1925,8 +2089,7 @@ CSSLint.addRule({
//check for use of "font-size"
parser.addListener("property", function(event){
- var name = event.property.toString().toLowerCase(),
- value = event.value.parts[0].value;
+ var name = event.property.toString().toLowerCase();
if (propertiesToCheck[name]){
properties[name] = 1;
@@ -1939,11 +2102,12 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Don't use properties with a star prefix.
*
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1954,23 +2118,25 @@ CSSLint.addRule({
//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 == "*") {
+ 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.
*
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -1981,19 +2147,20 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
textIndent,
direction;
- function startRule(event){
+ function startRule(){
textIndent = false;
direction = "inherit";
}
//event handler for end of rules
- function endRule(event){
- if (textIndent && direction != "ltr"){
+ 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);
}
}
@@ -2006,9 +2173,9 @@ CSSLint.addRule({
var name = event.property.toString().toLowerCase(),
value = event.value;
- if (name == "text-indent" && value.parts[0].value < -99){
+ if (name === "text-indent" && value.parts[0].value < -99){
textIndent = event.property;
- } else if (name == "direction" && value == "ltr"){
+ } else if (name === "direction" && value.toString() === "ltr"){
direction = "ltr";
}
});
@@ -2019,11 +2186,12 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Don't use properties with a underscore prefix.
*
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2034,22 +2202,24 @@ CSSLint.addRule({
//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 == "_") {
+ 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.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2060,9 +2230,10 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
- var headings = {
+ var headings = {
h1: 0,
h2: 0,
h3: 0,
@@ -2085,7 +2256,7 @@ CSSLint.addRule({
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"){
+ if (part.modifiers[j].type === "pseudo"){
pseudo = true;
break;
}
@@ -2101,7 +2272,7 @@ CSSLint.addRule({
}
});
- parser.addListener("endstylesheet", function(event){
+ parser.addListener("endstylesheet", function(){
var prop,
messages = [];
@@ -2120,10 +2291,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Don't use universal selector because it's slow.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2134,20 +2306,20 @@ CSSLint.addRule({
//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;
+ i;
for (i=0; i < selectors.length; i++){
selector = selectors[i];
part = selector.parts[selector.parts.length-1];
- if (part.elementName == "*"){
+ if (part.elementName === "*"){
reporter.report(rule.desc, part.line, part.col, rule);
}
}
@@ -2155,10 +2327,11 @@ CSSLint.addRule({
}
});
+
/*
* Rule: Don't use unqualified attribute selectors because they're just like universal selectors.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2169,6 +2342,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
parser.addListener("startrule", function(event){
@@ -2177,16 +2351,16 @@ CSSLint.addRule({
selector,
part,
modifier,
- i, j, k;
+ 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){
+ if (part.type === parser.SELECTOR_PART_TYPE){
for (k=0; k < part.modifiers.length; k++){
modifier = part.modifiers[k];
- if (modifier.type == "attribute" && (!part.elementName || part.elementName == "*")){
+ if (modifier.type === "attribute" && (!part.elementName || part.elementName === "*")){
reporter.report(rule.desc, part.line, part.col, rule);
}
}
@@ -2197,11 +2371,12 @@ CSSLint.addRule({
}
});
+
/*
* Rule: When using a vendor-prefixed property, make sure to
* include the standard one.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2212,6 +2387,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this,
properties,
num,
@@ -2272,24 +2448,20 @@ CSSLint.addRule({
"-ms-transform-origin" : "transform-origin",
"-moz-box-sizing" : "box-sizing",
- "-webkit-box-sizing" : "box-sizing",
-
- "-moz-user-select" : "user-select",
- "-khtml-user-select" : "user-select",
- "-webkit-user-select" : "user-select"
+ "-webkit-box-sizing" : "box-sizing"
};
//event handler for beginning of rules
function startRule(){
properties = {};
- num=1;
+ num = 1;
}
//event handler for end of rules
- function endRule(event){
+ function endRule(){
var prop,
- i, len,
- standard,
+ i,
+ len,
needed,
actual,
needsStandard = [];
@@ -2321,6 +2493,7 @@ CSSLint.addRule({
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();
@@ -2337,13 +2510,15 @@ CSSLint.addRule({
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.
*/
-/*global CSSLint*/
+
CSSLint.addRule({
//rule information
@@ -2354,6 +2529,7 @@ CSSLint.addRule({
//initialization
init: function(parser, reporter){
+ "use strict";
var rule = this;
//count how many times "float" is used
@@ -2363,7 +2539,7 @@ CSSLint.addRule({
len = parts.length;
while(i < len){
- if ((parts[i].units || parts[i].type == "percentage") && parts[i].value === 0 && parts[i].type != "time"){
+ 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++;
@@ -2374,8 +2550,9 @@ CSSLint.addRule({
}
});
-/*global CSSLint*/
+
(function() {
+ "use strict";
/**
* Replace special characters before write to output.
@@ -2446,7 +2623,7 @@ CSSLint.addRule({
* @param options {Object} (UNUSED for now) specifies special handling of output
* @return {String} output for results
*/
- formatResults: function(results, filename, options) {
+ formatResults: function(results, filename/*, options*/) {
var messages = results.messages,
output = [];
@@ -2458,20 +2635,20 @@ CSSLint.addRule({
* @return rule source as {String}
*/
var generateSource = function(rule) {
- if (!rule || !('name' in rule)) {
+ if (!rule || !("name" in rule)) {
return "";
}
- return 'net.csslint.' + rule.name.replace(/\s/g,'');
+ return "net.csslint." + rule.name.replace(/\s/g,"");
};
if (messages.length > 0) {
output.push("");
- CSSLint.Util.forEach(messages, function (message, i) {
+ CSSLint.Util.forEach(messages, function (message) {
//ignore rollups for now
if (!message.rollup) {
- output.push("");
}
});
@@ -2483,7 +2660,7 @@ CSSLint.addRule({
});
}());
-/*global CSSLint*/
+
CSSLint.addFormatter({
//format information
id: "compact",
@@ -2494,6 +2671,7 @@ CSSLint.addFormatter({
* @return {String} to prepend before all results
*/
startFormat: function() {
+ "use strict";
return "";
},
@@ -2502,6 +2680,7 @@ CSSLint.addFormatter({
* @return {String} to append after all results
*/
endFormat: function() {
+ "use strict";
return "";
},
@@ -2513,6 +2692,7 @@ CSSLint.addFormatter({
* @return {String} output for results
*/
formatResults: function(results, filename, options) {
+ "use strict";
var messages = results.messages,
output = "";
options = options || {};
@@ -2527,22 +2707,22 @@ CSSLint.addFormatter({
};
if (messages.length === 0) {
- return options.quiet ? "" : filename + ": Lint Free!";
+ return options.quiet ? "" : filename + ": Lint Free!";
}
- CSSLint.Util.forEach(messages, function(message, i) {
+ CSSLint.Util.forEach(messages, function(message) {
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";
+ ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
}
});
return output;
}
});
-/*global CSSLint*/
+
CSSLint.addFormatter({
//format information
id: "csslint-xml",
@@ -2553,6 +2733,7 @@ CSSLint.addFormatter({
* @return {String} to prepend before all results
*/
startFormat: function(){
+ "use strict";
return "";
},
@@ -2561,6 +2742,7 @@ CSSLint.addFormatter({
* @return {String} to append after all results
*/
endFormat: function(){
+ "use strict";
return "";
},
@@ -2571,7 +2753,8 @@ CSSLint.addFormatter({
* @param options {Object} (UNUSED for now) specifies special handling of output
* @return {String} output for results
*/
- formatResults: function(results, filename, options) {
+ formatResults: function(results, filename/*, options*/) {
+ "use strict";
var messages = results.messages,
output = [];
@@ -2596,7 +2779,7 @@ CSSLint.addFormatter({
if (messages.length > 0) {
output.push("");
- CSSLint.Util.forEach(messages, function (message, i) {
+ CSSLint.Util.forEach(messages, function (message) {
if (message.rollup) {
output.push("");
} else {
@@ -2610,7 +2793,7 @@ CSSLint.addFormatter({
return output.join("");
}
});
-/*global CSSLint*/
+
CSSLint.addFormatter({
//format information
id: "junit-xml",
@@ -2621,6 +2804,7 @@ CSSLint.addFormatter({
* @return {String} to prepend before all results
*/
startFormat: function(){
+ "use strict";
return "";
},
@@ -2629,6 +2813,7 @@ CSSLint.addFormatter({
* @return {String} to append after all results
*/
endFormat: function() {
+ "use strict";
return "";
},
@@ -2639,13 +2824,14 @@ CSSLint.addFormatter({
* @param options {Object} (UNUSED for now) specifies special handling of output
* @return {String} output for results
*/
- formatResults: function(results, filename, options) {
+ formatResults: function(results, filename/*, options*/) {
+ "use strict";
var messages = results.messages,
output = [],
tests = {
- 'error': 0,
- 'failure': 0
+ "error": 0,
+ "failure": 0
};
/**
@@ -2656,10 +2842,10 @@ CSSLint.addFormatter({
* @return rule source as {String}
*/
var generateSource = function(rule) {
- if (!rule || !('name' in rule)) {
+ if (!rule || !("name" in rule)) {
return "";
}
- return 'net.csslint.' + rule.name.replace(/\s/g,'');
+ return "net.csslint." + rule.name.replace(/\s/g,"");
};
/**
@@ -2685,11 +2871,11 @@ CSSLint.addFormatter({
if (messages.length > 0) {
- messages.forEach(function (message, i) {
+ messages.forEach(function (message) {
// since junit has no warning class
// all issues as errors
- var type = message.type === 'warning' ? 'error' : message.type;
+ var type = message.type === "warning" ? "error" : message.type;
//ignore rollups for now
if (!message.rollup) {
@@ -2697,7 +2883,7 @@ CSSLint.addFormatter({
// 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) + "\">" + type + ">");
+ output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\">" + type + ">");
output.push("");
tests[type] += 1;
@@ -2715,7 +2901,7 @@ CSSLint.addFormatter({
}
});
-/*global CSSLint*/
+
CSSLint.addFormatter({
//format information
id: "lint-xml",
@@ -2726,6 +2912,7 @@ CSSLint.addFormatter({
* @return {String} to prepend before all results
*/
startFormat: function(){
+ "use strict";
return "";
},
@@ -2734,6 +2921,7 @@ CSSLint.addFormatter({
* @return {String} to append after all results
*/
endFormat: function(){
+ "use strict";
return "";
},
@@ -2744,7 +2932,8 @@ CSSLint.addFormatter({
* @param options {Object} (UNUSED for now) specifies special handling of output
* @return {String} output for results
*/
- formatResults: function(results, filename, options) {
+ formatResults: function(results, filename/*, options*/) {
+ "use strict";
var messages = results.messages,
output = [];
@@ -2770,7 +2959,7 @@ CSSLint.addFormatter({
if (messages.length > 0) {
output.push("");
- CSSLint.Util.forEach(messages, function (message, i) {
+ CSSLint.Util.forEach(messages, function (message) {
if (message.rollup) {
output.push("");
} else {
@@ -2784,7 +2973,7 @@ CSSLint.addFormatter({
return output.join("");
}
});
-/*global CSSLint*/
+
CSSLint.addFormatter({
//format information
id: "text",
@@ -2795,6 +2984,7 @@ CSSLint.addFormatter({
* @return {String} to prepend before all results
*/
startFormat: function() {
+ "use strict";
return "";
},
@@ -2803,6 +2993,7 @@ CSSLint.addFormatter({
* @return {String} to append after all results
*/
endFormat: function() {
+ "use strict";
return "";
},
@@ -2814,6 +3005,7 @@ CSSLint.addFormatter({
* @return {String} output for results
*/
formatResults: function(results, filename, options) {
+ "use strict";
var messages = results.messages,
output = "";
options = options || {};
@@ -2822,7 +3014,14 @@ CSSLint.addFormatter({
return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + ".";
}
- output = "\n\ncsslint: There are " + messages.length + " problems 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;
@@ -2848,4 +3047,5 @@ CSSLint.addFormatter({
return output;
}
});
+
exports.CSSLint = CSSLint;
\ No newline at end of file
diff --git a/release/csslint-rhino.js b/dist/csslint-rhino.js
similarity index 91%
rename from release/csslint-rhino.js
rename to dist/csslint-rhino.js
index 587d438b..7ca4d140 100644
--- a/release/csslint-rhino.js
+++ b/dist/csslint-rhino.js
@@ -1,9 +1,9 @@
/*!
-CSSLint
-Copyright (c) 2013 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
+CSSLint v0.10.0
+Copyright (c) 2015 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
+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
@@ -12,7 +12,7 @@ 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
+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
@@ -21,8 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* Build: v0.10.0 15-August-2013 01:07:22 */
-var exports = exports || {};
+
+var module = module || {},
+ exports = exports || {};
+
var CSSLint = (function(){
/*!
Parser-Lib
@@ -47,11 +49,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* Version v0.2.3, Build time: 19-June-2013 11:16:15 */
+/* Version v0.2.5, Build time: 7-May-2014 03:37:38 */
var parserlib = {};
(function(){
-
/**
* A generic base to inherit from for any object
* that needs event handling.
@@ -922,8 +923,6 @@ TokenStreamBase.prototype = {
};
-
-
parserlib.util = {
StringReader: StringReader,
SyntaxError : SyntaxError,
@@ -932,8 +931,6 @@ EventTarget : EventTarget,
TokenStreamBase : TokenStreamBase
};
})();
-
-
/*
Parser-Lib
Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.
@@ -957,7 +954,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* Version v0.2.3, Build time: 19-June-2013 11:16:15 */
+/* Version v0.2.5, Build time: 7-May-2014 03:37:38 */
(function(){
var EventTarget = parserlib.util.EventTarget,
TokenStreamBase = parserlib.util.TokenStreamBase,
@@ -965,7 +962,6 @@ StringReader = parserlib.util.StringReader,
SyntaxError = parserlib.util.SyntaxError,
SyntaxUnit = parserlib.util.SyntaxUnit;
-
var Colors = {
aliceblue :"#f0f8ff",
antiquewhite :"#faebd7",
@@ -992,6 +988,7 @@ var Colors = {
darkcyan :"#008b8b",
darkgoldenrod :"#b8860b",
darkgray :"#a9a9a9",
+ darkgrey :"#a9a9a9",
darkgreen :"#006400",
darkkhaki :"#bdb76b",
darkmagenta :"#8b008b",
@@ -1003,11 +1000,13 @@ var Colors = {
darkseagreen :"#8fbc8f",
darkslateblue :"#483d8b",
darkslategray :"#2f4f4f",
+ darkslategrey :"#2f4f4f",
darkturquoise :"#00ced1",
darkviolet :"#9400d3",
deeppink :"#ff1493",
deepskyblue :"#00bfff",
dimgray :"#696969",
+ dimgrey :"#696969",
dodgerblue :"#1e90ff",
firebrick :"#b22222",
floralwhite :"#fffaf0",
@@ -1018,6 +1017,7 @@ var Colors = {
gold :"#ffd700",
goldenrod :"#daa520",
gray :"#808080",
+ grey :"#808080",
green :"#008000",
greenyellow :"#adff2f",
honeydew :"#f0fff0",
@@ -1035,12 +1035,14 @@ var Colors = {
lightcyan :"#e0ffff",
lightgoldenrodyellow :"#fafad2",
lightgray :"#d3d3d3",
+ lightgrey :"#d3d3d3",
lightgreen :"#90ee90",
lightpink :"#ffb6c1",
lightsalmon :"#ffa07a",
lightseagreen :"#20b2aa",
lightskyblue :"#87cefa",
lightslategray :"#778899",
+ lightslategrey :"#778899",
lightsteelblue :"#b0c4de",
lightyellow :"#ffffe0",
lime :"#00ff00",
@@ -1093,6 +1095,7 @@ var Colors = {
skyblue :"#87ceeb",
slateblue :"#6a5acd",
slategray :"#708090",
+ slategrey :"#708090",
snow :"#fffafa",
springgreen :"#00ff7f",
steelblue :"#4682b4",
@@ -1118,6 +1121,7 @@ var Colors = {
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.",
+ greytext :"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.",
highlight :"Item(s) selected in a control.",
highlighttext :"Text of item(s) selected in a control.",
inactiveborder :"Inactive window border.",
@@ -1175,7 +1179,6 @@ function Combinator(text, line, col){
Combinator.prototype = new SyntaxUnit();
Combinator.prototype.constructor = Combinator;
-
/*global SyntaxUnit, Parser*/
/**
* Represents a media feature, such as max-width:500.
@@ -1208,7 +1211,6 @@ function MediaFeature(name, value){
MediaFeature.prototype = new SyntaxUnit();
MediaFeature.prototype.constructor = MediaFeature;
-
/*global SyntaxUnit, Parser*/
/**
* Represents an individual media query.
@@ -1252,7 +1254,6 @@ function MediaQuery(modifier, mediaType, features, line, col){
MediaQuery.prototype = new SyntaxUnit();
MediaQuery.prototype.constructor = MediaQuery;
-
/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit,
PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector,
PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */
@@ -1514,7 +1515,7 @@ Parser.prototype = function(){
tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);
//grab the URI value
- uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1");
+ uri = tokenStream.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/, "$1");
this._readWhitespace();
@@ -1619,8 +1620,10 @@ Parser.prototype = function(){
while(true) {
if (tokenStream.peek() == Tokens.PAGE_SYM){
this._page();
- } else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){
+ } else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){
this._font_face();
+ } else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){
+ this._viewport();
} else if (!this._ruleset()){
break;
}
@@ -2812,11 +2815,11 @@ Parser.prototype = function(){
var tokenStream = this._tokenStream,
values = [],
- //valueParts = [],
+ //valueParts = [],
value = null,
operator = null;
- value = this._term();
+ value = this._term(inFunction);
if (value !== null){
values.push(value);
@@ -2829,11 +2832,11 @@ Parser.prototype = function(){
values.push(operator);
} /*else {
//if there's not an operator, you have a full value
- values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
- valueParts = [];
- }*/
+ values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
+ valueParts = [];
+ }*/
- value = this._term();
+ value = this._term(inFunction);
if (value === null){
break;
@@ -2843,7 +2846,7 @@ Parser.prototype = function(){
} while(true);
}
- //cleanup
+ //cleanup
/*if (valueParts.length){
values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
}*/
@@ -2851,7 +2854,7 @@ Parser.prototype = function(){
return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;
},
- _term: function(){
+ _term: function(inFunction){
/*
* term
@@ -2865,6 +2868,7 @@ Parser.prototype = function(){
var tokenStream = this._tokenStream,
unary = null,
value = null,
+ endChar = null,
token,
line,
col;
@@ -2885,6 +2889,20 @@ Parser.prototype = function(){
col = tokenStream.token().startCol;
}
+ //see if it's a simple block
+ } else if (inFunction && tokenStream.match([Tokens.LPAREN, Tokens.LBRACE, Tokens.LBRACKET])){
+
+ token = tokenStream.token();
+ endChar = token.endChar;
+ value = token.value + this._expr(inFunction).text;
+ if (unary === null){
+ line = tokenStream.token().startLine;
+ col = tokenStream.token().startCol;
+ }
+ tokenStream.mustMatch(Tokens.type(endChar));
+ value += endChar;
+ this._readWhitespace();
+
//see if there's a simple match
} else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,
Tokens.ANGLE, Tokens.TIME,
@@ -3529,17 +3547,23 @@ nth
['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*
;
*/
-
/*global Validation, ValidationTypes, ValidationError*/
var Properties = {
//A
+ "align-items" : "flex-start | flex-end | center | baseline | stretch",
+ "align-content" : "flex-start | flex-end | center | space-between | space-around | stretch",
+ "align-self" : "auto | flex-start | flex-end | center | baseline | stretch",
+ "-webkit-align-items" : "flex-start | flex-end | center | baseline | stretch",
+ "-webkit-align-content" : "flex-start | flex-end | center | space-between | space-around | stretch",
+ "-webkit-align-self" : "auto | flex-start | flex-end | center | baseline | stretch",
"alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ",
"alignment-baseline" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
"animation" : 1,
"animation-delay" : { multi: "