l0bsterssg

node.js static responsive blog post generator
Log | Files | Refs | README

esvalidate.js (7744B)


      1 #!/usr/bin/env node
      2 /*
      3   Copyright JS Foundation and other contributors, https://js.foundation/
      4 
      5   Redistribution and use in source and binary forms, with or without
      6   modification, are permitted provided that the following conditions are met:
      7 
      8     * Redistributions of source code must retain the above copyright
      9       notice, this list of conditions and the following disclaimer.
     10     * Redistributions in binary form must reproduce the above copyright
     11       notice, this list of conditions and the following disclaimer in the
     12       documentation and/or other materials provided with the distribution.
     13 
     14   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     15   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
     18   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24 */
     25 
     26 /*jslint sloppy:true plusplus:true node:true rhino:true */
     27 /*global phantom:true */
     28 
     29 var fs, system, esprima, options, fnames, forceFile, count;
     30 
     31 if (typeof esprima === 'undefined') {
     32     // PhantomJS can only require() relative files
     33     if (typeof phantom === 'object') {
     34         fs = require('fs');
     35         system = require('system');
     36         esprima = require('./esprima');
     37     } else if (typeof require === 'function') {
     38         fs = require('fs');
     39         try {
     40             esprima = require('esprima');
     41         } catch (e) {
     42             esprima = require('../');
     43         }
     44     } else if (typeof load === 'function') {
     45         try {
     46             load('esprima.js');
     47         } catch (e) {
     48             load('../esprima.js');
     49         }
     50     }
     51 }
     52 
     53 // Shims to Node.js objects when running under PhantomJS 1.7+.
     54 if (typeof phantom === 'object') {
     55     fs.readFileSync = fs.read;
     56     process = {
     57         argv: [].slice.call(system.args),
     58         exit: phantom.exit,
     59         on: function (evt, callback) {
     60             callback();
     61         }
     62     };
     63     process.argv.unshift('phantomjs');
     64 }
     65 
     66 // Shims to Node.js objects when running under Rhino.
     67 if (typeof console === 'undefined' && typeof process === 'undefined') {
     68     console = { log: print };
     69     fs = { readFileSync: readFile };
     70     process = {
     71         argv: arguments,
     72         exit: quit,
     73         on: function (evt, callback) {
     74             callback();
     75         }
     76     };
     77     process.argv.unshift('esvalidate.js');
     78     process.argv.unshift('rhino');
     79 }
     80 
     81 function showUsage() {
     82     console.log('Usage:');
     83     console.log('   esvalidate [options] [file.js...]');
     84     console.log();
     85     console.log('Available options:');
     86     console.log();
     87     console.log('  --format=type  Set the report format, plain (default) or junit');
     88     console.log('  -v, --version  Print program version');
     89     console.log();
     90     process.exit(1);
     91 }
     92 
     93 options = {
     94     format: 'plain'
     95 };
     96 
     97 fnames = [];
     98 
     99 process.argv.splice(2).forEach(function (entry) {
    100 
    101     if (forceFile || entry === '-' || entry.slice(0, 1) !== '-') {
    102         fnames.push(entry);
    103     } else if (entry === '-h' || entry === '--help') {
    104         showUsage();
    105     } else if (entry === '-v' || entry === '--version') {
    106         console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
    107         console.log();
    108         process.exit(0);
    109     } else if (entry.slice(0, 9) === '--format=') {
    110         options.format = entry.slice(9);
    111         if (options.format !== 'plain' && options.format !== 'junit') {
    112             console.log('Error: unknown report format ' + options.format + '.');
    113             process.exit(1);
    114         }
    115     } else if (entry === '--') {
    116         forceFile = true;
    117     } else {
    118         console.log('Error: unknown option ' + entry + '.');
    119         process.exit(1);
    120     }
    121 });
    122 
    123 if (fnames.length === 0) {
    124     fnames.push('');
    125 }
    126 
    127 if (options.format === 'junit') {
    128     console.log('<?xml version="1.0" encoding="UTF-8"?>');
    129     console.log('<testsuites>');
    130 }
    131 
    132 count = 0;
    133 
    134 function run(fname, content) {
    135     var timestamp, syntax, name;
    136     try {
    137         if (typeof content !== 'string') {
    138             throw content;
    139         }
    140 
    141         if (content[0] === '#' && content[1] === '!') {
    142             content = '//' + content.substr(2, content.length);
    143         }
    144 
    145         timestamp = Date.now();
    146         syntax = esprima.parse(content, { tolerant: true });
    147 
    148         if (options.format === 'junit') {
    149 
    150             name = fname;
    151             if (name.lastIndexOf('/') >= 0) {
    152                 name = name.slice(name.lastIndexOf('/') + 1);
    153             }
    154 
    155             console.log('<testsuite name="' + fname + '" errors="0" ' +
    156                 ' failures="' + syntax.errors.length + '" ' +
    157                 ' tests="' + syntax.errors.length + '" ' +
    158                 ' time="' + Math.round((Date.now() - timestamp) / 1000) +
    159                 '">');
    160 
    161             syntax.errors.forEach(function (error) {
    162                 var msg = error.message;
    163                 msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
    164                 console.log('  <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
    165                     ' time="0">');
    166                 console.log('    <error type="SyntaxError" message="' + error.message + '">' +
    167                     error.message + '(' + name + ':' + error.lineNumber + ')' +
    168                     '</error>');
    169                 console.log('  </testcase>');
    170             });
    171 
    172             console.log('</testsuite>');
    173 
    174         } else if (options.format === 'plain') {
    175 
    176             syntax.errors.forEach(function (error) {
    177                 var msg = error.message;
    178                 msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
    179                 msg = fname + ':' + error.lineNumber + ': ' + msg;
    180                 console.log(msg);
    181                 ++count;
    182             });
    183 
    184         }
    185     } catch (e) {
    186         ++count;
    187         if (options.format === 'junit') {
    188             console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
    189                 ' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
    190             console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
    191             console.log(' <error type="ParseError" message="' + e.message + '">' +
    192                 e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
    193                 ')</error>');
    194             console.log(' </testcase>');
    195             console.log('</testsuite>');
    196         } else {
    197             console.log(fname + ':' + e.lineNumber + ': ' + e.message.replace(/^Line\ [0-9]*\:\ /, ''));
    198         }
    199     }
    200 }
    201 
    202 fnames.forEach(function (fname) {
    203     var content = '';
    204     try {
    205         if (fname && (fname !== '-' || forceFile)) {
    206             content = fs.readFileSync(fname, 'utf-8');
    207         } else {
    208             fname = '';
    209             process.stdin.resume();
    210             process.stdin.on('data', function(chunk) {
    211                 content += chunk;
    212             });
    213             process.stdin.on('end', function() {
    214                 run(fname, content);
    215             });
    216             return;
    217         }
    218     } catch (e) {
    219         content = e;
    220     }
    221     run(fname, content);
    222 });
    223 
    224 process.on('exit', function () {
    225     if (options.format === 'junit') {
    226         console.log('</testsuites>');
    227     }
    228 
    229     if (count > 0) {
    230         process.exit(1);
    231     }
    232 
    233     if (count === 0 && typeof phantom === 'object') {
    234         process.exit(0);
    235     }
    236 });