diff --git a/lib/cli.js b/lib/cli.js index 70a0ad51..b84b053f 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -21,9 +21,9 @@ function cli() filterLevel += " 2: 1 + stylesheets, scripts, forms\n"; filterLevel += " 3: 2 + metadata\n"; filterLevel += " Default: "+defaultOptions.filterLevel; - + this.nopter = new nopter(); - + this.nopter.config( { title: "Broken Link Checker", @@ -83,6 +83,12 @@ function cli() info: "URL to an HTML document.", type: require("url") }, + "quiet": + { + short: ["q"], + info: "Quiet mode - only show broken links.", + type: Boolean + }, "host-requests": { rename: "maxSocketsPerHost", @@ -139,9 +145,9 @@ cli.prototype.input = function(args, showArgs) { //var testing = args !== undefined; args = this.nopter.input(args); - + //if (testing===true && showArgs===true) return args; - + if (args.help === true) { log( this.nopter.help() ); @@ -157,7 +163,7 @@ cli.prototype.input = function(args, showArgs) { args.excludedKeywords = defaultOptions.excludedKeywords; } - + run(args.input, { excludedKeywords: args.excludedKeywords, @@ -176,7 +182,8 @@ cli.prototype.input = function(args, showArgs) excludeFilteredLinks: args.verbose!==true, maintainLinkOrder: args.maintainLinkOrder, recursive: args.recursive - }); + }, + args.quiet); } else { @@ -191,41 +198,45 @@ function log() { // Avoid spinner chars getting stuck in the log spinner.clear(); - + console.log.apply(null, arguments); } -function logMetrics(brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit) +function logMetrics(quiet, brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit) { + var output = preBreak===true ? "\n" : ""; - + output += chalk.gray("Finished! "+totalLinks+" links found."); - + if (excludedLinks > 0) { output += chalk.gray(" "+excludedLinks+" excluded."); } - + if (totalLinks > 0) { output += chalk.gray(" "); output += chalk[ brokenLinks>0 ? "red" : "green" ](brokenLinks+" broken"); output += chalk.gray("."); } - + if (duration != null) { output += chalk.gray("\nElapsed time: "); output += chalk.gray( humanizeDuration(duration, {round:true, largest:2}) ); } - - log(output); + + if (!quiet || brokenLinks > 0) { + log(output); + } if (exit === true) { - process.exit(brokenLinks===0 ? 0 : 1); + console.log('logMetrics exit', {brokenLinks}) + process.exit(brokenLinks === 0 ? 0 : 1); } } @@ -234,11 +245,11 @@ function logMetrics(brokenLinks, excludedLinks, totalLinks, duration, preBreak, /* Ensure that `logMetrics()` is called after `logResults_delayed()`. */ -function logMetrics_delayed(brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit) +function logMetrics_delayed(quiet, brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit) { setImmediate( function() { - logMetrics(brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit); + logMetrics(quiet, brokenLinks, excludedLinks, totalLinks, duration, preBreak, exit); }); } @@ -247,25 +258,25 @@ function logMetrics_delayed(brokenLinks, excludedLinks, totalLinks, duration, pr function logPage(data, pageUrl) { var output = ""; - - if (++data.total.pages > 1) output += "\n"; - + + if (data.total.pages > 1) output += "\n"; + output += chalk.white("Getting links from: ") + chalk.yellow(pageUrl); - + log(output); } -function logResult(result, finalResult) +function logResult(result, finalResult, quiet) { var output = ""; - + if (result.__cli_excluded !== true) { // TODO :: if later results are skipped, the last RENDERED result will not be "└─" output = chalk.gray( finalResult!==true ? "├─" : "└─" ); - + if (result.broken === true) { output += chalk.red("BROKEN"); @@ -281,7 +292,7 @@ function logResult(result, finalResult) output += chalk.green("OK"); output += chalk.gray("─── "); } - + if (result.url.resolved != null) { output += chalk.yellow( result.url.resolved ); @@ -291,7 +302,7 @@ function logResult(result, finalResult) // Excluded scheme output += chalk.yellow( result.url.original ); } - + if (result.broken === true) { output += chalk.gray(" ("+ result.brokenReason +")"); @@ -306,7 +317,7 @@ function logResult(result, finalResult) output += chalk.gray(" (CACHED)"); } } - + return output; } @@ -316,24 +327,24 @@ function logResult(result, finalResult) Logs links in the order that they are found in their containing HTML document, even if later links receive an earlier response. */ -function logResults(data) +function logResults(data, quiet) { var done,output,result; var nextIsReady = true; - + while (nextIsReady) { result = data.page.results[data.page.currentIndex]; - + if (result !== undefined) { done = data.page.done===true && data.page.currentIndex>=data.page.results.length-1; - - output = logResult(result, done); - + + output = logResult(result, done, quiet); + if (output !== "") log(output); if (done === true) return; - + data.page.currentIndex++; } else @@ -348,14 +359,14 @@ function logResults(data) /* Ensure that `logResults()` is called after `data.page.done=true`. */ -function logResults_delayed(data) +function logResults_delayed(data, quiet) { // Avoid more than one delay via multiple synchronous iterations if (data.delay === null) { data.delay = setImmediate( function() { - logResults(data); + logResults(data, quiet); data.delay = null; }); } @@ -390,10 +401,10 @@ function resetPageData(data) -function run(url, checkerOptions, logOptions) +function run(url, checkerOptions, logOptions, quiet) { var handlers,instance; - var data = + var data = { delay: null, page: {}, @@ -406,33 +417,46 @@ function run(url, checkerOptions, logOptions) startTime: Date.now() } }; - + // In case first page doesn't call "html" handler resetPageData(data); - - handlers = + + var quietPageLogger = null + + var possibleLogPage = function (data, pageUrl) { + data.total.pages ++ + if (quiet) { + quietPageLogger = function () { + logPage(data, pageUrl); + } + } else { + logPage(data, pageUrl); + } + } + + handlers = { html: function(tree, robots, response, pageUrl) { resetPageData(data); - - logPage(data, pageUrl); + + possibleLogPage(data, pageUrl); }, junk: function(result) { if (logOptions.excludeFilteredLinks === true) { result.__cli_excluded = true; - + data.page.excludedLinks++; data.total.excludedLinks++; } - + data.page.totalLinks++; data.total.links++; - + pushResult(data, result, logOptions); - + logResults_delayed(data); }, link: function(result) @@ -441,7 +465,7 @@ function run(url, checkerOptions, logOptions) if (result.broken===false && result.http.cached===true && logOptions.excludeCachedLinks===true) { result.__cli_excluded = true; - + data.page.excludedLinks++; data.total.excludedLinks++; } @@ -450,12 +474,30 @@ function run(url, checkerOptions, logOptions) data.page.brokenLinks++; data.total.brokenLinks++; } - + + if (quiet) { + if (result.broken===true){ + if (quietPageLogger){ + quietPageLogger() + quietPageLogger = null + } + } else { + // not broken + result.__cli_excluded = true; + } + } else { + // not quiet + if (quietPageLogger){ + quietPageLogger() + quietPageLogger = null + } + } + data.page.totalLinks++; data.total.links++; - + pushResult(data, result, logOptions); - + logResults_delayed(data); }, page: function(error, pageUrl) @@ -463,34 +505,36 @@ function run(url, checkerOptions, logOptions) if (error != null) { // "html" handler will not have been called - logPage(data, pageUrl); - + possibleLogPage(data, pageUrl); + log( chalk[ error.code!==200 ? "red" : "gray" ](error.name+": "+error.message) ); } else { data.page.done = true; - - logMetrics_delayed(data.page.brokenLinks, data.page.excludedLinks, data.page.totalLinks); + + logMetrics_delayed(quiet, data.page.brokenLinks, data.page.excludedLinks, data.page.totalLinks); } }, end: function() { if (data.total.pages <= 0) { - process.exit(1); - } - else if (data.total.pages === 1) - { + console.log('Pages <= 0', data.total) + process.exit(1); + } + else if (data.total.pages === 1) + { + console.log('Pages === 1', data.total); process.exit(data.page.done===true && data.total.brokenLinks===0 ? 0 : 1); } else if (data.total.pages > 1) { - logMetrics_delayed(data.total.brokenLinks, data.total.excludedLinks, data.total.links, Date.now()-data.total.startTime, true, true); + logMetrics_delayed(quiet, data.total.brokenLinks, data.total.excludedLinks, data.total.links, Date.now()-data.total.startTime, true, true); } } }; - + if (logOptions.recursive !== true) { instance = new blc.HtmlUrlChecker(checkerOptions, handlers); @@ -499,9 +543,9 @@ function run(url, checkerOptions, logOptions) { instance = new blc.SiteChecker(checkerOptions, handlers); } - + spinner(); - + instance.enqueue(url); }