diff --git a/.eslintrc.json b/.eslintrc.json
index 9f5944d..2405491 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -263,7 +263,6 @@
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-namespace": "error",
- "@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-use-before-define": "error",
diff --git a/.gitignore b/.gitignore
index cf78318..f15e82c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,7 +24,7 @@ node_modules/
.vscode
# Compiled files
-dist/
+dist/tests
# Test output
.nyc_output/
diff --git a/README.md b/README.md
index a0d9acd..981f6cb 100644
--- a/README.md
+++ b/README.md
@@ -26,11 +26,17 @@ markdown-link-validator ./path/to/mds [options]
Basic configuration:
-i, --ignorePatterns path::[String] Regex to ignore links - default: []
- -f, --flags path::String Flags applied to the ignore pattern
- -h, --help Show help
+ --ignorePatternsFromFile String File containing regex to ignore links (see --ignorePatterns option), one per line
+ -f, --flags path::String Flags applied to the ignore patterns
+ -c, --ignoreStatusCodes [Number] HTTP status code of valid links - default: [200]
+ -e, --optionalMdExtension Boolean File extension (.md) is optional for relative links, that can be also folders with an index.md file inside#
+ -o, --allowOtherExtensions Boolean Relative links are valid also with extensions other than .md, including images
+ --noEmptyFiles Boolean Links to empty files are invalid (shown as errors instead of warnings in report)
+ -q, --quietMode Boolean Show only errors and warnings in report
+ -h, --help Show help
Miscellaneous:
- --debug Output debugging information
+ --debug Output debugging information
```
The following will analyze all the `.md` files found under `./docs` and
diff --git a/dist/src/bin/markdown-link-validator.d.ts b/dist/src/bin/markdown-link-validator.d.ts
new file mode 100644
index 0000000..66cf6e8
--- /dev/null
+++ b/dist/src/bin/markdown-link-validator.d.ts
@@ -0,0 +1,6 @@
+#!/usr/bin/env node
+/**
+ * @fileoverview Main CLI that is run via the markdown-link-validator command.
+ * Based on ESLint.
+ */
+export {};
diff --git a/dist/src/bin/markdown-link-validator.js b/dist/src/bin/markdown-link-validator.js
new file mode 100644
index 0000000..6f9b74c
--- /dev/null
+++ b/dist/src/bin/markdown-link-validator.js
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+/**
+ * @fileoverview Main CLI that is run via the markdown-link-validator command.
+ * Based on ESLint.
+ */
+/* eslint no-console:off */
+/*
+ * Helpers
+ */
+const debug = (process.argv.includes('--debug'));
+import d from 'debug';
+// This initialization needs to be done *before* other requires in order to work.
+if (debug) {
+ d.enable('markdown-link-validator:*');
+}
+/*
+ * Requirements
+ */
+// Now we can safely include the other modules that use debug.
+import cli from '../lib/cli.js';
+/*
+ * Execution
+ */
+process.once('uncaughtException', (err) => {
+ console.error(err.message);
+ console.error(err.stack);
+ process.exitCode = 1;
+});
+process.once('unhandledRejection', (reason) => {
+ console.error(reason);
+ process.exitCode = 1;
+});
+const run = async () => {
+ process.exitCode = await cli.execute(process.argv);
+};
+run();
+//# sourceMappingURL=markdown-link-validator.js.map
\ No newline at end of file
diff --git a/dist/src/bin/markdown-link-validator.js.map b/dist/src/bin/markdown-link-validator.js.map
new file mode 100644
index 0000000..e13438e
--- /dev/null
+++ b/dist/src/bin/markdown-link-validator.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"markdown-link-validator.js","sourceRoot":"","sources":["../../../src/bin/markdown-link-validator.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,2BAA2B;AAE3B;;GAEG;AAEH,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAEjD,OAAO,CAAC,MAAM,OAAO,CAAC;AAEtB,iFAAiF;AACjF,IAAI,KAAK,EAAE;IACP,CAAC,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;CACzC;AAED;;GAEG;AAEH,8DAA8D;AAC9D,OAAO,GAAG,MAAM,eAAe,CAAC;AAEhC;;GAEG;AAEH,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,KAAK,IAAI,EAAE;IACnB,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,GAAG,EAAE,CAAC"}
\ No newline at end of file
diff --git a/dist/src/lib/cli.d.ts b/dist/src/lib/cli.d.ts
new file mode 100644
index 0000000..2bf83e4
--- /dev/null
+++ b/dist/src/lib/cli.d.ts
@@ -0,0 +1,7 @@
+/**
+ * @fileoverview Main CLI object, it reads the options from cli.
+ */
+declare const _default: {
+ execute: (args: string[]) => Promise<0 | 1>;
+};
+export default _default;
diff --git a/dist/src/lib/cli.js b/dist/src/lib/cli.js
new file mode 100644
index 0000000..3c9f9bf
--- /dev/null
+++ b/dist/src/lib/cli.js
@@ -0,0 +1,199 @@
+/**
+ * @fileoverview Main CLI object, it reads the options from cli.
+ */
+/*
+ * The CLI object should *not* call process.exit() directly. It should only return
+ * exit codes. This allows other programs to use the CLI object and still control
+ * when the program exits.
+ */
+import path from 'path';
+import { fileURLToPath } from 'url';
+import events from 'events';
+import fs from 'fs';
+import readline from 'readline';
+import { debug as d } from './utils/debug.js';
+import { globby } from 'globby';
+import chalk from 'chalk';
+import wrapPromise from './utils/wrappromise.js';
+const __filename = fileURLToPath(import.meta.url);
+const debug = d(__filename);
+import { options } from './cli/options.js';
+import { MDFile } from './mdfile.js';
+const getMDFiles = async (directory, ignorePatterns, ignoreStatusCodes, optionalMdExtension, allowOtherExtensions, noEmptyFiles) => {
+ const filesPath = await globby(['**/*.md', '!node_modules', '!**/node_modules'], { cwd: directory });
+ return filesPath.map((relativePath) => {
+ const file = new MDFile(directory, relativePath, ignorePatterns, ignoreStatusCodes, optionalMdExtension, allowOtherExtensions, noEmptyFiles);
+ return file;
+ });
+};
+const validateLinks = async (mdFiles) => {
+ const limit = 10;
+ const promises = [];
+ for (const mdFile of mdFiles) {
+ promises.push(wrapPromise(mdFile.validateLinks()));
+ if (promises.length >= limit) {
+ // Wait for a file to be validated.
+ await Promise.race(promises);
+ // Remove the resolved/rejected file from the promises array.
+ const index = promises.findIndex((promise) => {
+ return promise.resolved || promise.rejected;
+ });
+ promises.splice(index, 1);
+ }
+ }
+ // Wait for the pending promises to be resolved/rejected.
+ await Promise.all(promises);
+};
+const getInvalidLinks = (mdFiles) => {
+ return mdFiles.reduce((total, mdFile) => {
+ return [...total, ...mdFile.invalidLinks];
+ }, []);
+};
+const getInvalidLinkLabels = (mdFiles) => {
+ return mdFiles.reduce((total, mdFile) => {
+ return [...total, ...mdFile.invalidLinkLabels];
+ }, []);
+};
+const reportLinks = (mdFiles, directory, quietMode, noEmptyFiles) => {
+ const totalLinksByFile = {};
+ const totalLinks = {
+ error: 0,
+ success: 0,
+ warning: 0
+ };
+ mdFiles.forEach((mdFile) => {
+ const messages = [];
+ totalLinksByFile[mdFile.path] = {
+ error: 0,
+ success: 0,
+ warning: 0
+ };
+ mdFile.links.forEach((link) => {
+ if (link.isValid && link.statusCode !== 204) {
+ totalLinksByFile[mdFile.path].success++;
+ messages.push({
+ level: 'info',
+ message: chalk.green(`✔ [${link.statusCode}] ${link.link}`)
+ });
+ }
+ else {
+ const level = !noEmptyFiles && link.statusCode === 204 ? 'warning' : 'error';
+ const errorMessage = chalk.red(`✖ [${link.statusCode}] ${link.link}:${link.position.line}:${link.position.column}`);
+ const warningMessage = chalk.yellow(`○ [${link.statusCode}] ${link.link}:${link.position.line}:${link.position.column}`);
+ totalLinksByFile[mdFile.path][level]++;
+ messages.push({
+ level,
+ message: level === 'warning' ? warningMessage : errorMessage
+ });
+ }
+ });
+ mdFile.invalidLinkLabels.forEach((linkLabel) => {
+ totalLinksByFile[mdFile.path].error++;
+ messages.push({
+ level: 'error',
+ message: chalk.red(`✖ [${linkLabel.statusCode}] ${linkLabel.label}:${linkLabel.position.line}:${linkLabel.position.column}`)
+ });
+ });
+ if (!quietMode || totalLinksByFile[mdFile.path].warning > 0 || totalLinksByFile[mdFile.path].error > 0) {
+ console.log('');
+ console.log(chalk.cyan(mdFile.path));
+ messages
+ .filter((message) => {
+ return quietMode ? ['error', 'warning', undefined].includes(message.level) : true;
+ })
+ .forEach((message) => {
+ console.log(message.message);
+ });
+ }
+ totalLinks.success += totalLinksByFile[mdFile.path].success;
+ totalLinks.error += totalLinksByFile[mdFile.path].error;
+ let chalkColor = chalk.green;
+ if (totalLinksByFile[mdFile.path].error > 0) {
+ chalkColor = chalk.red;
+ }
+ if (!quietMode || totalLinksByFile[mdFile.path].error > 0) {
+ console.log(chalkColor(`Found ${totalLinksByFile[mdFile.path].error + totalLinksByFile[mdFile.path].success} links and labels:
+ ${totalLinksByFile[mdFile.path].success} valid
+ ${totalLinksByFile[mdFile.path].error} invalid`));
+ }
+ });
+ let chalkColor = chalk.green;
+ if (totalLinks.error > 0) {
+ chalkColor = chalk.red;
+ }
+ if (!quietMode || totalLinks.error > 0) {
+ console.log('');
+ console.log(chalkColor(`Found a total of ${totalLinks.error + totalLinks.success} links and labels in directory "${directory}":
+ ${totalLinks.success} valid
+ ${totalLinks.error} invalid`));
+ }
+};
+/**
+ * Execute the analysis for the directories passed as parameter.
+ * * e.g. markdown-link-validator ./documentation
+ * * e.g. markdown-link-validator ./docs --debug
+ * * e.g. markdown-link-validator ./docs -i https?:\/\/test\.com\/.* -f gi
+ */
+const execute = async (args) => {
+ let currentOptions;
+ try {
+ currentOptions = options.parse(args);
+ }
+ catch (err) {
+ console.error(err);
+ return 1;
+ }
+ if (currentOptions.help) {
+ console.log(options.generateHelp());
+ return 0;
+ }
+ console.log('Analyzing...');
+ const ignorePatterns = currentOptions.ignorePatterns.map((pattern) => {
+ return new RegExp(pattern, currentOptions.flags);
+ });
+ if (currentOptions.ignorePatternsFrom) {
+ try {
+ const rl = readline.createInterface({
+ crlfDelay: Infinity,
+ input: fs.createReadStream(currentOptions.ignorePatternsFrom)
+ });
+ rl.on('line', (pattern) => {
+ if (pattern) {
+ ignorePatterns.push(new RegExp(pattern, currentOptions.flags));
+ }
+ });
+ await events.once(rl, 'close');
+ }
+ catch (err) {
+ console.error(err);
+ return 1;
+ }
+ }
+ const ignoreStatusCodes = [...(!currentOptions.noEmptyFiles ? [200, 204] : [200]), ...currentOptions.ignoreStatusCodes];
+ /* Get the directories full path */
+ const directories = currentOptions._.map((dir) => {
+ return path.resolve(process.cwd(), dir);
+ });
+ debug(`Directories to analyze: ${directories.toString()}`);
+ let invalidLinks = [];
+ let invalidLinkLabels = [];
+ const start = Date.now();
+ for (const directory of directories) {
+ /* Get all md files */
+ const mdFiles = await getMDFiles(directory, ignorePatterns, ignoreStatusCodes, currentOptions.optionalMdExtension, currentOptions.allowOtherExtensions, currentOptions.noEmptyFiles);
+ await validateLinks(mdFiles);
+ reportLinks(mdFiles, directory, currentOptions.quietMode, currentOptions.noEmptyFiles);
+ invalidLinks = invalidLinks.concat(getInvalidLinks(mdFiles));
+ invalidLinkLabels = invalidLinkLabels.concat(getInvalidLinkLabels(mdFiles));
+ }
+ if (!currentOptions.quietMode) {
+ console.log('');
+ console.log(`Time to validate: ${(Date.now() - start) / 1000}s`);
+ }
+ if (invalidLinks.length > 0 || invalidLinkLabels.length > 0) {
+ return 1;
+ }
+ return 0;
+};
+export default { execute };
+//# sourceMappingURL=cli.js.map
\ No newline at end of file
diff --git a/dist/src/lib/cli.js.map b/dist/src/lib/cli.js.map
new file mode 100644
index 0000000..214975c
--- /dev/null
+++ b/dist/src/lib/cli.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/lib/cli.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/src/lib/cli/options.d.ts b/dist/src/lib/cli/options.d.ts
new file mode 100644
index 0000000..1e16d39
--- /dev/null
+++ b/dist/src/lib/cli/options.d.ts
@@ -0,0 +1,4 @@
+/**
+ * @fileoverview Options configuration for optionator.
+ */
+export declare const options: any;
diff --git a/dist/src/lib/cli/options.js b/dist/src/lib/cli/options.js
new file mode 100644
index 0000000..81fa235
--- /dev/null
+++ b/dist/src/lib/cli/options.js
@@ -0,0 +1,92 @@
+/**
+ * @fileoverview Options configuration for optionator.
+ */
+import { createRequire as _createRequire } from "module";
+const __require = _createRequire(import.meta.url);
+/*
+ * ------------------------------------------------------------------------------
+ * Requirements
+ * ------------------------------------------------------------------------------
+ */
+const optionator = __require("optionator"); // `require` used because `optionator` exports a function
+/*
+ * ------------------------------------------------------------------------------
+ * Initialization and Public Interface
+ * ------------------------------------------------------------------------------
+ */
+export const options = optionator({
+ defaults: {
+ concatRepeatedArrays: true,
+ mergeRepeatedObjects: true
+ },
+ options: [
+ { heading: 'Basic configuration' },
+ {
+ alias: 'i',
+ concatRepeatedArrays: [true, { oneValuePerFlag: true }],
+ default: '[]',
+ description: 'Regex to ignore links',
+ option: 'ignorePatterns',
+ type: 'path::[String]'
+ },
+ {
+ default: '',
+ description: 'File containing regex to ignore links (see --ignorePatterns option), one per line',
+ option: 'ignorePatternsFrom',
+ type: 'String'
+ },
+ {
+ alias: 'f',
+ dependsOn: ['or', 'ignorePatterns', 'ignorePatternsFrom'],
+ description: 'Flags applied to the ignore patterns',
+ option: 'flags',
+ type: 'path::String'
+ },
+ {
+ alias: 'c',
+ concatRepeatedArrays: [true, { oneValuePerFlag: true }],
+ default: '[200]',
+ description: 'HTTP status code to ignore links',
+ option: 'ignoreStatusCodes',
+ type: '[Number]'
+ },
+ {
+ alias: 'e',
+ description: 'File extension (.md) is optional for relative links, that can be also folders with an index.md file inside',
+ option: 'optionalMdExtension',
+ type: 'Boolean'
+ },
+ {
+ alias: 'o',
+ description: 'Relative links are valid also with extensions other than .md, including images',
+ option: 'allowOtherExtensions',
+ type: 'Boolean'
+ },
+ {
+ description: 'Links to empty files raise errors',
+ option: 'noEmptyFiles',
+ type: 'Boolean'
+ },
+ {
+ alias: 'q',
+ description: 'Show only errors in report',
+ option: 'quietMode',
+ type: 'Boolean'
+ },
+ {
+ alias: 'h',
+ description: 'Show help',
+ option: 'help',
+ type: 'Boolean'
+ },
+ { heading: 'Miscellaneous' },
+ {
+ default: false,
+ description: 'Output debugging information',
+ option: 'debug',
+ type: 'Boolean'
+ }
+ ],
+ prepend: 'markdown-link-validator ./path/to/mds [options]'
+});
+//# sourceMappingURL=options.js.map
\ No newline at end of file
diff --git a/dist/src/lib/cli/options.js.map b/dist/src/lib/cli/options.js.map
new file mode 100644
index 0000000..0cc5d93
--- /dev/null
+++ b/dist/src/lib/cli/options.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/lib/cli/options.ts"],"names":[],"mappings":"AAAA;;GAEG;;;AAEH;;;;GAIG;AAEH,2CAA0C,CAAC,yDAAyD;AAEpG;;;;GAIG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAC;IAC9B,QAAQ,EAAE;QACN,oBAAoB,EAAE,IAAI;QAC1B,oBAAoB,EAAE,IAAI;KAC7B;IACD,OAAO,EAAE;QACL,EAAE,OAAO,EAAE,qBAAqB,EAAE;QAClC;YACI,KAAK,EAAE,GAAG;YACV,oBAAoB,EAAE,CAAC,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;YACvD,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,uBAAuB;YACpC,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB;SACzB;QACD;YACI,OAAO,EAAE,EAAE;YACX,WAAW,EAAE,mFAAmF;YAChG,MAAM,EAAE,oBAAoB;YAC5B,IAAI,EAAE,QAAQ;SACjB;QACD;YACI,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,CAAC;YACzD,WAAW,EAAE,sCAAsC;YACnD,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,cAAc;SACvB;QACD;YACI,KAAK,EAAE,GAAG;YACV,oBAAoB,EAAE,CAAC,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;YACvD,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,kCAAkC;YAC/C,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,UAAU;SACnB;QACD;YACI,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,4GAA4G;YACzH,MAAM,EAAE,qBAAqB;YAC7B,IAAI,EAAE,SAAS;SAClB;QACD;YACI,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,gFAAgF;YAC7F,MAAM,EAAE,sBAAsB;YAC9B,IAAI,EAAE,SAAS;SAClB;QACD;YACI,WAAW,EAAE,mCAAmC;YAChD,MAAM,EAAE,cAAc;YACtB,IAAI,EAAE,SAAS;SAClB;QACD;YACI,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,4BAA4B;YACzC,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,SAAS;SAClB;QACD;YACI,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,WAAW;YACxB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS;SAClB;QACD,EAAE,OAAO,EAAE,eAAe,EAAE;QAC5B;YACI,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,8BAA8B;YAC3C,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,SAAS;SAClB;KACJ;IACD,OAAO,EAAE,iDAAiD;CAC7D,CAAC,CAAC"}
\ No newline at end of file
diff --git a/dist/src/lib/label.d.ts b/dist/src/lib/label.d.ts
new file mode 100644
index 0000000..bd3683c
--- /dev/null
+++ b/dist/src/lib/label.d.ts
@@ -0,0 +1,15 @@
+import { ILabel, Position } from './types.js';
+export declare class Label implements ILabel {
+ private _isValid;
+ private _statusCode;
+ private _label;
+ private _position;
+ constructor(label: string, index: number, content: string);
+ private getPosition;
+ get label(): string;
+ get position(): Position;
+ get isValid(): boolean;
+ get statusCode(): number;
+ set isValid(value: boolean);
+ set statusCode(value: number);
+}
diff --git a/dist/src/lib/label.js b/dist/src/lib/label.js
new file mode 100644
index 0000000..74bad8d
--- /dev/null
+++ b/dist/src/lib/label.js
@@ -0,0 +1,46 @@
+export class Label {
+ _isValid;
+ _statusCode;
+ _label;
+ _position;
+ constructor(label, index, content) {
+ if (!label) {
+ throw new Error(`"label" can't be empty or null`);
+ }
+ if (typeof index !== 'number') {
+ throw new Error(`"index" has to be a number`);
+ }
+ if (!content) {
+ throw new Error(`"content" can't be empty or null`);
+ }
+ this._label = label;
+ this.getPosition(index, content);
+ }
+ getPosition(index, content) {
+ const partialContent = content.substring(0, index);
+ const lines = partialContent.split('\n');
+ this._position = {
+ column: lines[lines.length - 1].length + 1,
+ line: lines.length
+ };
+ }
+ get label() {
+ return this._label;
+ }
+ get position() {
+ return this._position;
+ }
+ get isValid() {
+ return this._isValid;
+ }
+ get statusCode() {
+ return this._statusCode;
+ }
+ set isValid(value) {
+ this._isValid = value;
+ }
+ set statusCode(value) {
+ this._statusCode = value;
+ }
+}
+//# sourceMappingURL=label.js.map
\ No newline at end of file
diff --git a/dist/src/lib/label.js.map b/dist/src/lib/label.js.map
new file mode 100644
index 0000000..18c0302
--- /dev/null
+++ b/dist/src/lib/label.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"label.js","sourceRoot":"","sources":["../../../src/lib/label.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,KAAK;IACN,QAAQ,CAAU;IAClB,WAAW,CAAS;IACpB,MAAM,CAAS;IACf,SAAS,CAAW;IAE5B,YAAmB,KAAa,EAAE,KAAa,EAAE,OAAe;QAC5D,IAAI,CAAC,KAAK,EAAE;YACR,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;SACrD;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;SACjD;QAED,IAAI,CAAC,OAAO,EAAE;YACV,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAEpB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAEO,WAAW,CAAC,KAAa,EAAE,OAAe;QAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,IAAI,CAAC,SAAS,GAAG;YACb,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;YAC1C,IAAI,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC;IACN,CAAC;IAED,IAAW,KAAK;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,IAAW,UAAU;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,IAAW,OAAO,CAAC,KAAc;QAC7B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,IAAW,UAAU,CAAC,KAAa;QAC/B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC7B,CAAC;CACJ"}
\ No newline at end of file
diff --git a/dist/src/lib/link.d.ts b/dist/src/lib/link.d.ts
new file mode 100644
index 0000000..4db9fee
--- /dev/null
+++ b/dist/src/lib/link.d.ts
@@ -0,0 +1,15 @@
+import { ILink, Position } from './types.js';
+export declare class Link implements ILink {
+ private _isValid;
+ private _statusCode;
+ private _link;
+ private _position;
+ constructor(link: string, index: number, content: string);
+ private getPosition;
+ get link(): string;
+ get position(): Position;
+ get isValid(): boolean;
+ get statusCode(): number;
+ set isValid(value: boolean);
+ set statusCode(value: number);
+}
diff --git a/dist/src/lib/link.js b/dist/src/lib/link.js
new file mode 100644
index 0000000..256133a
--- /dev/null
+++ b/dist/src/lib/link.js
@@ -0,0 +1,46 @@
+export class Link {
+ _isValid;
+ _statusCode;
+ _link;
+ _position;
+ constructor(link, index, content) {
+ if (!link) {
+ throw new Error(`"link" can't be empty or null`);
+ }
+ if (typeof index !== 'number') {
+ throw new Error(`"index" has to be a number`);
+ }
+ if (!content) {
+ throw new Error(`"content" can't be empty or null`);
+ }
+ this._link = link;
+ this.getPosition(index, content);
+ }
+ getPosition(index, content) {
+ const partialContent = content.substring(0, index);
+ const lines = partialContent.split('\n');
+ this._position = {
+ column: lines[lines.length - 1].length + 1,
+ line: lines.length
+ };
+ }
+ get link() {
+ return this._link;
+ }
+ get position() {
+ return this._position;
+ }
+ get isValid() {
+ return this._isValid;
+ }
+ get statusCode() {
+ return this._statusCode;
+ }
+ set isValid(value) {
+ this._isValid = value;
+ }
+ set statusCode(value) {
+ this._statusCode = value;
+ }
+}
+//# sourceMappingURL=link.js.map
\ No newline at end of file
diff --git a/dist/src/lib/link.js.map b/dist/src/lib/link.js.map
new file mode 100644
index 0000000..0457b92
--- /dev/null
+++ b/dist/src/lib/link.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"link.js","sourceRoot":"","sources":["../../../src/lib/link.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,IAAI;IACL,QAAQ,CAAU;IAClB,WAAW,CAAS;IACpB,KAAK,CAAS;IACd,SAAS,CAAW;IAE5B,YAAmB,IAAY,EAAE,KAAa,EAAE,OAAe;QAC3D,IAAI,CAAC,IAAI,EAAE;YACP,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;SACpD;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;SACjD;QAED,IAAI,CAAC,OAAO,EAAE;YACV,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;SACvD;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAEO,WAAW,CAAC,KAAa,EAAE,OAAe;QAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,IAAI,CAAC,SAAS,GAAG;YACb,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;YAC1C,IAAI,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC;IACN,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,IAAW,UAAU;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,IAAW,OAAO,CAAC,KAAc;QAC7B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,IAAW,UAAU,CAAC,KAAa;QAC/B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC7B,CAAC;CACJ"}
\ No newline at end of file
diff --git a/dist/src/lib/mdfile.d.ts b/dist/src/lib/mdfile.d.ts
new file mode 100644
index 0000000..bcd2b86
--- /dev/null
+++ b/dist/src/lib/mdfile.d.ts
@@ -0,0 +1,110 @@
+import { IMDFile, ILink, ILabel } from './types.js';
+export declare class MDFile implements IMDFile {
+ private _absoluteLinks;
+ /**
+ * This regex should match the following example:
+ * * ```markdown
+ * * [link label]: https://exxample.com
+ * * ```
+ */
+ private _codeBlockRegex;
+ private _urlRegex;
+ /**
+ * This regex should match the following example:
+ * * [link](https://example.com)
+ * * [link label]: https://exxample.com
+ * *
+ */
+ private _absoluteRegex;
+ /**
+ * This regex should match the following example:
+ * * http://example.com/avatar.jpg
+ */
+ private _standaloneRegex;
+ private _cache;
+ private _originalContent;
+ private _content;
+ private _ignorePatterns;
+ private _ignoreStatusCodes;
+ private _optionalMdExtension;
+ private _allowOtherExtensions;
+ private _noEmptyFiles;
+ private _internalLinks;
+ private _invalidLinks;
+ private _invalidLabels;
+ /**
+ * This regex should match the following examples:
+ * * [link](#somewhere)
+ * * [link] (#somewhere) → invalid link.
+ * * [link]( #somewhere)
+ */
+ private _internalRegex;
+ private _links;
+ private _path;
+ private _relativeLinks;
+ private _linkLabels;
+ private _linkAnchors;
+ private _directory;
+ private _relativePath;
+ /**
+ * This regex should match the following examples:
+ * * [link label]: /somewhere.md
+ * * [link label]: ./somewhere.md
+ * * [link label]: ../somewhere.md
+ * * [link label]: /somewhere
+ * * [link label]: ./somewhere
+ * * [link label]: ../somewhere
+ * * [link label]:/somewhere.md
+ * * [link label]:./somewhere.md
+ * * [link label]:../somewhere.md
+ * * [link label]:/somewhere
+ * * [link label]:./somewhere
+ * * [link label]:../somewhere
+ * * [link](/somewhere.md)
+ * * [link](./somewhere.md)
+ * * [link](../somewhere.md)
+ * * [link](/somewhere/)
+ * * [link](./somewhere/)
+ * * [link](../somewhere/)
+ */
+ private _relativeRegex;
+ private _relativeRegexWithImages;
+ /**
+ * This regex should match the link labels and anchors:
+ * * Text with a [link][anchor].
+ * * [anchor]: http://example.com
+ */
+ private _labelRegex;
+ private _anchorRegex;
+ private _titles;
+ private _titleRegex;
+ private _normalizedTitles;
+ constructor(directory: string, relativePath: string, ignorePatterns: RegExp[], ignoreStatusCodes: number[], optionalMdExtension?: boolean, allowOtherExtensions?: boolean, noEmptyFiles?: boolean);
+ private stripCodeBlocks;
+ private getRelativeLinks;
+ private getAbsoluteLinks;
+ private getInternalLinks;
+ private getLinkLabels;
+ private getLinkAnchors;
+ private getTitles;
+ private ignoreLink;
+ private validateAbsoluteLinks;
+ private validateRelativeLink;
+ private validateRelativeLinks;
+ private validateInternalLink;
+ private validateInternalLinks;
+ private validateLabel;
+ validateLabels(): void;
+ validateLinks(): Promise;
+ get absoluteLinks(): Set;
+ get internalLinks(): Set;
+ get linkLabels(): Set;
+ get linkAnchors(): Set;
+ get path(): string;
+ get relativeLinks(): Set;
+ get relativePath(): string;
+ get titles(): Set;
+ get invalidLinkLabels(): Set;
+ get invalidLinks(): Set;
+ get links(): Set;
+}
diff --git a/dist/src/lib/mdfile.js b/dist/src/lib/mdfile.js
new file mode 100644
index 0000000..3af80d1
--- /dev/null
+++ b/dist/src/lib/mdfile.js
@@ -0,0 +1,379 @@
+import fs from 'fs';
+import path from 'path';
+import uslug from 'uslug';
+import request from './utils/request.js';
+import { Link } from './link.js';
+import { Label } from './label.js';
+export class MDFile {
+ _absoluteLinks;
+ /**
+ * This regex should match the following example:
+ * * ```markdown
+ * * [link label]: https://exxample.com
+ * * ```
+ */
+ _codeBlockRegex = /`{3}.*?`{3}/gs;
+ _urlRegex = /https?:\/\/[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%,*_+.~#?&//=]*)/;
+ /**
+ * This regex should match the following example:
+ * * [link](https://example.com)
+ * * [link label]: https://exxample.com
+ * *
+ */
+ _absoluteRegex = new RegExp(`(]\\(|]:\\s*)(${this._urlRegex.source})`, 'g');
+ /**
+ * This regex should match the following example:
+ * * http://example.com/avatar.jpg
+ */
+ _standaloneRegex = new RegExp(`(? {
+ return '\n'.repeat(match.split('\n').length - 1);
+ });
+ }
+ getRelativeLinks() {
+ let val;
+ while ((val = this._allowOtherExtensions ? this._relativeRegexWithImages.exec(this._content) : this._relativeRegex.exec(this._content)) !== null) {
+ const url = val[3] || val[1];
+ if (this._cache.has(url)) {
+ continue;
+ }
+ // [link](./somewhere.md) → shift will be 1 because of "]("
+ let shift = 2;
+ if (!val[1]) {
+ /**
+ * [link label]: ./somewhere.md → val[2] will be ": "
+ * [link label]:./somewhere.md → val[2] will be ":"
+ */
+ shift = val[2].length;
+ }
+ this._cache.add(url);
+ this._relativeLinks.add(new Link(url, val.index + shift, this._content));
+ }
+ }
+ getAbsoluteLinks() {
+ let val;
+ while ((val = this._absoluteRegex.exec(this._content)) !== null) {
+ const url = val[2];
+ if (this._cache.has(url)) {
+ continue;
+ }
+ /**
+ * [link](https://example.com) → val[1] will be "]("
+ * [link label]: https://exxample.com → val[1] will be "]: "
+ * → val[1] will be 'src="'
+ */
+ const shift = val[1].length;
+ this._cache.add(url);
+ this._absoluteLinks.add(new Link(url, val.index + shift, this._content));
+ }
+ while ((val = this._standaloneRegex.exec(this._content)) !== null) {
+ const url = val[0].replace(/\.$/, '');
+ if (this._cache.has(url)) {
+ continue;
+ }
+ this._cache.add(url);
+ this._absoluteLinks.add(new Link(url, val.index, this._content));
+ }
+ }
+ getInternalLinks() {
+ let val;
+ while ((val = this._internalRegex.exec(this._content)) !== null) {
+ const url = val[1];
+ if (this._cache.has(url)) {
+ continue;
+ }
+ this._cache.add(url);
+ this._internalLinks.add(new Link(url, val.index + 2, this._content));
+ }
+ }
+ getLinkLabels() {
+ let val;
+ while ((val = this._labelRegex.exec(this._content)) !== null) {
+ const label = val[1];
+ this._linkLabels.add(new Label(label, val.index, this._content));
+ }
+ }
+ getLinkAnchors() {
+ let val;
+ while ((val = this._anchorRegex.exec(this._content)) !== null) {
+ const anchor = val[1];
+ this._linkAnchors.add(val[1]);
+ }
+ }
+ getTitles() {
+ let val;
+ while ((val = this._titleRegex.exec(this._content)) !== null) {
+ this._titles.add(val[1]);
+ this._normalizedTitles.add(uslug(val[1]));
+ }
+ }
+ ignoreLink(url) {
+ return this._ignorePatterns.some((pattern) => {
+ return pattern.test(url);
+ });
+ }
+ async validateAbsoluteLinks() {
+ const promises = [];
+ for (const link of this._absoluteLinks) {
+ if (this.ignoreLink(link.link)) {
+ link.isValid = true;
+ link.statusCode = 200;
+ continue;
+ }
+ const promise = request.get(link.link, this._ignoreStatusCodes)
+ .then((linkStatus) => {
+ link.isValid = linkStatus.isOk;
+ link.statusCode = linkStatus.statusCode;
+ });
+ promises.push(promise);
+ }
+ await Promise.all(promises);
+ }
+ validateRelativeLink(link) {
+ if (this.ignoreLink(link.link)) {
+ link.isValid = true;
+ link.statusCode = 200;
+ return;
+ }
+ const fullPath = link.link.startsWith('/') ? path.join(this._directory, link.link) : path.join(path.dirname(this._path), link.link);
+ const [originalFilePath, hash] = fullPath.split('#');
+ const originalFilePathIsDirectory = fs.existsSync(originalFilePath) && fs.statSync(originalFilePath).isDirectory(); // eslint-disable-line no-sync
+ // Relative links should point to a md file, but extension is optional
+ let filePath = originalFilePath;
+ if (originalFilePathIsDirectory) {
+ // If relative link points to a folder, search for a `index.md` file inside that folder.
+ filePath = this._optionalMdExtension ? path.join(originalFilePath, 'index.md') : originalFilePath;
+ }
+ else {
+ // Else append a `.md` extensions if missing
+ filePath = this._optionalMdExtension && !path.extname(originalFilePath) ? `${originalFilePath}.md` : originalFilePath;
+ }
+ // Relative links should point to a md file.
+ if (!this._allowOtherExtensions && path.extname(filePath) !== '.md') {
+ link.isValid = false;
+ link.statusCode = 404;
+ return;
+ }
+ const exists = fs.existsSync(filePath); // eslint-disable-line no-sync
+ if (!exists) {
+ link.isValid = false;
+ link.statusCode = 404;
+ return;
+ }
+ if (exists && this._allowOtherExtensions && path.extname(filePath) !== '.md') {
+ link.isValid = true;
+ link.statusCode = 200;
+ return;
+ }
+ /**
+ * 1. Read file content
+ * 2. Check if file is not empty
+ * 3. Get titles
+ * 4. Check if has exists.
+ */
+ const fileContent = fs.readFileSync(filePath, { encoding: 'utf-8' }); // eslint-disable-line no-sync
+ const normalizedTitles = new Set();
+ let val;
+ if (!hash) {
+ link.isValid = !(this._noEmptyFiles && !fileContent);
+ link.statusCode = !fileContent ? 204 : 200;
+ return;
+ }
+ while ((val = this._titleRegex.exec(fileContent)) !== null) {
+ normalizedTitles.add(uslug(val[1]));
+ }
+ link.isValid = normalizedTitles.has(hash);
+ link.statusCode = link.isValid ? 200 : 404;
+ }
+ validateRelativeLinks() {
+ this._relativeLinks.forEach((link) => {
+ this.validateRelativeLink(link);
+ });
+ }
+ validateInternalLink(link) {
+ if (this.ignoreLink(link.link)) {
+ link.isValid = true;
+ link.statusCode = 200;
+ return;
+ }
+ if (this._normalizedTitles.has(link.link.substring(1))) {
+ link.isValid = true;
+ link.statusCode = 200;
+ return;
+ }
+ link.isValid = false;
+ link.statusCode = 404;
+ }
+ validateInternalLinks() {
+ this._internalLinks.forEach((link) => {
+ this.validateInternalLink(link);
+ });
+ }
+ validateLabel(label) {
+ if (this._linkAnchors.has(label.label)) {
+ label.isValid = true;
+ label.statusCode = 200;
+ return;
+ }
+ label.isValid = false;
+ label.statusCode = 404;
+ }
+ validateLabels() {
+ this._linkLabels.forEach((label) => {
+ this.validateLabel(label);
+ });
+ }
+ async validateLinks() {
+ await this.validateAbsoluteLinks();
+ this.validateRelativeLinks();
+ this.validateInternalLinks();
+ this.validateLabels();
+ }
+ get absoluteLinks() {
+ return this._absoluteLinks;
+ }
+ get internalLinks() {
+ return this._internalLinks;
+ }
+ get linkLabels() {
+ return this._linkLabels;
+ }
+ get linkAnchors() {
+ return this._linkAnchors;
+ }
+ get path() {
+ return this._path;
+ }
+ get relativeLinks() {
+ return this._relativeLinks;
+ }
+ get relativePath() {
+ return this._relativePath;
+ }
+ get titles() {
+ return this._titles;
+ }
+ get invalidLinkLabels() {
+ if (this._invalidLabels) {
+ return this._invalidLabels;
+ }
+ const invalidLabels = [...this._linkLabels]
+ .filter((label) => {
+ return !label.isValid;
+ });
+ this._invalidLabels = new Set(invalidLabels);
+ return this._invalidLabels;
+ }
+ get invalidLinks() {
+ if (this._invalidLinks) {
+ return this._invalidLinks;
+ }
+ const invalidAbsoluteLinks = [...this._absoluteLinks]
+ .filter((link) => {
+ return !link.isValid;
+ });
+ const invalidRelativeLinks = [...this._relativeLinks]
+ .filter((link) => {
+ return !link.isValid;
+ });
+ const invalidInternalLinks = [...this._internalLinks]
+ .filter((link) => {
+ return !link.isValid;
+ });
+ this._invalidLinks = new Set(invalidAbsoluteLinks.concat(invalidRelativeLinks).concat(invalidInternalLinks));
+ return this._invalidLinks;
+ }
+ get links() {
+ if (this._links) {
+ return this._links;
+ }
+ this._links = new Set([...this._absoluteLinks, ...this._relativeLinks, ...this._internalLinks]);
+ return this._links;
+ }
+}
+//# sourceMappingURL=mdfile.js.map
\ No newline at end of file
diff --git a/dist/src/lib/mdfile.js.map b/dist/src/lib/mdfile.js.map
new file mode 100644
index 0000000..1f698af
--- /dev/null
+++ b/dist/src/lib/mdfile.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mdfile.js","sourceRoot":"","sources":["../../../src/lib/mdfile.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/src/lib/types.d.ts b/dist/src/lib/types.d.ts
new file mode 100644
index 0000000..97aa820
--- /dev/null
+++ b/dist/src/lib/types.d.ts
@@ -0,0 +1,45 @@
+export type CLIOptions = {
+ _: string[];
+ debug: boolean;
+ flags: string;
+ optionalMdExtension: boolean;
+ allowOtherExtensions: boolean;
+ noEmptyFiles: boolean;
+ quietMode: boolean;
+ help: boolean;
+ ignorePatterns: string[];
+ ignorePatternsFrom: string;
+ ignoreStatusCodes: number[];
+};
+export type Position = {
+ line: number;
+ column: number;
+};
+interface IFragment {
+ isValid: boolean;
+ position: Position;
+ statusCode?: number;
+}
+export interface ILink extends IFragment {
+ link: string;
+}
+export interface ILabel extends IFragment {
+ label: string;
+}
+export interface IMDFile {
+ absoluteLinks: Set;
+ internalLinks: Set;
+ invalidLinks: Set;
+ invalidLinkLabels: Set;
+ links: Set;
+ path: string;
+ relativeLinks: Set;
+ relativePath: string;
+ titles: Set;
+ validateLinks: () => Promise;
+}
+export type Message = {
+ message: string;
+ level?: 'info' | 'warning' | 'error';
+};
+export {};
diff --git a/dist/src/lib/types.js b/dist/src/lib/types.js
new file mode 100644
index 0000000..718fd38
--- /dev/null
+++ b/dist/src/lib/types.js
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=types.js.map
\ No newline at end of file
diff --git a/dist/src/lib/types.js.map b/dist/src/lib/types.js.map
new file mode 100644
index 0000000..5bb5e4d
--- /dev/null
+++ b/dist/src/lib/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/dist/src/lib/utils/debug.d.ts b/dist/src/lib/utils/debug.d.ts
new file mode 100644
index 0000000..63e6223
--- /dev/null
+++ b/dist/src/lib/utils/debug.d.ts
@@ -0,0 +1,2 @@
+import d from 'debug';
+export declare const debug: (filePath: string) => d.IDebugger;
diff --git a/dist/src/lib/utils/debug.js b/dist/src/lib/utils/debug.js
new file mode 100644
index 0000000..e2eb78c
--- /dev/null
+++ b/dist/src/lib/utils/debug.js
@@ -0,0 +1,24 @@
+import path from 'path';
+import d from 'debug';
+const debugEnabled = (process.argv.includes('--debug'));
+// must do this initialization *before* other requires in order to work
+if (debugEnabled) {
+ d.enable('markdown-link-validator:*');
+}
+export const debug = (filePath) => {
+ let output = path.basename(filePath, path.extname(filePath));
+ let dirPath = path.dirname(filePath);
+ let currentDir = path.basename(dirPath);
+ /*
+ * The debug message is generated from the file path, e.g.:
+ *
+ * * src/lib/cli.ts => markdown-link-validator:cli
+ */
+ while (currentDir && currentDir !== 'lib') {
+ output = `${currentDir}:${output}`;
+ dirPath = path.join(dirPath, '..');
+ currentDir = path.basename(dirPath);
+ }
+ return d(`markdown-link-validator:${output}`);
+};
+//# sourceMappingURL=debug.js.map
\ No newline at end of file
diff --git a/dist/src/lib/utils/debug.js.map b/dist/src/lib/utils/debug.js.map
new file mode 100644
index 0000000..97d95a1
--- /dev/null
+++ b/dist/src/lib/utils/debug.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../../src/lib/utils/debug.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,CAAC,MAAM,OAAO,CAAC;AAEtB,MAAM,YAAY,GAAY,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAEjE,uEAAuE;AACvE,IAAI,YAAY,EAAE;IACd,CAAC,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;CACzC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAe,EAAE;IAEnD,IAAI,MAAM,GAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrE,IAAI,OAAO,GAAW,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,UAAU,GAAW,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEhD;;;;OAIG;IAEH,OAAO,UAAU,IAAI,UAAU,KAAK,KAAK,EAAE;QACvC,MAAM,GAAG,GAAG,UAAU,IAAI,MAAM,EAAE,CAAC;QAEnC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACnC,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;KACvC;IAED,OAAO,CAAC,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;AAClD,CAAC,CAAC"}
\ No newline at end of file
diff --git a/dist/src/lib/utils/delay.d.ts b/dist/src/lib/utils/delay.d.ts
new file mode 100644
index 0000000..e43ddb9
--- /dev/null
+++ b/dist/src/lib/utils/delay.d.ts
@@ -0,0 +1,3 @@
+/** Convenience wrapper to add a delay using promises. */
+declare const _default: (millisecs: number) => Promise