-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathline-numbers.js
57 lines (46 loc) · 1.66 KB
/
line-numbers.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
import picomatch from 'picomatch';
const NUMBER_REGEX = /^\d+$/;
const RANGE_REGEX = /^(?<startGroup>\d+)-(?<endGroup>\d+)$/;
const LINE_NUMBERS_REGEX = /^(?:\d+(?:-\d+)?,?)+$/;
const DELIMITER = ':';
const distinctArray = array => [...new Set(array)];
const sortNumbersAscending = array => {
const sorted = [...array];
sorted.sort((a, b) => a - b);
return sorted;
};
const parseNumber = string => Number.parseInt(string, 10);
const removeAllWhitespace = string => string.replaceAll(/\s/g, '');
const range = (start, end) => Array.from({length: end - start + 1}).fill(start).map((element, index) => element + index);
const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(
suffix.split(',').flatMap(part => {
if (NUMBER_REGEX.test(part)) {
return parseNumber(part);
}
const {groups: {startGroup, endGroup}} = RANGE_REGEX.exec(part);
const start = parseNumber(startGroup);
const end = parseNumber(endGroup);
if (start > end) {
return range(end, start);
}
return range(start, end);
}),
));
export function splitPatternAndLineNumbers(pattern) {
const parts = pattern.split(DELIMITER);
if (parts.length === 1) {
return {pattern, lineNumbers: null};
}
const suffix = removeAllWhitespace(parts.pop());
if (!LINE_NUMBERS_REGEX.test(suffix)) {
return {pattern, lineNumbers: null};
}
return {pattern: parts.join(DELIMITER), lineNumbers: parseLineNumbers(suffix)};
}
export function getApplicableLineNumbers(normalizedFilePath, filter) {
return sortNumbersAscending(distinctArray(
filter
.filter(({pattern, lineNumbers}) => lineNumbers && picomatch.isMatch(normalizedFilePath, pattern))
.flatMap(({lineNumbers}) => lineNumbers),
));
}