Skip to content

Commit

Permalink
Merge pull request #364 from dudeofawesome/feat/reporters
Browse files Browse the repository at this point in the history
✨ add support for additional test reporters
  • Loading branch information
tcort authored Nov 5, 2024
2 parents 29694c8 + e5958fe commit 02c0ddb
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 57 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
.tern-port
junit.xml
72 changes: 17 additions & 55 deletions markdown-link-check
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

let chalk;
const fs = require('fs');
const markdownLinkCheck = require('./');
const { promisify } = require('util');
const markdownLinkCheck = promisify(require('./'));
const needle = require('needle');
const path = require('path');
const pkg = require('./package.json');
Expand All @@ -30,6 +31,10 @@ function commaSeparatedCodesList(value, dummyPrevious) {
});
}

function commaSeparatedReportersList(value) {
return value.split(',').map((reporter) => require(path.resolve('reporters', reporter)));
}

function getInputs() {
const inputs = [];

Expand All @@ -42,6 +47,7 @@ function getInputs() {
.option('-i --ignore <paths>', 'ignore input paths including an ignore path', commaSeparatedPathsList)
.option('-a, --alive <code>', 'comma separated list of HTTP codes to be considered as alive', commaSeparatedCodesList)
.option('-r, --retry', 'retry after the duration indicated in \'retry-after\' header when HTTP code is 429')
.option('--reporters <names>', 'specify reporters to use', commaSeparatedReportersList)
.option('--projectBaseUrl <url>', 'the URL to use for {{BASEURL}} replacement')
.arguments('[filenamesOrUrls...]')
.action(function (filenamesOrUrls) {
Expand Down Expand Up @@ -121,6 +127,7 @@ function getInputs() {
input.opts.verbose = (program.opts().verbose === true);
input.opts.retryOn429 = (program.opts().retry === true);
input.opts.aliveStatusCodes = program.opts().alive;
input.opts.reporters = program.opts().reporters ?? [require(path.resolve('reporters', 'default.js'))];
const config = program.opts().config;
if (config) {
input.opts.config = config.trim();
Expand Down Expand Up @@ -195,68 +202,23 @@ async function processInput(filenameForOutput, stream, opts) {
opts.retryCount = config.retryCount;
opts.fallbackRetryDelay = config.fallbackRetryDelay;
opts.aliveStatusCodes = config.aliveStatusCodes;
opts.reporters = config.reporters;
}

await runMarkdownLinkCheck(filenameForOutput, markdown, opts);
}

async function runMarkdownLinkCheck(filenameForOutput, markdown, opts) {
const statusLabels = {
alive: chalk.green('✓'),
dead: chalk.red('✖'),
ignored: chalk.gray('/'),
error: chalk.yellow('⚠'),
};

return new Promise((resolve, reject) => {
markdownLinkCheck(markdown, opts, function (err, results) {
if (err) {
console.error(chalk.red('\n ERROR: something went wrong!'));
console.error(err.stack);
reject();
}

if (results.length === 0 && !opts.quiet) {
console.log(chalk.yellow(' No hyperlinks found!'));
}
results.forEach(function (result) {
// Skip messages for non-deadlinks in quiet mode.
if (opts.quiet && result.status !== 'dead') {
return;
}

if (opts.verbose) {
if (result.err) {
console.log(' [%s] %s → Status: %s %s', statusLabels[result.status], result.link, result.statusCode, result.err);
} else {
console.log(' [%s] %s → Status: %s', statusLabels[result.status], result.link, result.statusCode);
}
}
else if(!opts.quiet) {
console.log(' [%s] %s', statusLabels[result.status], result.link);
}
});
const [err, results] = await markdownLinkCheck(markdown, opts)
.then(res => [null, res]).catch(err => [err]);

if(!opts.quiet){
console.log('\n %s links checked.', results.length);
}

if (results.some((result) => result.status === 'dead')) {
let deadLinks = results.filter(result => { return result.status === 'dead'; });
if(!opts.quiet){
console.error(chalk.red('\n ERROR: %s dead links found!'), deadLinks.length);
} else {
console.error(chalk.red('\n ERROR: %s dead links found in %s !'), deadLinks.length, filenameForOutput);
}
deadLinks.forEach(function (result) {
console.log(' [%s] %s → Status: %s', statusLabels[result.status], result.link, result.statusCode);
});
reject();
}
await Promise.allSettled(
opts.reporters.map(reporter => reporter(err, results, opts, filenameForOutput)
));

resolve();
});
});
if (err) throw null;
else if (results.some((result) => result.status === 'dead')) return;
else return;
}

async function main() {
Expand Down
153 changes: 152 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"markdown-link-extractor": "^4.0.2",
"needle": "^3.3.1",
"progress": "^2.0.3",
"proxy-agent": "^6.4.0"
"proxy-agent": "^6.4.0",
"xmlbuilder2": "^3.1.1"
},
"devDependencies": {
"@eslint/js": "^9.3.0",
Expand Down
59 changes: 59 additions & 0 deletions reporters/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module.exports = async function defaultReporter(err, results, opts, filenameForOutput) {
const chalk = (await import('chalk')).default

const statusLabels = {
alive: chalk.green('✓'),
dead: chalk.red('✖'),
ignored: chalk.gray('/'),
error: chalk.yellow('⚠'),
};

if (err) {
console.error(chalk.red("\n ERROR: something went wrong!"));
console.error(err.stack);
}

if (results.length === 0 && !opts.quiet) {
console.log(chalk.yellow(" No hyperlinks found!"));
}
results.forEach(function (result) {
// Skip messages for non-deadlinks in quiet mode.
if (opts.quiet && result.status !== "dead") {
return;
}

if (opts.verbose) {
if (result.err) {
console.log(
" [%s] %s → Status: %s %s",
statusLabels[result.status],
result.link,
result.statusCode,
result.err
);
} else {
console.log(" [%s] %s → Status: %s", statusLabels[result.status], result.link, result.statusCode);
}
} else if (!opts.quiet) {
console.log(" [%s] %s", statusLabels[result.status], result.link);
}
});

if (!opts.quiet) {
console.log("\n %s links checked.", results.length);
}

if (results.some((result) => result.status === "dead")) {
let deadLinks = results.filter((result) => {
return result.status === "dead";
});
if (!opts.quiet) {
console.error(chalk.red("\n ERROR: %s dead links found!"), deadLinks.length);
} else {
console.error(chalk.red("\n ERROR: %s dead links found in %s !"), deadLinks.length, filenameForOutput);
}
deadLinks.forEach(function (result) {
console.log(" [%s] %s → Status: %s", statusLabels[result.status], result.link, result.statusCode);
});
}
};
Loading

0 comments on commit 02c0ddb

Please sign in to comment.