markdown_link_checker_sc 0.0.136 → 0.0.138
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/README.md +20 -9
- package/index.js +52 -25
- package/package.json +1 -1
- package/src/errors.js +5 -1
- package/src/filters.js +4 -3
- package/src/links.js +2 -2
- package/src/output_errors.js +3 -3
- package/src/process_image_orphans.js +4 -4
- package/src/process_local_image_links.js +2 -2
package/README.md
CHANGED
|
@@ -12,25 +12,36 @@ Current version only does internal link checking
|
|
|
12
12
|
Usage: markdown_link_checker_sc [options]
|
|
13
13
|
|
|
14
14
|
Options:
|
|
15
|
-
-r, --
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-i, --imagedir [directory] The directory to search for all image files for global orphan checking, relative
|
|
20
|
-
|
|
15
|
+
-r, --repo <path> Repo root directory. Defaults to current directory. Everything resolved relative to this.) (default: "")
|
|
16
|
+
-d, --doc [directory] Docs root directory, relative to -g (such as `docs`). Defaults to '' (all docs in root of repo). Use -d as well to restrict search to a particular subfolder. Defaults to current directory. (default:
|
|
17
|
+
"D:\\github\\hamishwillee\\markdown_link_checker_sc")
|
|
18
|
+
-e, --subdir [directory] A subfolder of the docs root (-d) to search for markdown and html files. Such as: `en` for an English subfolder. Default empty (same as -d directory) (default: "")
|
|
19
|
+
-i, --imagedir [directory] The directory to search for all image files for global orphan checking, relative docs root (-d) - such as: `assets` or `en`. Default empty if not explicitly set, and global orphan checking will not be done
|
|
20
|
+
(default: "")
|
|
21
21
|
-c, --headingAnchorSlugify [value] Slugify approach for turning markdown headings into heading anchors. Currently support vuepress only and always (default: "vuepress")
|
|
22
22
|
-t, --tryMarkdownforHTML [value] Try a markdown file extension check if a link to HTML fails. (default: true)
|
|
23
23
|
-l, --log <types...> Types of console logs to display logs for debugging. Types: functions, todo etc.
|
|
24
|
-
-f, --files <path> JSON file with array of files to report on (default is all files).
|
|
25
|
-
root. (default: "")
|
|
24
|
+
-f, --files <path> JSON file with array of files to report on (default is all files). JSON paths are usually relative to git repo root `-r`. (default: "")
|
|
26
25
|
-s, --toc [value] full filename of TOC/Summary file in file system. If not specified, inferred from file with most links to other files
|
|
27
26
|
-u, --site_url [value] Site base url in form dev.example.com (used to catch absolute urls to local files)
|
|
28
27
|
-o, --logtofile [value] Output logs to file (default: true)
|
|
29
|
-
-p, --interactive [value] Interactively add errors to the ignore list at _link_checker_sc/ignore_errors.json (default: false)
|
|
28
|
+
-p, --interactive [value] Interactively add errors to the ignore list at <repo>/_link_checker_sc/ignore_errors.json (default: false)
|
|
30
29
|
-c, --anchor_in_heading [value] Detect anchors in heading such as: # Heading {#anchor} (default: true)
|
|
31
30
|
-h, --help display help for command
|
|
32
31
|
```
|
|
33
32
|
|
|
33
|
+
## Ignore file
|
|
34
|
+
|
|
35
|
+
You can create a `_link_checker_sc\ignorefile.json` in the docs (path specified by `-d`) that lists any files you want to avoid parsing.
|
|
36
|
+
This is a JSON array of file paths relative the the docsroot.
|
|
37
|
+
|
|
38
|
+
For example, to not parse `en/_sidebar.md` your ignore file would have this pattern:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
["en/_sidebar.md"]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Note that a missing ignorefile is not an error.
|
|
34
45
|
|
|
35
46
|
## What link formats can it match
|
|
36
47
|
|
package/index.js
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { sharedData } from "./src/shared_data.js";
|
|
6
|
-
//const path = require("path");
|
|
7
6
|
import { program } from "commander";
|
|
8
|
-
//const { program } = require("commander");
|
|
9
7
|
import {
|
|
10
8
|
logFunction,
|
|
11
9
|
logToFile,
|
|
@@ -30,19 +28,23 @@ import { filterErrors, filterIgnoreErrors } from "./src/filters.js";
|
|
|
30
28
|
|
|
31
29
|
program
|
|
32
30
|
.option(
|
|
33
|
-
"-r, --
|
|
34
|
-
"
|
|
31
|
+
"-r, --repo <path>",
|
|
32
|
+
"Repo root directory. Defaults to current directory. Everything resolved relative to this.)",
|
|
33
|
+
""
|
|
34
|
+
)
|
|
35
|
+
.option(
|
|
36
|
+
"-d, --doc [directory]",
|
|
37
|
+
"Docs root directory, relative to -g (such as `docs`). Defaults to '' (all docs in root of repo). Use -d as well to restrict search to a particular subfolder. Defaults to current directory.",
|
|
35
38
|
process.cwd()
|
|
36
39
|
)
|
|
37
40
|
.option(
|
|
38
|
-
"-
|
|
39
|
-
"A subfolder
|
|
41
|
+
"-e, --subdir [directory]",
|
|
42
|
+
"A subfolder of the docs root (-d) to search for markdown and html files. Such as: `en` for an English subfolder. Default empty (same as -d directory)",
|
|
40
43
|
""
|
|
41
44
|
)
|
|
42
|
-
|
|
43
45
|
.option(
|
|
44
46
|
"-i, --imagedir [directory]",
|
|
45
|
-
"The directory to search for all image files for global orphan checking, relative
|
|
47
|
+
"The directory to search for all image files for global orphan checking, relative docs root (-d) - such as: `assets` or `en`. Default empty if not explicitly set, and global orphan checking will not be done",
|
|
46
48
|
""
|
|
47
49
|
)
|
|
48
50
|
.option(
|
|
@@ -61,12 +63,7 @@ program
|
|
|
61
63
|
)
|
|
62
64
|
.option(
|
|
63
65
|
"-f, --files <path>",
|
|
64
|
-
"JSON file with array of files to report on (default is all files). JSON paths are usually relative to git root
|
|
65
|
-
""
|
|
66
|
-
)
|
|
67
|
-
.option(
|
|
68
|
-
"-g, --repo [directory]",
|
|
69
|
-
"Repo root directory. Files in -f JSON are resolved to absolute paths relative to this dir. Defaults to current directory.)",
|
|
66
|
+
"JSON file with array of files to report on (default is all files). JSON paths are usually relative to git repo root `-r`.",
|
|
70
67
|
""
|
|
71
68
|
)
|
|
72
69
|
.option(
|
|
@@ -80,7 +77,7 @@ program
|
|
|
80
77
|
.option("-o, --logtofile [value]", "Output logs to file", true)
|
|
81
78
|
.option(
|
|
82
79
|
"-p, --interactive [value]",
|
|
83
|
-
"Interactively add errors to the ignore list at _link_checker_sc/ignore_errors.json",
|
|
80
|
+
"Interactively add errors to the ignore list at <repo>/_link_checker_sc/ignore_errors.json",
|
|
84
81
|
false
|
|
85
82
|
)
|
|
86
83
|
.option(
|
|
@@ -102,11 +99,40 @@ sharedData.allHTMLFiles = new Set([]);
|
|
|
102
99
|
sharedData.allImageFiles = new Set([]);
|
|
103
100
|
sharedData.allOtherFiles = new Set([]);
|
|
104
101
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
function resolveRepoPath(repoOption) {
|
|
103
|
+
// This gets the path from CWD by default, or resolves path up.
|
|
104
|
+
if (!repoOption || repoOption === ".") {
|
|
105
|
+
return process.cwd(); // Current working directory (Node.js)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (repoOption === "..") {
|
|
109
|
+
return path.resolve(process.cwd(), ".."); // One directory up
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return path.resolve(repoOption); // Resolve to absolute path
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
sharedData.options.repo = resolveRepoPath(sharedData.options.repo);
|
|
116
|
+
|
|
117
|
+
sharedData.options.docsroot = path.join(
|
|
118
|
+
sharedData.options.repo,
|
|
119
|
+
sharedData.options.doc
|
|
108
120
|
);
|
|
109
121
|
|
|
122
|
+
// Markdown directory we are actually checking
|
|
123
|
+
sharedData.options.markdownroot = path.join(
|
|
124
|
+
sharedData.options.docsroot,
|
|
125
|
+
sharedData.options.subdir
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
//console.log(`debug: sharedData.options.repo: ${sharedData.options.repo}`);
|
|
129
|
+
//console.log(`debug: sharedData.options.doc: ${sharedData.options.doc}`);
|
|
130
|
+
//console.log(`debug: sharedData.options.subdir: ${sharedData.options.subdir}`);
|
|
131
|
+
//console.log(`debug: sharedData.options.docsroot: ${sharedData.options.docsroot}`);
|
|
132
|
+
//console.log(`debug: sharedData.options.markdownroot: ${sharedData.options.markdownroot}`);
|
|
133
|
+
|
|
134
|
+
//process.exit(1);
|
|
135
|
+
|
|
110
136
|
// Function for loading JSON file that contains files to report on
|
|
111
137
|
async function loadJSONFileToReportOn(filePath) {
|
|
112
138
|
sharedData.options.log.includes("functions")
|
|
@@ -150,9 +176,9 @@ async function loadJSONFileToIgnore(filePath) {
|
|
|
150
176
|
if (filesArray.length == 0) {
|
|
151
177
|
return [];
|
|
152
178
|
} else {
|
|
153
|
-
// Array relative to root, so update to have full path
|
|
179
|
+
// Array relative to repo root, so update to have full path
|
|
154
180
|
filesArray = filesArray.map((str) =>
|
|
155
|
-
path.join(sharedData.options.
|
|
181
|
+
path.join(sharedData.options.docsroot, str)
|
|
156
182
|
);
|
|
157
183
|
}
|
|
158
184
|
|
|
@@ -162,8 +188,8 @@ async function loadJSONFileToIgnore(filePath) {
|
|
|
162
188
|
|
|
163
189
|
return filesArray;
|
|
164
190
|
} catch (error) {
|
|
165
|
-
//console.
|
|
166
|
-
|
|
191
|
+
//console.log(`Error reading ignore file: ${error.message}`);
|
|
192
|
+
//Note, ignore file is private really.
|
|
167
193
|
return [];
|
|
168
194
|
//process.exit(1);
|
|
169
195
|
}
|
|
@@ -215,7 +241,7 @@ const processDirectory = async (dir) => {
|
|
|
215
241
|
results.push(...subResults);
|
|
216
242
|
} else if (sharedData.options.ignoreFiles.includes(file)) {
|
|
217
243
|
// do nothing
|
|
218
|
-
//
|
|
244
|
+
//console.log(`XxxxXignorelist: file: ${file}`);
|
|
219
245
|
} else if (isMarkdown(file)) {
|
|
220
246
|
sharedData.allMarkdownFiles.add(file);
|
|
221
247
|
const result = await processFile(file);
|
|
@@ -246,7 +272,8 @@ const processDirectory = async (dir) => {
|
|
|
246
272
|
: (sharedData.options.files = []);
|
|
247
273
|
|
|
248
274
|
const pathToJsonIgnoreFile = path.join(
|
|
249
|
-
sharedData.options.
|
|
275
|
+
sharedData.options.repo,
|
|
276
|
+
sharedData.options.doc,
|
|
250
277
|
"_link_checker_sc/ignorefile.json"
|
|
251
278
|
);
|
|
252
279
|
//console.log(`debug: pathToJsonIgnoreFile: ${pathToJsonIgnoreFile}`);
|
|
@@ -255,7 +282,7 @@ const processDirectory = async (dir) => {
|
|
|
255
282
|
);
|
|
256
283
|
|
|
257
284
|
// process containing markdown, return results which includes links, headings, id anchors
|
|
258
|
-
const results = await processDirectory(
|
|
285
|
+
const results = await processDirectory(sharedData.options.markdownroot);
|
|
259
286
|
|
|
260
287
|
if (!results.allErrors) {
|
|
261
288
|
results.allErrors = [];
|
package/package.json
CHANGED
package/src/errors.js
CHANGED
|
@@ -11,14 +11,18 @@ class LinkError {
|
|
|
11
11
|
this.link = link;
|
|
12
12
|
this.file = this.link.page;
|
|
13
13
|
this.fileRelativeToRoot = this.link.fileRelativeToRoot;
|
|
14
|
+
//console.log(`debugX: fileRelativeToRoot: ${this.fileRelativeToRoot}`);
|
|
14
15
|
} else {
|
|
15
16
|
this.file = file; // i.e. infer file from link, but if link not specified then can take passed value
|
|
16
|
-
this.fileRelativeToRoot = this.file.split(sharedData.options.
|
|
17
|
+
this.fileRelativeToRoot = this.file.split(sharedData.options.docsroot)[1];
|
|
18
|
+
//console.log( `debug: sharedData.options.docsroot: ${sharedData.options.docsroot}` );
|
|
19
|
+
//console.log(`debug: fileRelativeToRoot: ${this.fileRelativeToRoot}`);
|
|
17
20
|
this.fileRelativeToRoot =
|
|
18
21
|
this.fileRelativeToRoot.startsWith("/") ||
|
|
19
22
|
this.fileRelativeToRoot.startsWith("\\")
|
|
20
23
|
? this.fileRelativeToRoot.substring(1)
|
|
21
24
|
: this.fileRelativeToRoot;
|
|
25
|
+
//console.log(`debug: 2fileRelativeToRoot: ${this.fileRelativeToRoot}`);
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
|
package/src/filters.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { sharedData } from "./shared_data.js";
|
|
4
4
|
import { logFunction } from "./helpers.js";
|
|
5
|
-
import normalize from
|
|
5
|
+
import normalize from "normalize-path";
|
|
6
6
|
|
|
7
7
|
function filterIgnoreErrors(errors) {
|
|
8
8
|
// This method removes any errors that are in the ignore errors list
|
|
@@ -11,7 +11,7 @@ function filterIgnoreErrors(errors) {
|
|
|
11
11
|
// Currently it is the pages to output, as listed in the options.files to output.
|
|
12
12
|
logFunction(`Function: filterIgnoreErrors(${errors})`);
|
|
13
13
|
const errorFile = path.join(
|
|
14
|
-
sharedData.options.
|
|
14
|
+
sharedData.options.docsroot,
|
|
15
15
|
"./_link_checker_sc/ignore_errors.json"
|
|
16
16
|
);
|
|
17
17
|
|
|
@@ -33,7 +33,8 @@ function filterIgnoreErrors(errors) {
|
|
|
33
33
|
sharedData.IgnoreErrors.forEach((ignorableError) => {
|
|
34
34
|
if (
|
|
35
35
|
error.type === ignorableError.type &&
|
|
36
|
-
normalize(error.fileRelativeToRoot) ===
|
|
36
|
+
normalize(error.fileRelativeToRoot) ===
|
|
37
|
+
normalize(ignorableError.fileRelativeToRoot)
|
|
37
38
|
) {
|
|
38
39
|
// Same file and type, so probably filter out.
|
|
39
40
|
if (!(error.link && ignorableError.link)) {
|
package/src/links.js
CHANGED
|
@@ -42,9 +42,9 @@ class Link {
|
|
|
42
42
|
} else {
|
|
43
43
|
throw new Error("Link: page argument is required.");
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
//console.log(`debug: page: ${page}, sharedData.options.docsroot: ${sharedData.options.docsroot}`);
|
|
46
46
|
// Create a relative file link for comparison
|
|
47
|
-
this.fileRelativeToRoot = this.page.split(sharedData.options.
|
|
47
|
+
this.fileRelativeToRoot = this.page.split(sharedData.options.docsroot)[1];
|
|
48
48
|
this.fileRelativeToRoot = (this.fileRelativeToRoot.startsWith('/') || this.fileRelativeToRoot.startsWith('\\')) ? this.fileRelativeToRoot.substring(1) : this.fileRelativeToRoot
|
|
49
49
|
|
|
50
50
|
if (url) {
|
package/src/output_errors.js
CHANGED
|
@@ -37,10 +37,10 @@ function outputErrors(results) {
|
|
|
37
37
|
//console.log(sortedByPageErrors);
|
|
38
38
|
for (const page in sortedByPageErrors) {
|
|
39
39
|
let pageFromRoot;
|
|
40
|
-
if (sharedData.options.
|
|
41
|
-
pageFromRoot = page.split(sharedData.options.
|
|
40
|
+
if (sharedData.options.docsroot) {
|
|
41
|
+
pageFromRoot = page.split(sharedData.options.docsroot)[1];
|
|
42
42
|
} else {
|
|
43
|
-
pageFromRoot = page.split(sharedData.options.
|
|
43
|
+
pageFromRoot = page.split(sharedData.options.markdownroot)[1];
|
|
44
44
|
}
|
|
45
45
|
//console.log(`\nXX${page}`); //Root needs to full path - not '.' or whatever
|
|
46
46
|
console.log(`\n${pageFromRoot}`); //Root needs to full path - not '.' or whatever
|
|
@@ -15,7 +15,7 @@ var otherFileTypes = []; // Just used for logging in function below.
|
|
|
15
15
|
|
|
16
16
|
// Gets all image files in a directory.
|
|
17
17
|
async function getAllImageFilesInDirectory(dir) {
|
|
18
|
-
logFunction(`Function: getAllImageFilesInDirectory(${dir})`)
|
|
18
|
+
logFunction(`Function: getAllImageFilesInDirectory(${dir})`);
|
|
19
19
|
|
|
20
20
|
// TODO put this all in a try catch and return a better error.
|
|
21
21
|
// Or perhaps put around parent.
|
|
@@ -42,14 +42,14 @@ async function getAllImageFilesInDirectory(dir) {
|
|
|
42
42
|
|
|
43
43
|
// Checks if any images in the options.directory
|
|
44
44
|
async function checkImageOrphansGlobal(results) {
|
|
45
|
-
logFunction(`Function: checkImageOrphansGlobal()`)
|
|
46
|
-
|
|
45
|
+
logFunction(`Function: checkImageOrphansGlobal()`);
|
|
46
|
+
|
|
47
47
|
const errors = [];
|
|
48
48
|
let allImagesFound = [];
|
|
49
49
|
|
|
50
50
|
if (sharedData.options.imagedir !== "") {
|
|
51
51
|
const imagePath = path.resolve(
|
|
52
|
-
sharedData.options.
|
|
52
|
+
sharedData.options.docsroot,
|
|
53
53
|
sharedData.options.imagedir
|
|
54
54
|
);
|
|
55
55
|
|
|
@@ -16,8 +16,8 @@ async function checkLocalImageLinks(results) {
|
|
|
16
16
|
|
|
17
17
|
page.relativeImageLinks.forEach((link, index, array) => {
|
|
18
18
|
//console.log(`XYYXLINK: ${JSON.stringify(link, null, 2)}`);
|
|
19
|
-
//console.log(`sharedData.options.
|
|
20
|
-
//console.log(`sharedData.options.
|
|
19
|
+
//console.log(`sharedData.options.repo: ${sharedData.options.repo}`);
|
|
20
|
+
//console.log(`sharedData.options.subdir: ${sharedData.options.subdir}`);
|
|
21
21
|
//console.log(`link.linkUrlt: ${link.url}`);
|
|
22
22
|
//console.log(`dirname: ${path.dirname(page.page_file)}`);
|
|
23
23
|
|