-
-
Notifications
You must be signed in to change notification settings - Fork 757
/
Copy pathmd044.js
133 lines (129 loc) · 4.67 KB
/
md044.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// @ts-check
"use strict";
const { addErrorDetailIf, escapeForRegExp, newLineRe, withinAnyRange } =
require("../helpers");
const { filterByPredicate, filterByTypes, parse } =
require("../helpers/micromark.cjs");
const ignoredChildTypes = new Set(
[ "codeFencedFence", "definition", "reference", "resource" ]
);
module.exports = {
"names": [ "MD044", "proper-names" ],
"description": "Proper names should have the correct capitalization",
"tags": [ "spelling" ],
"function": function MD044(params, onError) {
let names = params.config.names;
names = Array.isArray(names) ? names : [];
names.sort((a, b) => (b.length - a.length) || a.localeCompare(b));
const codeBlocks = params.config.code_blocks;
const includeCodeBlocks =
(codeBlocks === undefined) ? true : !!codeBlocks;
const htmlElements = params.config.html_elements;
const includeHtmlElements =
(htmlElements === undefined) ? true : !!htmlElements;
const scannedTypes = new Set([ "data", "htmlFlowData" ]);
if (includeCodeBlocks) {
scannedTypes.add("codeFlowValue");
scannedTypes.add("codeTextData");
}
const tokenAdjustments = new Map();
const contentTokens =
filterByPredicate(
params.parsers.micromark.tokens,
(token) => scannedTypes.has(token.type),
(token) => {
let { children } = token;
const { startLine, text } = token;
if (!includeHtmlElements && (token.type === "htmlFlow")) {
if (text.startsWith("<!--")) {
// Remove comment content
children = [];
} else {
// Re-parse to get htmlText elements for detailed tokenization
const htmlTextLines =
`<md044>\n${text}\n</md044>`.split(newLineRe);
children = parse(htmlTextLines.join(""));
const reTokens = [ ...children ];
for (const reToken of reTokens) {
tokenAdjustments.set(reToken, {
htmlTextLines,
startLine
});
reTokens.push(...reToken.children);
}
}
}
return children.filter((t) => !ignoredChildTypes.has(t.type));
}
);
const exclusions = [];
const autoLinked = new Set();
for (const name of names) {
const escapedName = escapeForRegExp(name);
const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
const namePattern =
`(${startNamePattern})(${escapedName})${endNamePattern}`;
const nameRe = new RegExp(namePattern, "gi");
for (const token of contentTokens) {
let match = null;
while ((match = nameRe.exec(token.text)) !== null) {
const [ , leftMatch, nameMatch ] = match;
const index = token.startColumn - 1 + match.index + leftMatch.length;
const length = nameMatch.length;
const lineIndex = token.startLine - 1;
if (
!withinAnyRange(exclusions, lineIndex, index, length) &&
!names.includes(nameMatch)
) {
let urlRanges = [];
if (!autoLinked.has(token)) {
urlRanges = filterByTypes(
parse(token.text),
[ "literalAutolink" ]
).map(
(t) => [
lineIndex,
token.startColumn - 1 + t.startColumn - 1,
t.endColumn - t.startColumn
]
);
exclusions.push(...urlRanges);
autoLinked.add(token);
}
if (!withinAnyRange(urlRanges, lineIndex, index, length)) {
let lineNumber = token.startLine;
let column = index;
if (tokenAdjustments.has(token)) {
const { htmlTextLines, startLine } =
tokenAdjustments.get(token);
let lineDelta = 0;
while (htmlTextLines[lineDelta].length <= column) {
column -= htmlTextLines[lineDelta].length;
lineDelta++;
}
lineNumber = startLine + lineDelta - 1;
}
column++;
addErrorDetailIf(
onError,
lineNumber,
name,
nameMatch,
null,
null,
[ column, length ],
{
"editColumn": column,
"deleteCount": length,
"insertText": name
}
);
}
}
exclusions.push([ lineIndex, index, length ]);
}
}
}
}
};