-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
144 lines (111 loc) · 3.18 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
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
134
135
136
137
138
139
140
141
142
143
144
module.exports = function (matcher, input) {
validateMatcher(matcher);
validateInput(input);
if (matcher.pattern.length == 1) {
return singleMatch(matcher, input);
}
const loopPattern = matcher.pattern[matcher.pattern.length - 1];
if (loopPattern.loop) {
return loopMatch(matcher, input);
}
throw new Error(
"Unsupported pattern configuration. We currently support single pattern and multi-line loop pattern configurations"
);
};
function loopMatch(matcher, input) {
const lines = input.split("\n");
const matches = [];
// If we have context, try the loop line. If it matches, try it again
// If not, reset context jump back to the first pattern
while (lines.length) {
let context = {};
let line = lines.shift();
// Take a copy that we can manipulate
let patterns = matcher.pattern.slice(0);
while ((x = patterns.shift())) {
// Match the current line
const re = new RegExp(x.regexp);
let r = runRegExp(re, line, x, matcher);
// If it's not a loop entry, save the matches in the context
// and try processing the next pattern
if (!x.loop) {
context = { ...context, ...r };
continue;
}
while ((line = lines.shift()) !== undefined) {
if (line === "") {
continue;
}
let r = runRegExp(re, line, x, matcher);
// If the regexp didn't match, assume that the loop is over and start again
if (!r) {
lines.unshift(line);
break;
}
// Otherwise add a match and run this loop again
matches.push({ ...context, ...r });
}
}
}
return matches;
}
function singleMatch(matcher, input) {
// We only support single line matchers at the moment
const pattern = matcher.pattern[0];
const re = new RegExp(pattern.regexp);
const lines = [];
for (let line of input.split("\n")) {
let matches = runRegExp(re, line, pattern, matcher);
if (!matches) {
continue;
}
lines.push(matches);
}
return lines;
}
function validateMatcher(matcher) {
if (!matcher) {
throw new Error("No matcher provided");
}
if (!matcher.owner) {
throw new Error("No matcher.owner provided");
}
if (!matcher.pattern) {
throw new Error("No matcher.pattern provided");
}
if (!Array.isArray(matcher.pattern) || matcher.pattern.length < 1) {
throw new Error("matcher.pattern must be an array with at least one value");
}
}
function validateInput(input) {
if (!input) {
throw new Error("No input provided");
}
}
function runRegExp(re, line, pattern, matcher) {
const s = line.match(re);
if (!s) {
return null;
}
const matches = {};
for (let k in pattern) {
if (k == "regexp" || k == "loop") {
continue;
}
if (pattern[k] === 0) {
throw new Error(
`Group 0 is not a valid capture group (it contains the entire matched string)`
);
}
if (!s[pattern[k]]) {
throw new Error(
`Invalid capture group provided. Group ${pattern[k]} (${k}) does not exist in regexp`
);
}
matches[k] = s[pattern[k]].trim();
}
if (!matches.severity) {
matches.severity = matcher.severity;
}
return matches;
}