diff --git a/README.md b/README.md index 022c456..2f3ad62 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,23 @@ Check recursively in the other directories: find -name \*.adoc -exec asciidoc-link-check -p {} \; ``` +### Ignore specific links + +1. Create a JSON config file containing ignore patterns: + ```json + { + "ignorePatterns": [ + { "pattern": "^https://192.17" }, + { "pattern": "^https://www.google" } + ] + + } + ``` +1. Use the config file option: + ``` + asciidoc-link-check README.adoc -c + ``` + Using in your node project -------------------------- @@ -81,10 +98,16 @@ API Use the following function: ``` javascript -asciidocLinkCheck(asciidoc, callback) +asciidocLinkCheck(asciidoc, [opts], callback) ``` -Accepts a string containing `asciidoc` formatted text and a `callback`, extracts all links and checks if they are alive or dead. Then calls the `callback` with `(err, results)`. +Accepts a string containing `asciidoc` formatted text and a `callback` function, +extracts all links and checks if they are alive or dead. Then calls the +`callback` function with `(err, results)`. + +- `opts` optional objects + + - `ignorePatterns`: An array of objects of regular expressions patterns. Examples ======== diff --git a/asciidoc-link-check b/asciidoc-link-check index 659dba1..4350bb4 100755 --- a/asciidoc-link-check +++ b/asciidoc-link-check @@ -12,14 +12,20 @@ var path = require('path'); var statusLabels = { alive: chalk.green('✓'), - dead: chalk.red('✖') + dead: chalk.red('✖'), + ignored: chalk.gray('~') }; var error = false; var opts = {}; var filenameOutput = ""; var stream = process.stdin; // read from stdin unless a filename is given -program.option('-p, --progress', 'show progress bar').arguments('[filenameOrUrl]').action(function (filenameOrUrl) { +program +.option('-p, --progress', 'Show progress bar') +.option('-c, --config [config]', 'Use a JSON config file') +.option('-q, --quiet', 'Display errors only') +.arguments('[filenameOrUrl]') +.action(function (filenameOrUrl) { filenameOutput = filenameOrUrl; if (/https?:/.test(filenameOrUrl)) { stream = request.get(filenameOrUrl); @@ -37,30 +43,76 @@ program.option('-p, --progress', 'show progress bar').arguments('[filenameOrUrl] stream = fs.createReadStream(filenameOrUrl); } }) - .parse(process.argv); +.parse(process.argv); opts.showProgressBar = (program.progress === true); // force true or undefined to be true or false. +opts.quiet = (program.quiet === true); var asciidoc = ''; // collect the asciidoc data, then process it stream.on('data', function (chunk) { asciidoc += chunk.toString(); }).on('end', function () { console.log(chalk.cyan('\nFILE: ' + filenameOutput)) - asciidocLinkCheck(asciidoc, opts, function (err, results) { - if (results.length === 0) { - console.log(chalk.yellow('No hyperlinks found!\n')) + if (program.config) { + fs.access(program.config, fs.constants.R_OK, function (err) { + if (!err) { + let configStream = fs.createReadStream(program.config); + let configData = ''; + + configStream.on('data', function (chunk) { + configData += chunk.toString(); + }).on('end', function () { + let config = JSON.parse(configData); + + opts.ignorePatterns = config.ignorePatterns; + + runasciidocLinkCheck(asciidoc, opts); + }); + } + else { + console.error(chalk.red('\nERROR: Can\'t access configuration file.')); + process.exit(1); + } + }); + } + else { + runasciidocLinkCheck(asciidoc, opts); + } +}); + +function runasciidocLinkCheck(asciidoc, opts) { + +asciidocLinkCheck(asciidoc, opts, function (err, results) { + + if (results.length === 0) { + console.log(chalk.yellow('No hyperlinks found!\n')) + } + results.forEach(function (result) { + if (result.status === 'dead') { + error = true; } - results.forEach(function (result) { - if (result.status === 'dead') { - error = true; + + // Skip messages for non-deadlinks in quiet mode. + if (opts.quiet && result.status !== 'dead') { + return; + } + + switch(result.status) { + case 'dead': console.log('[%s] %s', statusLabels[result.status], chalk.red(result.link)); - } else + break; + case 'ignored': + console.log('[%s] %s', statusLabels[result.status], chalk.gray(result.link)); + break; + default: console.log('[%s] %s', statusLabels[result.status], result.link); - }); - if (error) { - console.error(chalk.red('ERROR: dead links found!\n')); - process.exit(1); - } + } + }); -}); \ No newline at end of file + if (error) { + console.error(chalk.red('ERROR: dead links found!\n')); + process.exit(1); + } +}); +} \ No newline at end of file diff --git a/index.js b/index.js index b949c76..ee2834e 100644 --- a/index.js +++ b/index.js @@ -25,6 +25,23 @@ module.exports = function asciidocLinkCheck(asciidoc, opts, callback) { } async.mapLimit(linksCollection, 2, function (link, callback) { + if (opts.ignorePatterns) { + let shouldIgnore = opts.ignorePatterns.some(function(ignorePattern) { + return ignorePattern.pattern instanceof RegExp ? ignorePattern.pattern.test(link) : (new RegExp(ignorePattern.pattern)).test(link) ? true : false; + }); + + if (shouldIgnore) { + let linkCheckResult = {}; + + linkCheckResult.link = link; + linkCheckResult.statusCode = 0; + linkCheckResult.status = 'ignored'; + bar.tick(); + callback(null, linkCheckResult); + return; + } + } + linkCheck(link, opts, function (err, result) { if (opts.showProgressBar) { bar.tick();