JSCodeSniffer v.2.x
JSCodeSniffer is a node.js application that checks JavaScript code style consistency according to a provided coding style, just like phpcs. One can define a custom coding style by using described below JSON notation or use one of predefined standards.
Features
- Tool is available as UMD (can be used with nodejs or as a RequireJS module)
- Predefined popular coding styles (jQuery Coding Style Guide, Idiomatic Style Manifesto)
- Reports in the style of phpcs
- Solution ready for Continuous Integration
- Provided Git pre-commit hook script
- Provided SVN pre-commit hook script
- Provided Grunt task
- Provided Jenkins CheckStyle report
- Custom standard can be easily configured by using JSON notation
- Scripts can be associated to a coding style in block comments using
jscs
tag - Relaxing options can be provided with real-time configuration (
.jscsrc
) per project - Thoroughly covered with automated tests: 200+ unit-tests, 70+ integration tests
Setup
JS_CodeSniffer relies on node.js. If you don't have node.js installed, just follow the instructions: https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager
Make sure all the required dependencies installed
npm i
Make sure the binary is executable
chmod +x jscs
You can also create a symlink to make it globally available
ln -s jscs /usr/local/bin/jscs
Using JSCodeSniffer in the command line
Simply get detailed report on a target (file or directory) coding style according to jQuery Coding Style Guide
./jscs source-code.js --standard=Jquery
or
node jscs.js source-code.js --standard=Jquery
or
./jscs js/dir1 file1.js js/dir2 file2.js --standard=Jquery
Get detailed report on the coding style for all .js/.json files of the 'lib' folder according to jQuery Coding Style Guide
./jscs lib --standard=Jquery --report-full
Get summary report
./jscs lib --report-summary
Get XML report (which allows you to parse the output easily and use the results in your own scripts)
./jscs lib --report=xml
Get Checkstyle report (that is supported by wide range of 3rd party software. E.g. Jenkins via a plugin)
./jscs lib --report=checkstyle
Report to a file (by default report goes to stdout)
./jscs lib --report-file=filePath
Disable colors in the report
./jscs lib --highlight=0
Define width of report screen
./jscs lib --reportWidth=84
Using JSCodeSniffer as RequireJS (AMD) module
- Install the package or download and unpack it into you project folder
npm i jscodesniffer
- Use RequireJS to load required modules
;
Environments
Standard to sniff against can be enforced on the file by following instructions directly in the code
/* jscs standard:Jquery */
Old form introduced in version 1.x.x is also supported
/* @jscs standard:Jquery */
Real-Time Configuration
Adjusting options can be provided as manual standard in .jscsrc
file placed in the root of your project.
JSCodesniffer will search upward recursively until it finds any. It will extend the specified standard rule-sets
with the defenitions provided in this real-time configuration file. .jscsrc
syntax is pretty much the same as standard
defenition file except it doesn't need to be UMD (just JSON). I you need disable particular rule-sets you can simply
empty rule-set configurations:
Declaring coding style
Standard declaration are located in standard
directory. You can store there in a file named after your custom standard name
the rule-sets that you want your code be validated against. To make the defenition available for AMD/RequireJs, the JSON notation is supposed
to be wrapped as a UMD module.
NOTE: Conventions 'Any ; used as a statement terminator must be at the end of the line' and 'Multi-line Statements is checked' are tested by JSHint and therefore not provided with sniffs (See [http://contribute.jquery.org/style-guide/js/#linting] for details).
/* defines what characters allowed for line indentation */ "Indentation": "allowOnlyTabs": true "allowOnlySpaces": true "disallowMixed": true /* defines if trailing spaces allowed for lines */ "LineSpacing": "allowLineTrailingSpaces": false /* defines allowed range for line length */ "LineLength": "allowMaxLength": 80 "allowMinLength": 0 /* defines spacing conventions for comma punctuator Example: // good var foo, bar; // bad var foo , bar; */ "CommaPunctuatorSpacing": "disallowPrecedingSpaces": false /* defines spacing conventions for semicolon punctuator Example: // good var foo; // bad var foo ; */ "SemicolonPunctuatorSpacing": "disallowPrecedingSpaces": false /* defines scoping rules for compound statements Example: // good if ( true ) { var foo = "bar"; } // bad if ( true ) var foo = "bar"; */ "CompoundStatementConventions": "for": "IfStatement" "SwitchStatement" "WhileStatement" "DoWhileStatement" "ForStatement" "ForInStatement" "WithStatement" "TryStatement" "requireBraces": true "requireMultipleLines": true /* defines spacing conventions for unary expressions Example: !!100 // good !! 100 // bad */ "UnaryExpressionIdentifierSpacing": "allowTrailingWhitespaces" : 0 /* defines spacing conventions for ternary conditionals Example: foo = true ? 1 : 0; // good foo = true ?1:0; // bad */ "TernaryConditionalPunctuatorsSpacing": "allowTestTrailingWhitespaces": 1 "allowConsequentPrecedingWhitespaces": 1 "allowConsequentTrailingWhitespaces": 1 "allowAlternatePrecedingWhitespaces": 1 /* Optional modifier. When undefined the sniffer treats nesting statements the same as regular When false, no rules applied for nesting statements When defined, the corresponding rules go for nesting statements foo( a?b:c ) */ "ifNesting": "allowTestTrailingWhitespaces": 0 "allowConsequentPrecedingWhitespaces": 0 "allowConsequentTrailingWhitespaces": 0 "allowAlternatePrecedingWhitespaces": 0 /* defines spacing conventions for empty constructs "for" qualifier takes an array of tokens compatible with Mozilla Parser AST (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API) Example: obj = {}; // good obj = { }; // bad */ "EmptyConstructsSpacing": "for": "ObjectExpression" "ArrayExpression" "CallExpression" "allowWhitespaces": false /* defines spacing conventions for object literals Example: obj = { prop: 1 }; // good obj = { prop:1 };// bad */ "ObjectLiteralSpacing": "allowKeyPrecedingWhitespaces": 1 "allowKeyTrailingWhitespaces": 0 "allowValuePrecedingWhitespaces": 1 "allowValueTrailingWhitespaces": 1 /* defines spacing conventions for array literals Example: arr = [ 1, 2 ]; // good arr = [1,2]; // bad */ "ArrayLiteralSpacing": "allowElementPrecedingWhitespaces": 1 "allowElementTrailingWhitespaces": 1 /* Optional modifier. "for" qualifier takes an array of tokens compatible with Mozilla Parser AST (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API) When qualifier "for" is missing the exception rules gets applied for any node type */ "exceptions": "singleElement": "for": "Literal" "allowElementPrecedingWhitespaces": 0 "allowElementTrailingWhitespaces": 0 "firstElement": "for": "Literal" "allowElementPrecedingWhitespaces": 1 "lastElement": "for": "Literal" "allowElementTrailingWhitespaces": 1 /* defines type of quotes to use across the code-base Example: foo = "text"; // good foo = 'text'; // bad */ "QuoteConventions": "allowDoubleQuotes": true "allowSingleQuotes": false /* defines naming conventions for variables Note: variable of all uppercase (including $_0-9) are considered as constants and ignored by the sniffer Example: var camelCase; // good var not_camel_case; // bad */ "VariableNamingConventions": "allowCase": "camel" "allowRepeating": true "allowNumbers": true /* defines naming conventions for functions Example: var PascalCase; // good var not_camel_or_pascal_case; // bad */ "FunctionNamingConventions": "allowCase": "camel" "pascal" "allowRepeating": true "allowNumbers": true /* defines naming conventions for new expressions Example: obj = new Constructor(); // good obj = new constructor(); // bad */ "NewExpressionCalleeNamingConventions": "allowCase": "pascal" "allowRepeating": true "allowNumbers": true /* defines spacing conventions for arguments Example: fn( 1, 2 ); // good fn(1,2); // bad */ "ArgumentsSpacing": "allowArgPrecedingWhitespaces": 1 "allowArgTrailingWhitespaces": 1 /* Optional modifier. "for" qualifier takes an array of tokens compatible with Mozilla Parser AST (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API) When qualifier "for" is missing the exception rules gets applied for any node type */ "exceptions": "singleArg" : "for": "FunctionExpression" "ArrayExpression" "ObjectExpression" "allowArgPrecedingWhitespaces": 0 "allowArgTrailingWhitespaces": 0 "firstArg": "for": "FunctionExpression" "allowArgPrecedingWhitespaces": 0 "lastArg": "for": "FunctionExpression" "allowArgTrailingWhitespaces": 0 /* Optional modifier. When undefined the sniffer treats nesting statements the same as regular When false, no rules applied for nesting statements When defined, the corresponding rules go for nesting statements foo( bar(1,1) ) */ "ifNesting": "allowArgPrecedingWhitespaces": 0 "allowArgTrailingWhitespaces": 0 /* defines spacing conventions for parameters Example: function fn( foo, bar ){}; // good function fn(foo,bar){}; // bad */ "ParametersSpacing": "allowParamPrecedingWhitespaces": 1 "allowParamTrailingWhitespaces": 1 /* Optional modifier. When qualifier "for" is missing the exception rules gets applied for any node type */ "exceptions": "singleParam": "for": "Literal" "allowElementPrecedingWhitespaces": 0 "allowElementTrailingWhitespaces": 0 "firstParam": "for": "Literal" "allowElementPrecedingWhitespaces": 1 "lastParam": "for": "Literal" "allowElementTrailingWhitespaces": 1 /* defines how methods can be placed when a chain of method calls is too long to fit on one line Example: // good elements .addClass( "foo" ) .children(); // bad elements.addClass( "foo" ) .children(); */ "ChainedMethodCallsPerLineConventions": "requireOnePerLineWhenMultilineCaller": true /* defines spacing conventions for chains of method calls Example: // good elements.addClass( "foo" ) // bad elements. addClass( "foo" ) */ "ChainedMethodCallsSpacing": "allowPrecedingPropertyWhitespaces": 0 /* defines spacing conventions for operators (including declarator) Example: foo = 1 + 1; // good foo = 1+1; // bad */ "OperatorSpacing" : "allowOperatorPrecedingWhitespaces": 1 "allowOperatorTrailingWhitespaces": 1 /* defines conventions for variable declarations Example: // good (function(){ var foo, bar; })(); // bad (function(){ var foo; var bar; })(); */ "VariableDeclarationPerScopeConventions" : "disallowMultiplePerBlockScope": true "requireInTheBeginning": true /* defines conventions for object declarations Example: // good o = { p1: 1, p2: 2 } // good o = { p1: 1, p2: 2 } // bad o = { p1: 1, p2: 2 } */ "ObjectLiteralConventions": "requireOnePerLineWhenMultiline": true /* defines conventions for array declarations Example: // good arr = [ 1, "two" ] // good arr = [ 1, "two" ] // bad arr = [ 1, "two" ] */ "ArrayLiteralConventions": "requireOnePerLineWhenMultiline": true
JSCodeSniffer and Continuous Integration
Setting up Apache Ant build script reporting to Jenkins Checkstyle plugin.
NOTE: If you have phpcs-ci ant target, invoke it prior to this one. Jscs will find created by phpcs checkstyle.xml and extend its body instead of overriding the report.
Setting up Grunt task
Gruntfile.js
grunt;grunt;
package.json
"devDependencies": //.. "grunt-contrib-jscs": "*"
Using the Subversion pre-commit hook
A pre-commit hook is a feature available in the Subversion version control system that allows code to be validated before it is committed to the repository. Edit scripts/jscs-svn-pre-commit and replace JSCS value with your own path to JS CodeSniffer
JSCS = "/your-path/jscodesniffer"
Make a symlink of scripts/jscs-svn-pre-commit in your repository hooks folder. E.g.
ln -s /<full path>/scripts/jscs-svn-pre-commit /repositories/<project>/hooks/pre-commit
Using the git pre-commit hook
Make a symlink of scripts/jscs-git-pre-commit in your repository .git/hooks folder. E.g.
ln -s /<full path>/scripts/jscs-git-pre-commit /<project>/.git/hooks/pre-commit