JsHint filter for Assetic

Yesterday at the university we were introduced to gulp.js. In an example we created some tasks for concatenating and minifying/uglifying JavaScript assets – quite the usual stuff you’ll use Assetic for in your Symfony projects.

But we also created a task which piped the assets through JsHint to perform code (quality) analysis. I really liked the idea of having an analysis run on your code on compilation time, so I looked for an existing JsHint filter for Assetic. Since I couldn’t find any (in an admittedly short Google search), I decided to quickly implement one on my own:

https://github.com/CodeLoversAt/assetic-jshint will pass the given asset through JsHint and throw a FilterException if any errors occurr. Since you might be interested in the actual file that produced the error, this filter will only work with a temporary file if it cannot determine the asset’s file name (like if you pass in an instance of a StringAsset).

As I mentioned in the first paragraph, I thought of using this filter in our Symfony projects from the beginning, so unsurprisingly I’ve also created a Symfony bundle which registers that filter:

https://github.com/CodeLoversAt/assetic-jshint-bundle

Here’s some example usage:

Lets consider the following two scripts. The first is called valid.js and it contains – as you might have guessed already – some simple, valid JavaScript

(function() {
    alert('I am valid!');
})();

The second one is called invalid.js and there we’ve forgotten a semicolon.

(function() {
    alert('I am invalid because I'm missing a semicolon at the end of this line!')
})();

Now we want to use this scripts in a template. First the valid one:

{% javascripts
[email protected]/Resources/public/js/valid.js'
output='compiled/js/demo_script.js' filter='jshint'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}

When we run app/console assetic:dump now, we won’t notice any difference, since the filter doesn’t have anything to complain about:

[email protected]:~/symfony$ app/console assetic:dump --env=prod --no-debug
Dumping all prod assets.
Debug mode is off.

13:26:13 [file+] /var/www/clients/client1/web65/symfony/app/../web/compiled/js/demo_script.js
[email protected]:~/symfony$ 

Now let’s see what happens if we add the invalid file to that asset:

{% javascripts
[email protected]/Resources/public/js/valid.js'
[email protected]/Resources/public/js/invalid.js'
output='compiled/js/demo_script.js' filter='jshint'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}

Again, we dump the assets, and here we go: a beautiful error appears:

[email protected]:~/symfony$ app/console assetic:dump --env=prod --no-debug
Dumping all prod assets.
Debug mode is off.

13:26:58 [file+] /var/www/clients/client1/web65/symfony/app/../web/compiled/js/demo_script.js



  [Assetic\Exception\FilterException]                                          
  An error occurred while running:                                             
  '/usr/local/bin/jshint' '/var/www/clients/client1/web65/symfony/src/CodeLov  
  ers/DemoBundle/Resources/public/js/invalid.js'                               

  Output:                                                                      
  /var/www/clients/client1/web65/symfony/src/CodeLovers/DemoBundle/Resources/  
  public/js/invalid.js: line 3, col 84, Missing semicolon.                     

  1 error                                                                      


  Input:                                                                       
  // some invalid JavaScript code                                              
  (function() {                                                                
      alert('I am invalid because I\'m missing a semicolon at the end of this  
   line!')                                                                     
  })();                                                                        



assetic:dump [--watch] [--force] [--period="..."] [write_to]


[email protected]:~/symfony$ 

As you can see, the error contains the real file name, where the error occurred. This should be quite helpful in real life scenarios.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax