@datalackey/update-markdown-toc 1.1.13 → 1.3.0
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 +9 -12
- package/bin/update-markdown-toc.js +5 -5
- package/dist/cli/TocRunConfig.d.ts +2 -0
- package/dist/cli/TocRunConfig.js +1 -0
- package/dist/cli/descriptor.d.ts +1 -2
- package/dist/cli/descriptor.js +7 -35
- package/dist/engine/TocFileProcessor.d.ts +2 -2
- package/dist/engine/generateToc.js +18 -7
- package/dist/engine/processFile.js +2 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
- [Design Goals and Philosophy](#design-goals-and-philosophy)
|
|
33
33
|
- [Packaging, Publishing, and Inter-relationship with Other Plugins](#packaging-publishing-and-inter-relationship-with-other-plugins)
|
|
34
34
|
- [Known Limitations](#known-limitations)
|
|
35
|
-
- [
|
|
35
|
+
- [Contributing and Releasing](#contributing-and-releasing)
|
|
36
36
|
<!-- TOC:END -->
|
|
37
37
|
|
|
38
38
|
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
|
|
41
41
|
A Node.js command-line **documentation helper** which automatically:
|
|
42
42
|
|
|
43
|
-
- generates Table of Contents (TOC) blocks for Markdown files
|
|
43
|
+
- generates Table of Contents (TOC) blocks for Markdown files (using GitHub's Markdown renderer)
|
|
44
44
|
- operates on either a single file, or recursively finds all `*.md` files from a root path
|
|
45
45
|
- regenerates TOCs from headings, targeting only regions explicitly marked with [TOC markers](#toc-markers)
|
|
46
46
|
- avoids gratuitous reformatting or changes of any kind outside of regions marked by the aforementioned [TOC markers](#toc-markers)
|
|
47
47
|
- avoids updating files when the generated TOC is already correct
|
|
48
48
|
- provides a `--check` mode which flags Markdown files with stale TOCs (intended for CI)
|
|
49
|
-
-
|
|
50
|
-
|
|
49
|
+
- validates intra-document links (i.e., those between Markdown docs in the repo (including #fragments, image paths)
|
|
50
|
+
- validates external HTTP/HTTPS links, with configurable timeout
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
## Why not Some Other Markdown TOC Generator ?
|
|
@@ -316,11 +316,6 @@ When such errors occur, the tool prints an error message and exits non-zero with
|
|
|
316
316
|
|
|
317
317
|
When combined with `--verbose`, skipped files (Markdown files without start/end region markers) are reported explicitly. For example:
|
|
318
318
|
|
|
319
|
-
```bash
|
|
320
|
-
update-markdown-toc --recursive docs/ --verbose
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
319
|
```bash
|
|
325
320
|
update-markdown-toc --recursive docs/ --verbose
|
|
326
321
|
```
|
|
@@ -355,7 +350,7 @@ The intended workflow is:
|
|
|
355
350
|
This package is one component of a small ecosystem of JavaScript tooling plugins maintained as individual npm packages in this repository.
|
|
356
351
|
The versioning and release of these packages is governed by a coordinated release policy, and
|
|
357
352
|
the packages adhere to common design and architectural principles policies
|
|
358
|
-
that are more completely described [here](
|
|
353
|
+
that are more completely described [here](../../README.md).
|
|
359
354
|
|
|
360
355
|
## Known Limitations
|
|
361
356
|
|
|
@@ -369,7 +364,9 @@ In practice this affects only headings with inline code, bold, or italic syntax.
|
|
|
369
364
|
Plain-text headings are unaffected. A fix to unify both paths is planned for a
|
|
370
365
|
future release.
|
|
371
366
|
|
|
372
|
-
##
|
|
367
|
+
## Contributing and Releasing
|
|
373
368
|
|
|
374
|
-
|
|
369
|
+
For development setup, build workflow, and release procedures (including how to
|
|
370
|
+
trigger a publish via Changesets), see
|
|
371
|
+
[CONTRIBUTING.md](../docs/CONTRIBUTING.md).
|
|
375
372
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { runCli } from "@datalackey/tooling-core"
|
|
4
|
-
import { TocFileProcessor } from "../dist/engine/TocFileProcessor.js"
|
|
5
|
-
import { descriptor } from "../dist/cli/descriptor.js"
|
|
3
|
+
import { runCli } from "@datalackey/tooling-core";
|
|
4
|
+
import { TocFileProcessor } from "../dist/engine/TocFileProcessor.js";
|
|
5
|
+
import { descriptor } from "../dist/cli/descriptor.js";
|
|
6
6
|
|
|
7
7
|
await runCli({
|
|
8
8
|
descriptor: descriptor,
|
|
9
|
-
processor: new TocFileProcessor()
|
|
10
|
-
})
|
|
9
|
+
processor: new TocFileProcessor(),
|
|
10
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/cli/descriptor.d.ts
CHANGED
package/dist/cli/descriptor.js
CHANGED
|
@@ -1,40 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const DEFAULT_LINK_TIMEOUT_MS = 3000;
|
|
1
|
+
import { runLinkValidation } from "@datalackey/tooling-core";
|
|
3
2
|
export const descriptor = {
|
|
4
3
|
name: "update-markdown-toc",
|
|
5
4
|
description: "Auto-generate Table of Contents for Markdown files",
|
|
6
|
-
options: [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
flag: "-n",
|
|
13
|
-
description: "Skip external link validation in check mode (short form)"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
flag: "--link-timeout-ms",
|
|
17
|
-
description: "Timeout in milliseconds for external link requests (default: 3000)",
|
|
18
|
-
requiresValue: true,
|
|
19
|
-
valueName: "ms"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
flag: "-l",
|
|
23
|
-
description: "Timeout in milliseconds for external link requests (short form)",
|
|
24
|
-
requiresValue: true,
|
|
25
|
-
valueName: "ms"
|
|
5
|
+
options: [],
|
|
6
|
+
async afterRun(files, config) {
|
|
7
|
+
if (config.runMode !== "check") {
|
|
8
|
+
return;
|
|
26
9
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const noExternalCheck = parseBooleanOption("--no-external-link-check", passthrough) ||
|
|
30
|
-
parseBooleanOption("-n", passthrough);
|
|
31
|
-
const timeoutMs = parseNumberOption("--link-timeout-ms", passthrough) ??
|
|
32
|
-
parseNumberOption("-l", passthrough) ??
|
|
33
|
-
DEFAULT_LINK_TIMEOUT_MS;
|
|
34
|
-
return {
|
|
35
|
-
...standard,
|
|
36
|
-
validateExternalLinks: noExternalCheck ? false : standard.validateExternalLinks,
|
|
37
|
-
linkTimeoutMs: timeoutMs
|
|
38
|
-
};
|
|
39
|
-
}
|
|
10
|
+
await runLinkValidation(files, config);
|
|
11
|
+
},
|
|
40
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FileProcessor } from "@datalackey/tooling-core";
|
|
1
|
+
import type { FileProcessor, ProcessingStatus } from "@datalackey/tooling-core";
|
|
2
2
|
import type { RunConfig } from "@datalackey/tooling-core";
|
|
3
3
|
export declare class TocFileProcessor implements FileProcessor<RunConfig> {
|
|
4
|
-
process(filePath: string, config: RunConfig):
|
|
4
|
+
process(filePath: string, config: RunConfig): ProcessingStatus;
|
|
5
5
|
}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import GithubSlugger from "github-slugger";
|
|
2
2
|
const START = "<!-- TOC:START -->";
|
|
3
3
|
const END = "<!-- TOC:END -->";
|
|
4
|
+
function stripFencedLines(lines) {
|
|
5
|
+
let inFence = false;
|
|
6
|
+
const result = [];
|
|
7
|
+
for (const line of lines) {
|
|
8
|
+
if (line.startsWith("```")) {
|
|
9
|
+
inFence = !inFence;
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (!inFence)
|
|
13
|
+
result.push(line);
|
|
14
|
+
}
|
|
15
|
+
if (inFence)
|
|
16
|
+
throw new Error("Unclosed code fence (```) in document");
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
4
19
|
function detectLineEnding(text) {
|
|
5
20
|
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
6
21
|
}
|
|
@@ -18,13 +33,11 @@ export function generateTOC(content) {
|
|
|
18
33
|
const endIndex = content.indexOf(END);
|
|
19
34
|
const before = content.slice(0, startIndex);
|
|
20
35
|
const after = content.slice(endIndex + END.length);
|
|
21
|
-
const contentWithoutTOC = before.replace(/\s*$/, "") +
|
|
22
|
-
lineEnding +
|
|
23
|
-
after.replace(/^\s*/, "");
|
|
36
|
+
const contentWithoutTOC = before.replace(/\s*$/, "") + lineEnding + after.replace(/^\s*/, "");
|
|
24
37
|
const lines = contentWithoutTOC.split(lineEnding);
|
|
25
38
|
const headings = [];
|
|
26
39
|
const slugger = new GithubSlugger();
|
|
27
|
-
for (const line of lines) {
|
|
40
|
+
for (const line of stripFencedLines(lines)) {
|
|
28
41
|
const m = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
29
42
|
if (!m)
|
|
30
43
|
continue;
|
|
@@ -41,8 +54,6 @@ export function generateTOC(content) {
|
|
|
41
54
|
const indent = " ".repeat(h.level - minLevel);
|
|
42
55
|
return `${indent}- [${h.title}](#${h.anchor})`;
|
|
43
56
|
});
|
|
44
|
-
const tocBlock = lineEnding +
|
|
45
|
-
tocLines.join(lineEnding) +
|
|
46
|
-
lineEnding;
|
|
57
|
+
const tocBlock = lineEnding + tocLines.join(lineEnding) + lineEnding;
|
|
47
58
|
return before + START + tocBlock + END + after;
|
|
48
59
|
}
|
|
@@ -29,8 +29,8 @@ export function processFile(filePath, config) {
|
|
|
29
29
|
return "unchanged";
|
|
30
30
|
}
|
|
31
31
|
if (config.runMode === "check") {
|
|
32
|
-
debugLog(config, `processFile:
|
|
33
|
-
return "
|
|
32
|
+
debugLog(config, `processFile: needsUpdate filePath=${absolutePath}`);
|
|
33
|
+
return "needsUpdate";
|
|
34
34
|
}
|
|
35
35
|
fs.writeFileSync(filePath, updated, "utf8");
|
|
36
36
|
debugLog(config, `processFile: updated filePath=${absolutePath}`);
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalackey/update-markdown-toc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Auto-generate Table of Contents for a Markdown file (or files, recursively from a top level folder)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"private": false,
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsc -p tsconfig.json",
|
|
10
|
-
"test": "bash scripts/run-all-tests.sh"
|
|
10
|
+
"test": "npx vitest run --config vitest.config.ts && bash scripts/run-all-tests.sh"
|
|
11
11
|
},
|
|
12
12
|
"bin": {
|
|
13
13
|
"update-markdown-toc": "./bin/update-markdown-toc.js"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^18.19.130",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vitest": "^1.0.0"
|
|
55
55
|
}
|
|
56
56
|
}
|