-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathfix-links.js
82 lines (72 loc) · 2.46 KB
/
fix-links.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
const fs = require("fs")
/**
* Sorry about the very crude regex.
* It captures:
* [links like this](/foo/bar)
* It does *not* capture:
* [links like this](./foo/bar)
* [links like this](http://foo/bar)
* [links like this](/img/foo/bar.png)
* [links like this](/foo/bar.md)
*/
const regex = /\[([^\]]+)\]\(\/(?!img)([^)]+(?<!md#?(.*)))\)/
const replaceWith = "../"
const indexFilenames = ['index.md', 'excel-to-genesis.md']
const isIndexFile = file => indexFilenames.indexOf(file) !== -1
const walkDirectory = (root, depth = 1) => {
const entries = fs.readdirSync(root, { withFileTypes: true })
const dirs = entries.filter(e => e.isDirectory())
const files = entries.filter(e => e.isFile() && e.name.endsWith(".md"))
let paths = []
for (const dir of dirs) {
paths = paths.concat(walkDirectory(`${root}/${dir.name}`, depth + 1))
}
for (const file of files) {
const path = `${root}/${file.name}`
const data = fs.readFileSync(path).toString('utf8')
if (regex.test(data)) {
// index files aren't served from /folder/index/, they're served from /folder/ - so we need
// to decrease the depth accordingly
if (isIndexFile(file.name)) {
depth -= 1
}
paths.push({path, depth})
}
}
return paths
}
const replaceFile = (path, depth) => {
const data = fs.readFileSync(path).toString('utf8')
const replaced = replaceString(data, depth)
fs.writeFileSync(path, replaced)
}
const replaceString = (data, depth) => {
const globalRegex = new RegExp(regex, "g")
const replacedPath = replaceWith.repeat(depth)
return data.replaceAll(globalRegex, "[$1](" + replacedPath + "$2)")
}
const runMain = () => {
const paths = [].concat(
walkDirectory("./docs"),
)
for (const {path, depth} of paths) {
replaceFile(path, depth)
}
}
const runTests = () => {
const assert = require('node:assert')
const test = (actual, expected) => {
console.log(`Testing '${actual}'`)
assert.equal(replaceString(actual, 1), expected)
}
test("foo [bar](/baz)", "foo [bar](../baz)")
test("foo [bar](../baz)", "foo [bar](../baz)")
test("foo [bar](/baz) boo [fish](/test)", "foo [bar](../baz) boo [fish](../test)")
test("[bar](/f/baz.md)", "[bar](/f/baz.md)")
test("[bar](/f/baz.md#test)", "[bar](/f/baz.md#test)")
}
if (process.argv[2] === "--test") {
runTests()
} else {
runMain()
}