source: trip-planner-front/node_modules/nanomatch/lib/parsers.js@ b738035

Last change on this file since b738035 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[6a3a178]1'use strict';
2
3var regexNot = require('regex-not');
4var toRegex = require('to-regex');
5
6/**
7 * Characters to use in negation regex (we want to "not" match
8 * characters that are matched by other parsers)
9 */
10
11var cached;
12var NOT_REGEX = '[\\[!*+?$^"\'.\\\\/]+';
13var not = createTextRegex(NOT_REGEX);
14
15/**
16 * Nanomatch parsers
17 */
18
19module.exports = function(nanomatch, options) {
20 var parser = nanomatch.parser;
21 var opts = parser.options;
22
23 parser.state = {
24 slashes: 0,
25 paths: []
26 };
27
28 parser.ast.state = parser.state;
29 parser
30
31 /**
32 * Beginning-of-string
33 */
34
35 .capture('prefix', function() {
36 if (this.parsed) return;
37 var m = this.match(/^\.[\\/]/);
38 if (!m) return;
39 this.state.strictOpen = !!this.options.strictOpen;
40 this.state.addPrefix = true;
41 })
42
43 /**
44 * Escape: "\\."
45 */
46
47 .capture('escape', function() {
48 if (this.isInside('bracket')) return;
49 var pos = this.position();
50 var m = this.match(/^(?:\\(.)|([$^]))/);
51 if (!m) return;
52
53 return pos({
54 type: 'escape',
55 val: m[2] || m[1]
56 });
57 })
58
59 /**
60 * Quoted strings
61 */
62
63 .capture('quoted', function() {
64 var pos = this.position();
65 var m = this.match(/^["']/);
66 if (!m) return;
67
68 var quote = m[0];
69 if (this.input.indexOf(quote) === -1) {
70 return pos({
71 type: 'escape',
72 val: quote
73 });
74 }
75
76 var tok = advanceTo(this.input, quote);
77 this.consume(tok.len);
78
79 return pos({
80 type: 'quoted',
81 val: tok.esc
82 });
83 })
84
85 /**
86 * Negations: "!"
87 */
88
89 .capture('not', function() {
90 var parsed = this.parsed;
91 var pos = this.position();
92 var m = this.match(this.notRegex || /^!+/);
93 if (!m) return;
94 var val = m[0];
95
96 var isNegated = (val.length % 2) === 1;
97 if (parsed === '' && !isNegated) {
98 val = '';
99 }
100
101 // if nothing has been parsed, we know `!` is at the start,
102 // so we need to wrap the result in a negation regex
103 if (parsed === '' && isNegated && this.options.nonegate !== true) {
104 this.bos.val = '(?!^(?:';
105 this.append = ')$).*';
106 val = '';
107 }
108 return pos({
109 type: 'not',
110 val: val
111 });
112 })
113
114 /**
115 * Dot: "."
116 */
117
118 .capture('dot', function() {
119 var parsed = this.parsed;
120 var pos = this.position();
121 var m = this.match(/^\.+/);
122 if (!m) return;
123
124 var val = m[0];
125 this.state.dot = val === '.' && (parsed === '' || parsed.slice(-1) === '/');
126
127 return pos({
128 type: 'dot',
129 dotfiles: this.state.dot,
130 val: val
131 });
132 })
133
134 /**
135 * Plus: "+"
136 */
137
138 .capture('plus', /^\+(?!\()/)
139
140 /**
141 * Question mark: "?"
142 */
143
144 .capture('qmark', function() {
145 var parsed = this.parsed;
146 var pos = this.position();
147 var m = this.match(/^\?+(?!\()/);
148 if (!m) return;
149
150 this.state.metachar = true;
151 this.state.qmark = true;
152
153 return pos({
154 type: 'qmark',
155 parsed: parsed,
156 val: m[0]
157 });
158 })
159
160 /**
161 * Globstar: "**"
162 */
163
164 .capture('globstar', function() {
165 var parsed = this.parsed;
166 var pos = this.position();
167 var m = this.match(/^\*{2}(?![*(])(?=[,)/]|$)/);
168 if (!m) return;
169
170 var type = opts.noglobstar !== true ? 'globstar' : 'star';
171 var node = pos({type: type, parsed: parsed});
172 this.state.metachar = true;
173
174 while (this.input.slice(0, 4) === '/**/') {
175 this.input = this.input.slice(3);
176 }
177
178 node.isInside = {
179 brace: this.isInside('brace'),
180 paren: this.isInside('paren')
181 };
182
183 if (type === 'globstar') {
184 this.state.globstar = true;
185 node.val = '**';
186
187 } else {
188 this.state.star = true;
189 node.val = '*';
190 }
191
192 return node;
193 })
194
195 /**
196 * Star: "*"
197 */
198
199 .capture('star', function() {
200 var pos = this.position();
201 var starRe = /^(?:\*(?![*(])|[*]{3,}(?!\()|[*]{2}(?![(/]|$)|\*(?=\*\())/;
202 var m = this.match(starRe);
203 if (!m) return;
204
205 this.state.metachar = true;
206 this.state.star = true;
207 return pos({
208 type: 'star',
209 val: m[0]
210 });
211 })
212
213 /**
214 * Slash: "/"
215 */
216
217 .capture('slash', function() {
218 var pos = this.position();
219 var m = this.match(/^\//);
220 if (!m) return;
221
222 this.state.slashes++;
223 return pos({
224 type: 'slash',
225 val: m[0]
226 });
227 })
228
229 /**
230 * Backslash: "\\"
231 */
232
233 .capture('backslash', function() {
234 var pos = this.position();
235 var m = this.match(/^\\(?![*+?(){}[\]'"])/);
236 if (!m) return;
237
238 var val = m[0];
239
240 if (this.isInside('bracket')) {
241 val = '\\';
242 } else if (val.length > 1) {
243 val = '\\\\';
244 }
245
246 return pos({
247 type: 'backslash',
248 val: val
249 });
250 })
251
252 /**
253 * Square: "[.]"
254 */
255
256 .capture('square', function() {
257 if (this.isInside('bracket')) return;
258 var pos = this.position();
259 var m = this.match(/^\[([^!^\\])\]/);
260 if (!m) return;
261
262 return pos({
263 type: 'square',
264 val: m[1]
265 });
266 })
267
268 /**
269 * Brackets: "[...]" (basic, this can be overridden by other parsers)
270 */
271
272 .capture('bracket', function() {
273 var pos = this.position();
274 var m = this.match(/^(?:\[([!^]?)([^\]]+|\]-)(\]|[^*+?]+)|\[)/);
275 if (!m) return;
276
277 var val = m[0];
278 var negated = m[1] ? '^' : '';
279 var inner = (m[2] || '').replace(/\\\\+/, '\\\\');
280 var close = m[3] || '';
281
282 if (m[2] && inner.length < m[2].length) {
283 val = val.replace(/\\\\+/, '\\\\');
284 }
285
286 var esc = this.input.slice(0, 2);
287 if (inner === '' && esc === '\\]') {
288 inner += esc;
289 this.consume(2);
290
291 var str = this.input;
292 var idx = -1;
293 var ch;
294
295 while ((ch = str[++idx])) {
296 this.consume(1);
297 if (ch === ']') {
298 close = ch;
299 break;
300 }
301 inner += ch;
302 }
303 }
304
305 return pos({
306 type: 'bracket',
307 val: val,
308 escaped: close !== ']',
309 negated: negated,
310 inner: inner,
311 close: close
312 });
313 })
314
315 /**
316 * Text
317 */
318
319 .capture('text', function() {
320 if (this.isInside('bracket')) return;
321 var pos = this.position();
322 var m = this.match(not);
323 if (!m || !m[0]) return;
324
325 return pos({
326 type: 'text',
327 val: m[0]
328 });
329 });
330
331 /**
332 * Allow custom parsers to be passed on options
333 */
334
335 if (options && typeof options.parsers === 'function') {
336 options.parsers(nanomatch.parser);
337 }
338};
339
340/**
341 * Advance to the next non-escaped character
342 */
343
344function advanceTo(input, endChar) {
345 var ch = input.charAt(0);
346 var tok = { len: 1, val: '', esc: '' };
347 var idx = 0;
348
349 function advance() {
350 if (ch !== '\\') {
351 tok.esc += '\\' + ch;
352 tok.val += ch;
353 }
354
355 ch = input.charAt(++idx);
356 tok.len++;
357
358 if (ch === '\\') {
359 advance();
360 advance();
361 }
362 }
363
364 while (ch && ch !== endChar) {
365 advance();
366 }
367 return tok;
368}
369
370/**
371 * Create text regex
372 */
373
374function createTextRegex(pattern) {
375 if (cached) return cached;
376 var opts = {contains: true, strictClose: false};
377 var not = regexNot.create(pattern, opts);
378 var re = toRegex('^(?:[*]\\((?=.)|' + not + ')', opts);
379 return (cached = re);
380}
381
382/**
383 * Expose negation string
384 */
385
386module.exports.not = NOT_REGEX;
Note: See TracBrowser for help on using the repository browser.