diff --git a/README.md b/README.md index 7205c01..d9aced5 100644 --- a/README.md +++ b/README.md @@ -45,17 +45,24 @@ To check hyperlinks in your markup language files, follow these steps: linkspector check ``` - To specify a custom configuration file path: + * To specify a custom configuration file path: - ```bash - linkspector check -c /path/to/custom-config.yml - ``` + ```bash + linkspector check -c /path/to/custom-config.yml + ``` - To get the output in JSON format: + * To output the results in JSON format: - ```bash - linkspector check --json - ``` + ```bash + linkspector check -j + ``` + The JSON output follows [rdjson](https://github.com/reviewdog/reviewdog/tree/master/proto/rdf#rdjson) format. + +1. Linkspector starts checking the hyperlinks in your files based on the configuration provided in the configuration file or using the default configuration. It then displays the results in your terminal. + +1. After the check is complete, Linkspector provides a summary of the results. If any dead links are found, they are listed in the terminal, along with their status codes and error messages. + +1. If no dead links are found, Linkspector displays a success message, indicating that all links are working. ## Configuration @@ -249,24 +256,18 @@ To use Linkspector with Docker, follow these steps: bash -c 'linkspector check -c /path/to/custom-config.yml' ``` -1. Linkspector starts checking the hyperlinks in your files based on the configuration provided in the configuration file or using the default configuration. It then displays the results in your terminal. - -1. After the check is complete, Linkspector provides a summary of the results. If any dead links are found, they are listed in the terminal, along with their status codes and error messages. - -1. If no dead links are found, Linkspector displays a success message, indicating that all links are working. - ## What's planned - [x] Spinner for local runs. - [ ] Create a GitHub action. - [x] Modified files only check. -- [x] Asciidoc support. +- [!] Asciidoc support. (Limited to hyperlinks only) - [ ] ReStructured Text support. - [ ] Disable binary files downlaod. -- [ ] JSON output for `failed-only` or `all` links. -- [ ] CSV output for `all` links. -- [ ] Experimaental mode to gather all links and check them in batches to study performance gains. -- [ ] Proxy support to connect puppeteer to a remote service. -- [ ] Puppeteer config support. +- [x] JSON output for `failed-only` ~~or `all`~~ links. +- ~~[ ] CSV output for `all` links.~~ (dropped for now) +- ~~[ ] Experimaental mode to gather all links and check them in batches to study performance gains.~~ (dropped for now) +- ~~[ ] Proxy support to connect puppeteer to a remote service.~~ (dropped for now) +- ~~[ ] Puppeteer config support.~~ (dropped for now) ## Contributing diff --git a/index.test.js b/index.test.js index 111e19d..c1ab741 100644 --- a/index.test.js +++ b/index.test.js @@ -11,7 +11,7 @@ test("linkspector should check image links in Markdown file", async () => { let results = []; // Array to store the results if json is true for await (const { file, result } of linkspector( - "./test/fixtures/image/imageTest.yml", + "./test/fixtures/markdown/image/imageTest.yml", cmd )) { currentFile = file; @@ -47,7 +47,7 @@ test("linkspector should check relative links in Markdown file", async () => { let results = []; // Array to store the results if json is true for await (const { file, result } of linkspector( - "./test/fixtures/relative/.relativeTest.yml", + "./test/fixtures/markdown/relative/.relativeTest.yml", cmd )) { currentFile = file; @@ -110,5 +110,41 @@ test("linkspector should check top-level relative links in Markdown file", async } expect(hasErrorLinks).toBe(false); + expect(results.length).toBe(5); +}); + +test("linkspector should add back the removed duplicates when returning the results", async () => { + let hasErrorLinks = false; + let currentFile = ""; // Variable to store the current file name + let results = []; // Array to store the results if json is true + + for await (const { file, result } of linkspector( + "./test/fixtures/markdown/duplicates/duplicateTest.yml", + cmd + )) { + currentFile = file; + for (const linkStatusObj of result) { + if (cmd.json) { + results.push({ + file: currentFile, + link: linkStatusObj.link, + status_code: linkStatusObj.status_code, + line_number: linkStatusObj.line_number, + position: linkStatusObj.position, + status: linkStatusObj.status, + error_message: linkStatusObj.error_message, + }); + } + if (linkStatusObj.status === "error") { + hasErrorLinks = true; + } + } + } + + expect(hasErrorLinks).toBe(true); expect(results.length).toBe(4); + expect(results[0].status).toBe("alive"); + expect(results[1].status).toBe("error"); + expect(results[2].status).toBe("alive"); + expect(results[3].status).toBe("error"); }); diff --git a/lib/update-linkstatus-obj.js b/lib/update-linkstatus-obj.js index 08e763d..19381b5 100644 --- a/lib/update-linkstatus-obj.js +++ b/lib/update-linkstatus-obj.js @@ -1,46 +1,38 @@ -'use strict'; +"use strict"; -function updateLinkstatusObj(astNodes, linkStatus) { - const tempObject = {}; +function updateLinkStatusObj(astNodes, linkStatus) { + const updatedLinkStatus = [...linkStatus]; astNodes.forEach((node) => { - const url = node.url; - if (tempObject[url]) { - tempObject[url].push(node); + const existingLink = linkStatus.find((link) => link.link === node.url); + if (existingLink) { + const existingPosition = existingLink.position; + const nodePosition = node.position; + if ( + existingPosition.start.line !== nodePosition.start.line || + existingPosition.start.column !== nodePosition.start.column || + existingPosition.end.line !== nodePosition.end.line || + existingPosition.end.column !== nodePosition.end.column + ) { + updatedLinkStatus.push({ + ...existingLink, + line_number: nodePosition.start.line, + position: nodePosition, + }); + } } else { - tempObject[url] = [node]; + updatedLinkStatus.push({ + link: node.url, + status: null, + status_code: null, + line_number: null, + position: node.position, + error_message: null, + title: node.title, + children: node.children, + }); } }); - - for (const url in tempObject) { - const nodes = tempObject[url]; - if (nodes.length > 1) { - const firstNode = nodes[0]; - for (let i = 1; i < nodes.length; i++) { - const newNode = nodes[i]; - const matchingLinkStatus = linkStatus.find((status) => status.link === newNode.url); - if (matchingLinkStatus) { - linkStatus.push({ - ...matchingLinkStatus, - line_number: newNode.position.start.line, - position: { - start: { - line: newNode.position.start.line, - column: newNode.position.start.column, - offset: newNode.position.start.offset, - }, - end: { - line: newNode.position.end.line, - column: newNode.position.end.column, - offset: newNode.position.end.offset, - }, - }, - }); - } - } - } - } - - return linkStatus; + return updatedLinkStatus; } -export { updateLinkstatusObj }; \ No newline at end of file +export { updateLinkStatusObj }; diff --git a/linkspector.js b/linkspector.js index 28f6521..531c2dd 100644 --- a/linkspector.js +++ b/linkspector.js @@ -8,7 +8,7 @@ import { extractMarkdownHyperlinks } from "./lib/extract-markdown-hyperlinks.js" import { extractAsciiDocLinks } from "./lib/extract-asciidoc-hyperlinks.js"; import { getUniqueLinks } from "./lib/get-unique-links.js"; import { checkHyperlinks } from "./lib/batch-check-links.js"; -import { updateLinkstatusObj } from "./lib/update-linkstatus-obj.js"; +import { updateLinkStatusObj } from "./lib/update-linkstatus-obj.js"; // Function to check if git is installed function isGitInstalled() { @@ -57,7 +57,9 @@ export async function* linkspector(configFile, cmd) { } catch (err) { if (err.code === "ENOENT") { if (!cmd.json) { - console.log("Configuration file not found. Using default configuration."); + console.log( + "Configuration file not found. Using default configuration." + ); } config = defaultConfig; } else { @@ -105,7 +107,6 @@ export async function* linkspector(configFile, cmd) { // Otherwise, only check the modified files filesToCheck = modifiedFilesToCheck; - console.log(filesToCheck); } // Initialize an array to store link status objects @@ -139,15 +140,12 @@ export async function* linkspector(configFile, cmd) { const linkStatus = await checkHyperlinks(uniqueLinks, config, file); // Update linkStatusObjects with information about removed links - linkStatusObjects = await updateLinkstatusObj( - linkStatusObjects, - linkStatus - ); + const updatedLinkStatus = updateLinkStatusObj(astNodes, linkStatus); // Yield an object with the relative file path and its result yield { file: relativeFilePath, - result: linkStatusObjects, + result: updatedLinkStatus, }; } } diff --git a/test/fixtures/image/imageTest.yml b/test/fixtures/image/imageTest.yml deleted file mode 100644 index bcbd50d..0000000 --- a/test/fixtures/image/imageTest.yml +++ /dev/null @@ -1,2 +0,0 @@ -dirs: - - ./test/fixtures/image diff --git a/test/fixtures/markdown/duplicates/duplicate1.md b/test/fixtures/markdown/duplicates/duplicate1.md new file mode 100644 index 0000000..912a442 --- /dev/null +++ b/test/fixtures/markdown/duplicates/duplicate1.md @@ -0,0 +1,7 @@ +This is a link to [Google](https://www.google.com). + +this is a link to [Yahoo](https://www.yahoo434234esdsadasd.com). + +This is a link to [Google](https://www.google.com) again. + +this is a link to [Yahoo](https://www.yahoo434234esdsadasd.com) again. \ No newline at end of file diff --git a/test/fixtures/markdown/duplicates/duplicateTest.yml b/test/fixtures/markdown/duplicates/duplicateTest.yml new file mode 100644 index 0000000..8b6a834 --- /dev/null +++ b/test/fixtures/markdown/duplicates/duplicateTest.yml @@ -0,0 +1,2 @@ +dirs: + - ./test/fixtures/markdown/duplicates diff --git a/test/fixtures/image/image.md b/test/fixtures/markdown/image/image.md similarity index 100% rename from test/fixtures/image/image.md rename to test/fixtures/markdown/image/image.md diff --git a/test/fixtures/markdown/image/imageTest.yml b/test/fixtures/markdown/image/imageTest.yml new file mode 100644 index 0000000..5961a59 --- /dev/null +++ b/test/fixtures/markdown/image/imageTest.yml @@ -0,0 +1,2 @@ +dirs: + - ./test/fixtures/markdown/image diff --git a/test/fixtures/markdown/relative/.relativeTest.yml b/test/fixtures/markdown/relative/.relativeTest.yml new file mode 100644 index 0000000..873c817 --- /dev/null +++ b/test/fixtures/markdown/relative/.relativeTest.yml @@ -0,0 +1,2 @@ +dirs: + - ./test/fixtures/markdown/relative diff --git a/test/fixtures/relative/relative1.md b/test/fixtures/markdown/relative/relative1.md similarity index 100% rename from test/fixtures/relative/relative1.md rename to test/fixtures/markdown/relative/relative1.md diff --git a/test/fixtures/relative/relative2.md b/test/fixtures/markdown/relative/relative2.md similarity index 100% rename from test/fixtures/relative/relative2.md rename to test/fixtures/markdown/relative/relative2.md diff --git a/test/fixtures/relative/.relativeTest.yml b/test/fixtures/relative/.relativeTest.yml deleted file mode 100644 index bc5a453..0000000 --- a/test/fixtures/relative/.relativeTest.yml +++ /dev/null @@ -1,2 +0,0 @@ -dirs: - - ./test/fixtures/relative