/
index.js
68 lines (57 loc) · 1.68 KB
/
index.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
'use strict';
const rule = require('unified-lint-rule');
const visit = require('unist-util-visit');
const banned = require('./banned.json');
const starts = ['this', 'the'];
const bannedRegex = banned.reduce((arr, b) => {
starts.forEach((s) => {
const trimmed = b.replace(s, '').trim();
if (b.startsWith(s) && arr.indexOf(trimmed) === -1)
arr.push(`${s}\\s(.*?)\\s${trimmed}\\b$`);
});
return arr;
}, []);
function descriptiveLinkText(ast, file) {
const textToNodes = {};
const aggregate = (node) => {
const text = node.children.reduce((str, arr) => {
if (arr.type == 'text') str += arr.value;
return str;
}, '');
if (!text) return;
if (!textToNodes[text]) {
textToNodes[text] = [];
}
textToNodes[text].push(node);
};
visit(ast, 'link', aggregate);
return Object.keys(textToNodes).map((txt) => {
const nodes = textToNodes[txt];
if (!nodes) return;
// test regex
starts.forEach((start) => {
if (txt.toLowerCase().startsWith(start)) {
bannedRegex.forEach((reg) => {
if (new RegExp(`${reg}`, 'i').test(txt)) {
for (const node of nodes) {
file.message(
`Replace "${txt}" with descriptive link text that details the destination.`,
node
);
}
}
});
}
});
// test banned words
if (banned.indexOf(txt.toLowerCase()) > -1) {
for (const node of nodes) {
file.message(
`Replace "${txt}" with descriptive link text that details the destination.`,
node
);
}
}
});
}
module.exports = rule('remark-lint:link-text', descriptiveLinkText);