markdown_link_checker_sc 0.0.117 → 0.0.118
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/helpers.js +11 -4
- package/src/links.js +5 -9
- package/src/output_errors.js +4 -5
- package/src/process_image_orphans.js +4 -6
- package/src/process_internal_url_links.js +2 -0
- package/src/process_local_image_links.js +4 -15
- package/src/process_markdown.js +12 -8
- package/src/process_orphans.js +3 -4
- package/src/process_relative_links.js +2 -3
- package/tests/links/html/img/tests1.md +12 -0
package/package.json
CHANGED
package/src/helpers.js
CHANGED
|
@@ -2,13 +2,20 @@ import fs from "fs/promises";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
4
|
|
|
5
|
+
// Call at start of function to ease logging to console.
|
|
6
|
+
function logFunction(name, ...args) {
|
|
7
|
+
sharedData.options.log.includes("functions")
|
|
8
|
+
? console.log(`${name}: ${args.join(", ")}`)
|
|
9
|
+
: null;
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
// Log data to specified file path, replacing file.
|
|
6
13
|
async function logToFile(filePath, dataString) {
|
|
7
14
|
sharedData.options.log.includes("functions")
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
? console.log(`Function: logToFile(${filePath}, dataString))`)
|
|
16
|
+
: null;
|
|
10
17
|
if (!sharedData.options.logtofile) {
|
|
11
|
-
|
|
18
|
+
return;
|
|
12
19
|
}
|
|
13
20
|
|
|
14
21
|
try {
|
|
@@ -48,4 +55,4 @@ function isHTML(file) {
|
|
|
48
55
|
return fileExtension === ".html" || fileExtension === ".htm" ? true : false;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
export { logToFile, isImage, isMarkdown, isHTML };
|
|
58
|
+
export { logToFile, logFunction, isImage, isMarkdown, isHTML };
|
package/src/links.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { isImage, isMarkdown, isHTML } from "./helpers.js";
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
|
+
import { logFunction } from "./helpers.js";
|
|
4
5
|
|
|
5
6
|
class Link {
|
|
6
7
|
address = "";
|
|
@@ -33,9 +34,7 @@ class Link {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
constructor({ page, url, type, text, title }) {
|
|
36
|
-
|
|
37
|
-
? console.log("Link:constructor")
|
|
38
|
-
: null;
|
|
37
|
+
logFunction("Link:constructor");
|
|
39
38
|
|
|
40
39
|
if (page) {
|
|
41
40
|
this.page = page;
|
|
@@ -110,9 +109,8 @@ class Link {
|
|
|
110
109
|
// This is only used if the type is not specified as an argument.
|
|
111
110
|
// Uses file extension etc, so should be run after SplitUrl() which finds the address
|
|
112
111
|
findType() {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
: null;
|
|
112
|
+
logFunction("Link:findType()");
|
|
113
|
+
|
|
116
114
|
let linkType = "unHandledLinkType";
|
|
117
115
|
|
|
118
116
|
this.isImage = this.address && isImage(this.address) ? true : false; //only if address is true.
|
|
@@ -182,9 +180,7 @@ class Link {
|
|
|
182
180
|
|
|
183
181
|
//get absolute path to link, if this is a relative URL link.
|
|
184
182
|
getAbsolutePath() {
|
|
185
|
-
|
|
186
|
-
? console.log(`Link:getAbsolutePath: page: ${this.page}, address: ${this.address} `)
|
|
187
|
-
: null;
|
|
183
|
+
logFunction("Link:getAbsolutePath", `this.page: ${this.page}`, `this.address: ${this.address}`);
|
|
188
184
|
if (!this.isRelative) throw new Error("Link:getAbsolutePath() called on non-relative path");
|
|
189
185
|
return path.resolve(path.dirname(this.page), this.address);
|
|
190
186
|
}
|
package/src/output_errors.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
//import { /*LinkError,*/ CurrentFileMissingAnchorError, LinkedFileMissingAnchorError, LinkedInternalPageMissingError, InternalLinkToHTMLError, UrlToLocalSiteError} from "./errors.js"
|
|
2
2
|
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
|
-
|
|
4
|
+
import { logFunction } from "./helpers.js";
|
|
5
5
|
|
|
6
6
|
//Function that generates console and/or log output from an array of error objects.
|
|
7
|
-
// - `results` is an array of error objects.
|
|
7
|
+
// - `results` is an array of error objects.
|
|
8
|
+
// These will have a `type` and a `page`. They may also have other values, depending on type of error - such as linkurl
|
|
8
9
|
function outputErrors(results) {
|
|
9
|
-
|
|
10
|
-
? console.log("Function: outputErrors()")
|
|
11
|
-
: null;
|
|
10
|
+
logFunction("Function: outputErrors()");
|
|
12
11
|
|
|
13
12
|
//Sort results by page and type.
|
|
14
13
|
// Perhaps next step is to create only get info for particular pages.
|
|
@@ -3,6 +3,7 @@ import fs from "fs";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { sharedData } from "./shared_data.js";
|
|
5
5
|
import { OrphanedImageError } from "./errors.js";
|
|
6
|
+
import { logFunction } from "./helpers.js";
|
|
6
7
|
|
|
7
8
|
function isImage(file) {
|
|
8
9
|
const imageExtensions = [".jpg", ".jpeg", ".png", ".svg", ".gif", ".webm"];
|
|
@@ -14,9 +15,7 @@ var otherFileTypes = []; // Just used for logging in function below.
|
|
|
14
15
|
|
|
15
16
|
// Gets all image files in a directory.
|
|
16
17
|
async function getAllImageFilesInDirectory(dir) {
|
|
17
|
-
|
|
18
|
-
? console.log(`Function: getAllImageFilesInDirectory(${dir})`)
|
|
19
|
-
: null;
|
|
18
|
+
logFunction(`Function: getAllImageFilesInDirectory(${dir})`)
|
|
20
19
|
|
|
21
20
|
// TODO put this all in a try catch and return a better error.
|
|
22
21
|
// Or perhaps put around parent.
|
|
@@ -43,9 +42,8 @@ async function getAllImageFilesInDirectory(dir) {
|
|
|
43
42
|
|
|
44
43
|
// Checks if any images in the options.directory
|
|
45
44
|
async function checkImageOrphansGlobal(results) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
: null;
|
|
45
|
+
logFunction(`Function: checkImageOrphansGlobal()`)
|
|
46
|
+
|
|
49
47
|
const errors = [];
|
|
50
48
|
let allImagesFound = [];
|
|
51
49
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { UrlToLocalSiteError} from "./errors.js"
|
|
3
|
+
import { logFunction } from "./helpers.js";
|
|
3
4
|
|
|
4
5
|
// An array of errors given a results object that contains our array of objects containing urls that link to our current site.
|
|
5
6
|
function processUrlsToLocalSource(results) {
|
|
7
|
+
logFunction(`Function: processUrlsToLocalSource()`);
|
|
6
8
|
const errors = [];
|
|
7
9
|
results.forEach((page, index, array) => {
|
|
8
10
|
//console.log(`PAGE: ${page}`);
|
|
@@ -2,11 +2,12 @@ import path from "path";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
4
|
import { LocalImageNotFoundError } from "./errors.js";
|
|
5
|
+
import { logFunction } from "./helpers.js";
|
|
5
6
|
|
|
6
7
|
// Checks if every image in every markdown page (results.page.relativeImageLinks) is present on the file system.
|
|
7
8
|
// - results is the array of information coming out of markdown parsing.
|
|
8
9
|
async function checkLocalImageLinks(results) {
|
|
9
|
-
|
|
10
|
+
logFunction(`Function: checkLocalImageLinks()`);
|
|
10
11
|
const errors = [];
|
|
11
12
|
const promises = [];
|
|
12
13
|
|
|
@@ -20,25 +21,13 @@ async function checkLocalImageLinks(results) {
|
|
|
20
21
|
//console.log(`link.linkUrlt: ${link.url}`);
|
|
21
22
|
//console.log(`dirname: ${path.dirname(page.page_file)}`);
|
|
22
23
|
|
|
23
|
-
const fullImagePath = path.join(
|
|
24
|
-
path.dirname(page.page_file),
|
|
25
|
-
link.url
|
|
26
|
-
);
|
|
24
|
+
const fullImagePath = path.join(path.dirname(page.page_file), link.url);
|
|
27
25
|
//console.log(`fullImagePath: ${fullImagePath}`);
|
|
28
26
|
const promise = new Promise((resolve) => {
|
|
29
27
|
fs.access(fullImagePath, fs.constants.F_OK, (err) => {
|
|
30
28
|
if (err) {
|
|
31
29
|
//console.log("Error");
|
|
32
|
-
|
|
33
|
-
/*
|
|
34
|
-
const error = {
|
|
35
|
-
type: "LocalImageNotFound",
|
|
36
|
-
page: `${page.page_file}`,
|
|
37
|
-
linkUrl: `${link.url}`,
|
|
38
|
-
linkText: `${link.text}`,
|
|
39
|
-
linkFullPath: `${fullImagePath}`,
|
|
40
|
-
};
|
|
41
|
-
*/
|
|
30
|
+
const error = new LocalImageNotFoundError({ link: link });
|
|
42
31
|
errors.push(error);
|
|
43
32
|
resolve(false);
|
|
44
33
|
} else {
|
package/src/process_markdown.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Link } from "./links.js";
|
|
2
2
|
import { sharedData } from "./shared_data.js";
|
|
3
|
+
import { logFunction } from "./helpers.js";
|
|
3
4
|
|
|
4
5
|
// Returns slug for a string (markdown heading) using Vuepress algorithm.
|
|
5
6
|
// Algorithm from chatgpt - needs testing.
|
|
6
7
|
const processMarkdown = (contents, page) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
: null;
|
|
8
|
+
logFunction(`Function: processMarkdown(): page: ${page}`);
|
|
9
|
+
|
|
10
10
|
const headings = [];
|
|
11
11
|
//const anchors = [];
|
|
12
12
|
const htmlAnchors = []; //{};
|
|
@@ -103,10 +103,10 @@ const processLineMarkdownLinks = (
|
|
|
103
103
|
unHandledLinkTypes,
|
|
104
104
|
page
|
|
105
105
|
) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
: null;
|
|
106
|
+
logFunction(`Function: processMarkdown(): page: ${page}`);
|
|
107
|
+
|
|
109
108
|
//const regex = /(?<prefix>[!@]?)\[(?<text>[^\]]+)\]\((?<url>\S+?)(?:\s+"(?<title>[^"]+)")?\)/g;
|
|
109
|
+
// Match to Markdown link OR image
|
|
110
110
|
const regex =
|
|
111
111
|
/(?<prefix>[!@]?)\[(?<text>[^\]]*)\]\((?<url>\S+?)(?:\s+"(?<title>[^"]+)")?\)/g;
|
|
112
112
|
const matches = line.matchAll(regex);
|
|
@@ -310,12 +310,16 @@ const processLineMarkdownLinks = (
|
|
|
310
310
|
//Might further parse this to catch img in anchor.
|
|
311
311
|
|
|
312
312
|
//Match for html img - append to the lists
|
|
313
|
-
const regexHTMLImgTotal = /<img\s+(?<attributes>.*?)
|
|
313
|
+
const regexHTMLImgTotal = /<img\s+(?<attributes>.*?)>/gi;
|
|
314
|
+
//const regexHTMLImgTotal = /<img\s+(?<attributes>.*?)\/>/gi;
|
|
315
|
+
|
|
314
316
|
const regex_htmlattr_src =
|
|
315
317
|
/src\s*[=]\s*(?<quote>['"])(?<src>.*?)(?<!\\)\k<quote>/i;
|
|
318
|
+
|
|
319
|
+
|
|
316
320
|
for (const match of line.matchAll(regexHTMLImgTotal)) {
|
|
321
|
+
//console.log(`XXXXXregexHTMLImgTotals: ${match}`)
|
|
317
322
|
const attributes = match.groups.attributes;
|
|
318
|
-
//console.log(`XXXXXImageattributes_s: ${attributes}`)
|
|
319
323
|
const linkText = "";
|
|
320
324
|
let linkTitle = "";
|
|
321
325
|
let linkUrl = "";
|
package/src/process_orphans.js
CHANGED
|
@@ -2,14 +2,13 @@ import { logToFile } from "./helpers.js";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
4
|
import { PageNotInTOCError, PageNotLinkedInternallyError } from "./errors.js";
|
|
5
|
-
|
|
5
|
+
import { logFunction } from "./helpers.js";
|
|
6
6
|
|
|
7
7
|
// Gets page with most links. Supposed to be used on the allResults object that is an array of objects about each page.
|
|
8
8
|
// Will use to get the summary.
|
|
9
9
|
function getPageWithMostLinks(pages) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
10
|
+
logFunction(`Function: getPageWithMostLinks`);
|
|
11
|
+
|
|
13
12
|
return pages.reduce(
|
|
14
13
|
(maxLinksPage, currentPage) => {
|
|
15
14
|
if (
|
|
@@ -7,12 +7,11 @@ import {
|
|
|
7
7
|
UrlToLocalSiteError,
|
|
8
8
|
} from "./errors.js";
|
|
9
9
|
import { sharedData } from "./shared_data.js";
|
|
10
|
+
import { logFunction } from "./helpers.js";
|
|
10
11
|
|
|
11
12
|
// An array of errors given a results object that contains our array of objects containing relativeLinks (and other information).
|
|
12
13
|
function processRelativeLinks(results) {
|
|
13
|
-
|
|
14
|
-
? console.log("Function: processRelativeLinks")
|
|
15
|
-
: null;
|
|
14
|
+
logFunction(`Function: processRelativeLinks()`);
|
|
16
15
|
const errors = [];
|
|
17
16
|
|
|
18
17
|
//console.log(sharedData);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Test
|
|
2
|
+
|
|
3
|
+
Run like: `node .\index.js -d tests/links/html/img/`
|
|
4
|
+
|
|
5
|
+
Confirm links with and without end backslash are caught.
|
|
6
|
+
Also with/without attributes
|
|
7
|
+
|
|
8
|
+
<img src="../../assets/airframes/multicopter/x500_holybro_pixhawk4/img_with_no_end_backslash_oneofthree.png" width="400" title="Hanger gaskets">
|
|
9
|
+
|
|
10
|
+
<img src="../../assets/airframes/multicopter/x500_holybro_pixhawk4/img_with_backslash_twoofthree.png" width="400" title="Hanger gaskets" />
|
|
11
|
+
|
|
12
|
+
<img src="img_with_backslash_no_attributes_threeofthree.png" />
|