Skip to content

Commit

Permalink
doc: tests local links in markdown documents
Browse files Browse the repository at this point in the history
PR-URL: #32359
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
aduh95 authored and targos committed Apr 22, 2020
1 parent 9c84d77 commit e51c42d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 9 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ test-doc: doc-only lint ## Builds, lints, and verifies the docs.
else \
$(PYTHON) tools/test.py $(PARALLEL_ARGS) doctool; \
fi
$(NODE) tools/doc/checkLinks.js .

test-known-issues: all
$(PYTHON) tools/test.py $(PARALLEL_ARGS) known_issues
Expand Down
8 changes: 4 additions & 4 deletions doc/guides/collaborator-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

This document explains how Collaborators manage the Node.js project.
Collaborators should understand the
[guidelines for new contributors](CONTRIBUTING.md) and the
[project governance model](GOVERNANCE.md).
[guidelines for new contributors](../../CONTRIBUTING.md) and the
[project governance model](../../GOVERNANCE.md).

## Issues and Pull Requests

Expand All @@ -50,7 +50,7 @@ request. See [Who to CC in the issue tracker](#who-to-cc-in-the-issue-tracker).

Always show courtesy to individuals submitting issues and pull requests. Be
welcoming to first-time contributors, identified by the GitHub
![First-time contributor](./doc/first_timer_badge.png) badge.
![First-time contributor](../first_timer_badge.png) badge.

For first-time contributors, check if the commit author is the same as the pull
request author. This way, once their pull request lands, GitHub will show them
Expand Down Expand Up @@ -474,7 +474,7 @@ $ git checkout master
```

Update the tree (assumes your repo is set up as detailed in
[CONTRIBUTING.md](./doc/guides/contributing/pull-requests.md#step-1-fork)):
[CONTRIBUTING.md](./contributing/pull-requests.md#step-1-fork)):

```text
$ git fetch upstream
Expand Down
4 changes: 2 additions & 2 deletions doc/guides/cpp-style-guide.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# C++ Style Guide

See also the [C++ codebase README](src/README.md) for C++ idioms in the Node.js
codebase not related to stylistic issues.
See also the [C++ codebase README](../../src/README.md) for C++ idioms in the
Node.js codebase not related to stylistic issues.

## Table of Contents

Expand Down
4 changes: 2 additions & 2 deletions doc/guides/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,8 @@ accordingly by removing the bold styling from the previous release.
If this release includes new APIs then it is necessary to document that they
were first added in this version. The relevant commits should already include
`REPLACEME` tags as per the example in the
[docs README](../tools/doc/README.md). Check for these tags with `grep REPLACEME
doc/api/*.md`, and substitute this node version with `sed -i
[docs README](../../tools/doc/README.md). Check for these tags with `grep
REPLACEME doc/api/*.md`, and substitute this node version with `sed -i
"s/REPLACEME/$VERSION/g" doc/api/*.md` or `perl -pi -e "s/REPLACEME/$VERSION/g"
doc/api/*.md`.

Expand Down
2 changes: 1 addition & 1 deletion onboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ onboarding session.
* Be nice about closing issues! Let people know why, and that issues and PRs
can be reopened if necessary

* [**See "Labels"**](./onboarding-extras.md#labels)
* [**See "Labels"**](./doc/guides/onboarding-extras.md#labels)
* There is [a bot](https://github.com/nodejs-github-bot/github-bot) that
applies subsystem labels (for example, `doc`, `test`, `assert`, or `buffer`)
so that we know what parts of the code base the pull request modifies. It is
Expand Down
74 changes: 74 additions & 0 deletions tools/doc/checkLinks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict';

const fs = require('fs');
const { Worker, isMainThread, workerData: path } = require('worker_threads');

function* getLinksRecursively(node) {
if (
(node.type === 'link' && !node.url.startsWith('#')) ||
node.type === 'image'
) {
yield node;
}
for (const child of node.children || []) {
yield* getLinksRecursively(child);
}
}

if (isMainThread) {
const { extname, join, resolve } = require('path');
const DIR = resolve(process.argv[2]);

console.log('Running Markdown link checker...');

async function* findMarkdownFilesRecursively(dirPath) {
const fileNames = await fs.promises.readdir(dirPath);

for (const fileName of fileNames) {
const path = join(dirPath, fileName);

const stats = await fs.promises.stat(path);
if (
stats.isDirectory() &&
fileName !== 'api' &&
fileName !== 'deps' &&
fileName !== 'node_modules'
) {
yield* findMarkdownFilesRecursively(path);
} else if (extname(fileName) === '.md') {
yield path;
}
}
}

function errorHandler(error) {
console.error(error);
process.exitCode = 1;
}

setImmediate(async () => {
for await (const path of findMarkdownFilesRecursively(DIR)) {
new Worker(__filename, { workerData: path }).on('error', errorHandler);
}
});
} else {
const unified = require('unified');
const { pathToFileURL } = require('url');

const tree = unified()
.use(require('remark-parse'))
.parse(fs.readFileSync(path));

const base = pathToFileURL(path);
for (const node of getLinksRecursively(tree)) {
const targetURL = new URL(node.url, base);
if (targetURL.protocol === 'file:' && !fs.existsSync(targetURL)) {
const error = new Error('Broken link in a Markdown document.');
const { start } = node.position;
error.stack =
error.stack.substring(0, error.stack.indexOf('\n') + 5) +
`at ${node.type} (${path}:${start.line}:${start.column})`;
throw error;
}
}
}

0 comments on commit e51c42d

Please sign in to comment.