source: trip-planner-front/node_modules/regenerate/regenerate.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: 33.8 KB
RevLine 
[6a3a178]1/*! https://mths.be/regenerate v1.4.2 by @mathias | MIT license */
2;(function(root) {
3
4 // Detect free variables `exports`.
5 var freeExports = typeof exports == 'object' && exports;
6
7 // Detect free variable `module`.
8 var freeModule = typeof module == 'object' && module &&
9 module.exports == freeExports && module;
10
11 // Detect free variable `global`, from Node.js/io.js or Browserified code,
12 // and use it as `root`.
13 var freeGlobal = typeof global == 'object' && global;
14 if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
15 root = freeGlobal;
16 }
17
18 /*--------------------------------------------------------------------------*/
19
20 var ERRORS = {
21 'rangeOrder': 'A range\u2019s `stop` value must be greater than or equal ' +
22 'to the `start` value.',
23 'codePointRange': 'Invalid code point value. Code points range from ' +
24 'U+000000 to U+10FFFF.'
25 };
26
27 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-pairs
28 var HIGH_SURROGATE_MIN = 0xD800;
29 var HIGH_SURROGATE_MAX = 0xDBFF;
30 var LOW_SURROGATE_MIN = 0xDC00;
31 var LOW_SURROGATE_MAX = 0xDFFF;
32
33 // In Regenerate output, `\0` is never preceded by `\` because we sort by
34 // code point value, so let’s keep this regular expression simple.
35 var regexNull = /\\x00([^0123456789]|$)/g;
36
37 var object = {};
38 var hasOwnProperty = object.hasOwnProperty;
39 var extend = function(destination, source) {
40 var key;
41 for (key in source) {
42 if (hasOwnProperty.call(source, key)) {
43 destination[key] = source[key];
44 }
45 }
46 return destination;
47 };
48
49 var forEach = function(array, callback) {
50 var index = -1;
51 var length = array.length;
52 while (++index < length) {
53 callback(array[index], index);
54 }
55 };
56
57 var toString = object.toString;
58 var isArray = function(value) {
59 return toString.call(value) == '[object Array]';
60 };
61 var isNumber = function(value) {
62 return typeof value == 'number' ||
63 toString.call(value) == '[object Number]';
64 };
65
66 // This assumes that `number` is a positive integer that `toString()`s nicely
67 // (which is the case for all code point values).
68 var zeroes = '0000';
69 var pad = function(number, totalCharacters) {
70 var string = String(number);
71 return string.length < totalCharacters
72 ? (zeroes + string).slice(-totalCharacters)
73 : string;
74 };
75
76 var hex = function(number) {
77 return Number(number).toString(16).toUpperCase();
78 };
79
80 var slice = [].slice;
81
82 /*--------------------------------------------------------------------------*/
83
84 var dataFromCodePoints = function(codePoints) {
85 var index = -1;
86 var length = codePoints.length;
87 var max = length - 1;
88 var result = [];
89 var isStart = true;
90 var tmp;
91 var previous = 0;
92 while (++index < length) {
93 tmp = codePoints[index];
94 if (isStart) {
95 result.push(tmp);
96 previous = tmp;
97 isStart = false;
98 } else {
99 if (tmp == previous + 1) {
100 if (index != max) {
101 previous = tmp;
102 continue;
103 } else {
104 isStart = true;
105 result.push(tmp + 1);
106 }
107 } else {
108 // End the previous range and start a new one.
109 result.push(previous + 1, tmp);
110 previous = tmp;
111 }
112 }
113 }
114 if (!isStart) {
115 result.push(tmp + 1);
116 }
117 return result;
118 };
119
120 var dataRemove = function(data, codePoint) {
121 // Iterate over the data per `(start, end)` pair.
122 var index = 0;
123 var start;
124 var end;
125 var length = data.length;
126 while (index < length) {
127 start = data[index];
128 end = data[index + 1];
129 if (codePoint >= start && codePoint < end) {
130 // Modify this pair.
131 if (codePoint == start) {
132 if (end == start + 1) {
133 // Just remove `start` and `end`.
134 data.splice(index, 2);
135 return data;
136 } else {
137 // Just replace `start` with a new value.
138 data[index] = codePoint + 1;
139 return data;
140 }
141 } else if (codePoint == end - 1) {
142 // Just replace `end` with a new value.
143 data[index + 1] = codePoint;
144 return data;
145 } else {
146 // Replace `[start, end]` with `[startA, endA, startB, endB]`.
147 data.splice(index, 2, start, codePoint, codePoint + 1, end);
148 return data;
149 }
150 }
151 index += 2;
152 }
153 return data;
154 };
155
156 var dataRemoveRange = function(data, rangeStart, rangeEnd) {
157 if (rangeEnd < rangeStart) {
158 throw Error(ERRORS.rangeOrder);
159 }
160 // Iterate over the data per `(start, end)` pair.
161 var index = 0;
162 var start;
163 var end;
164 while (index < data.length) {
165 start = data[index];
166 end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
167
168 // Exit as soon as no more matching pairs can be found.
169 if (start > rangeEnd) {
170 return data;
171 }
172
173 // Check if this range pair is equal to, or forms a subset of, the range
174 // to be removed.
175 // E.g. we have `[0, 11, 40, 51]` and want to remove 0-10 → `[40, 51]`.
176 // E.g. we have `[40, 51]` and want to remove 0-100 → `[]`.
177 if (rangeStart <= start && rangeEnd >= end) {
178 // Remove this pair.
179 data.splice(index, 2);
180 continue;
181 }
182
183 // Check if both `rangeStart` and `rangeEnd` are within the bounds of
184 // this pair.
185 // E.g. we have `[0, 11]` and want to remove 4-6 → `[0, 4, 7, 11]`.
186 if (rangeStart >= start && rangeEnd < end) {
187 if (rangeStart == start) {
188 // Replace `[start, end]` with `[startB, endB]`.
189 data[index] = rangeEnd + 1;
190 data[index + 1] = end + 1;
191 return data;
192 }
193 // Replace `[start, end]` with `[startA, endA, startB, endB]`.
194 data.splice(index, 2, start, rangeStart, rangeEnd + 1, end + 1);
195 return data;
196 }
197
198 // Check if only `rangeStart` is within the bounds of this pair.
199 // E.g. we have `[0, 11]` and want to remove 4-20 → `[0, 4]`.
200 if (rangeStart >= start && rangeStart <= end) {
201 // Replace `end` with `rangeStart`.
202 data[index + 1] = rangeStart;
203 // Note: we cannot `return` just yet, in case any following pairs still
204 // contain matching code points.
205 // E.g. we have `[0, 11, 14, 31]` and want to remove 4-20
206 // → `[0, 4, 21, 31]`.
207 }
208
209 // Check if only `rangeEnd` is within the bounds of this pair.
210 // E.g. we have `[14, 31]` and want to remove 4-20 → `[21, 31]`.
211 else if (rangeEnd >= start && rangeEnd <= end) {
212 // Just replace `start`.
213 data[index] = rangeEnd + 1;
214 return data;
215 }
216
217 index += 2;
218 }
219 return data;
220 };
221
222 var dataAdd = function(data, codePoint) {
223 // Iterate over the data per `(start, end)` pair.
224 var index = 0;
225 var start;
226 var end;
227 var lastIndex = null;
228 var length = data.length;
229 if (codePoint < 0x0 || codePoint > 0x10FFFF) {
230 throw RangeError(ERRORS.codePointRange);
231 }
232 while (index < length) {
233 start = data[index];
234 end = data[index + 1];
235
236 // Check if the code point is already in the set.
237 if (codePoint >= start && codePoint < end) {
238 return data;
239 }
240
241 if (codePoint == start - 1) {
242 // Just replace `start` with a new value.
243 data[index] = codePoint;
244 return data;
245 }
246
247 // At this point, if `start` is `greater` than `codePoint`, insert a new
248 // `[start, end]` pair before the current pair, or after the current pair
249 // if there is a known `lastIndex`.
250 if (start > codePoint) {
251 data.splice(
252 lastIndex != null ? lastIndex + 2 : 0,
253 0,
254 codePoint,
255 codePoint + 1
256 );
257 return data;
258 }
259
260 if (codePoint == end) {
261 // Check if adding this code point causes two separate ranges to become
262 // a single range, e.g. `dataAdd([0, 4, 5, 10], 4)` → `[0, 10]`.
263 if (codePoint + 1 == data[index + 2]) {
264 data.splice(index, 4, start, data[index + 3]);
265 return data;
266 }
267 // Else, just replace `end` with a new value.
268 data[index + 1] = codePoint + 1;
269 return data;
270 }
271 lastIndex = index;
272 index += 2;
273 }
274 // The loop has finished; add the new pair to the end of the data set.
275 data.push(codePoint, codePoint + 1);
276 return data;
277 };
278
279 var dataAddData = function(dataA, dataB) {
280 // Iterate over the data per `(start, end)` pair.
281 var index = 0;
282 var start;
283 var end;
284 var data = dataA.slice();
285 var length = dataB.length;
286 while (index < length) {
287 start = dataB[index];
288 end = dataB[index + 1] - 1;
289 if (start == end) {
290 data = dataAdd(data, start);
291 } else {
292 data = dataAddRange(data, start, end);
293 }
294 index += 2;
295 }
296 return data;
297 };
298
299 var dataRemoveData = function(dataA, dataB) {
300 // Iterate over the data per `(start, end)` pair.
301 var index = 0;
302 var start;
303 var end;
304 var data = dataA.slice();
305 var length = dataB.length;
306 while (index < length) {
307 start = dataB[index];
308 end = dataB[index + 1] - 1;
309 if (start == end) {
310 data = dataRemove(data, start);
311 } else {
312 data = dataRemoveRange(data, start, end);
313 }
314 index += 2;
315 }
316 return data;
317 };
318
319 var dataAddRange = function(data, rangeStart, rangeEnd) {
320 if (rangeEnd < rangeStart) {
321 throw Error(ERRORS.rangeOrder);
322 }
323 if (
324 rangeStart < 0x0 || rangeStart > 0x10FFFF ||
325 rangeEnd < 0x0 || rangeEnd > 0x10FFFF
326 ) {
327 throw RangeError(ERRORS.codePointRange);
328 }
329 // Iterate over the data per `(start, end)` pair.
330 var index = 0;
331 var start;
332 var end;
333 var added = false;
334 var length = data.length;
335 while (index < length) {
336 start = data[index];
337 end = data[index + 1];
338
339 if (added) {
340 // The range has already been added to the set; at this point, we just
341 // need to get rid of the following ranges in case they overlap.
342
343 // Check if this range can be combined with the previous range.
344 if (start == rangeEnd + 1) {
345 data.splice(index - 1, 2);
346 return data;
347 }
348
349 // Exit as soon as no more possibly overlapping pairs can be found.
350 if (start > rangeEnd) {
351 return data;
352 }
353
354 // E.g. `[0, 11, 12, 16]` and we’ve added 5-15, so we now have
355 // `[0, 16, 12, 16]`. Remove the `12,16` part, as it lies within the
356 // `0,16` range that was previously added.
357 if (start >= rangeStart && start <= rangeEnd) {
358 // `start` lies within the range that was previously added.
359
360 if (end > rangeStart && end - 1 <= rangeEnd) {
361 // `end` lies within the range that was previously added as well,
362 // so remove this pair.
363 data.splice(index, 2);
364 index -= 2;
365 // Note: we cannot `return` just yet, as there may still be other
366 // overlapping pairs.
367 } else {
368 // `start` lies within the range that was previously added, but
369 // `end` doesn’t. E.g. `[0, 11, 12, 31]` and we’ve added 5-15, so
370 // now we have `[0, 16, 12, 31]`. This must be written as `[0, 31]`.
371 // Remove the previously added `end` and the current `start`.
372 data.splice(index - 1, 2);
373 index -= 2;
374 }
375
376 // Note: we cannot return yet.
377 }
378
379 }
380
381 else if (start == rangeEnd + 1 || start == rangeEnd) {
382 data[index] = rangeStart;
383 return data;
384 }
385
386 // Check if a new pair must be inserted *before* the current one.
387 else if (start > rangeEnd) {
388 data.splice(index, 0, rangeStart, rangeEnd + 1);
389 return data;
390 }
391
392 else if (rangeStart >= start && rangeStart < end && rangeEnd + 1 <= end) {
393 // The new range lies entirely within an existing range pair. No action
394 // needed.
395 return data;
396 }
397
398 else if (
399 // E.g. `[0, 11]` and you add 5-15 → `[0, 16]`.
400 (rangeStart >= start && rangeStart < end) ||
401 // E.g. `[0, 3]` and you add 3-6 → `[0, 7]`.
402 end == rangeStart
403 ) {
404 // Replace `end` with the new value.
405 data[index + 1] = rangeEnd + 1;
406 // Make sure the next range pair doesn’t overlap, e.g. `[0, 11, 12, 14]`
407 // and you add 5-15 → `[0, 16]`, i.e. remove the `12,14` part.
408 added = true;
409 // Note: we cannot `return` just yet.
410 }
411
412 else if (rangeStart <= start && rangeEnd + 1 >= end) {
413 // The new range is a superset of the old range.
414 data[index] = rangeStart;
415 data[index + 1] = rangeEnd + 1;
416 added = true;
417 }
418
419 index += 2;
420 }
421 // The loop has finished without doing anything; add the new pair to the end
422 // of the data set.
423 if (!added) {
424 data.push(rangeStart, rangeEnd + 1);
425 }
426 return data;
427 };
428
429 var dataContains = function(data, codePoint) {
430 var index = 0;
431 var length = data.length;
432 // Exit early if `codePoint` is not within `data`’s overall range.
433 var start = data[index];
434 var end = data[length - 1];
435 if (length >= 2) {
436 if (codePoint < start || codePoint > end) {
437 return false;
438 }
439 }
440 // Iterate over the data per `(start, end)` pair.
441 while (index < length) {
442 start = data[index];
443 end = data[index + 1];
444 if (codePoint >= start && codePoint < end) {
445 return true;
446 }
447 index += 2;
448 }
449 return false;
450 };
451
452 var dataIntersection = function(data, codePoints) {
453 var index = 0;
454 var length = codePoints.length;
455 var codePoint;
456 var result = [];
457 while (index < length) {
458 codePoint = codePoints[index];
459 if (dataContains(data, codePoint)) {
460 result.push(codePoint);
461 }
462 ++index;
463 }
464 return dataFromCodePoints(result);
465 };
466
467 var dataIsEmpty = function(data) {
468 return !data.length;
469 };
470
471 var dataIsSingleton = function(data) {
472 // Check if the set only represents a single code point.
473 return data.length == 2 && data[0] + 1 == data[1];
474 };
475
476 var dataToArray = function(data) {
477 // Iterate over the data per `(start, end)` pair.
478 var index = 0;
479 var start;
480 var end;
481 var result = [];
482 var length = data.length;
483 while (index < length) {
484 start = data[index];
485 end = data[index + 1];
486 while (start < end) {
487 result.push(start);
488 ++start;
489 }
490 index += 2;
491 }
492 return result;
493 };
494
495 /*--------------------------------------------------------------------------*/
496
497 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
498 var floor = Math.floor;
499 var highSurrogate = function(codePoint) {
500 return parseInt(
501 floor((codePoint - 0x10000) / 0x400) + HIGH_SURROGATE_MIN,
502 10
503 );
504 };
505
506 var lowSurrogate = function(codePoint) {
507 return parseInt(
508 (codePoint - 0x10000) % 0x400 + LOW_SURROGATE_MIN,
509 10
510 );
511 };
512
513 var stringFromCharCode = String.fromCharCode;
514 var codePointToString = function(codePoint) {
515 var string;
516 // https://mathiasbynens.be/notes/javascript-escapes#single
517 // Note: the `\b` escape sequence for U+0008 BACKSPACE in strings has a
518 // different meaning in regular expressions (word boundary), so it cannot
519 // be used here.
520 if (codePoint == 0x09) {
521 string = '\\t';
522 }
523 // Note: IE < 9 treats `'\v'` as `'v'`, so avoid using it.
524 // else if (codePoint == 0x0B) {
525 // string = '\\v';
526 // }
527 else if (codePoint == 0x0A) {
528 string = '\\n';
529 }
530 else if (codePoint == 0x0C) {
531 string = '\\f';
532 }
533 else if (codePoint == 0x0D) {
534 string = '\\r';
535 }
536 else if (codePoint == 0x2D) {
537 // https://mathiasbynens.be/notes/javascript-escapes#hexadecimal
538 // Note: `-` (U+002D HYPHEN-MINUS) is escaped in this way rather
539 // than by backslash-escaping, in case the output is used outside
540 // of a character class in a `u` RegExp. /\-/u throws, but
541 // /\x2D/u is fine.
542 string = '\\x2D';
543 }
544 else if (codePoint == 0x5C) {
545 string = '\\\\';
546 }
547 else if (
548 codePoint == 0x24 ||
549 (codePoint >= 0x28 && codePoint <= 0x2B) ||
550 codePoint == 0x2E || codePoint == 0x2F ||
551 codePoint == 0x3F ||
552 (codePoint >= 0x5B && codePoint <= 0x5E) ||
553 (codePoint >= 0x7B && codePoint <= 0x7D)
554 ) {
555 // The code point maps to an unsafe printable ASCII character;
556 // backslash-escape it. Here’s the list of those symbols:
557 //
558 // $()*+./?[\]^{|}
559 //
560 // This matches SyntaxCharacters as well as `/` (U+002F SOLIDUS).
561 // https://tc39.github.io/ecma262/#prod-SyntaxCharacter
562 string = '\\' + stringFromCharCode(codePoint);
563 }
564 else if (codePoint >= 0x20 && codePoint <= 0x7E) {
565 // The code point maps to one of these printable ASCII symbols
566 // (including the space character):
567 //
568 // !"#%&',/0123456789:;<=>@ABCDEFGHIJKLMNO
569 // PQRSTUVWXYZ_`abcdefghijklmnopqrstuvwxyz~
570 //
571 // These can safely be used directly.
572 string = stringFromCharCode(codePoint);
573 }
574 else if (codePoint <= 0xFF) {
575 string = '\\x' + pad(hex(codePoint), 2);
576 }
577 else { // `codePoint <= 0xFFFF` holds true.
578 // https://mathiasbynens.be/notes/javascript-escapes#unicode
579 string = '\\u' + pad(hex(codePoint), 4);
580 }
581
582 // There’s no need to account for astral symbols / surrogate pairs here,
583 // since `codePointToString` is private and only used for BMP code points.
584 // But if that’s what you need, just add an `else` block with this code:
585 //
586 // string = '\\u' + pad(hex(highSurrogate(codePoint)), 4)
587 // + '\\u' + pad(hex(lowSurrogate(codePoint)), 4);
588
589 return string;
590 };
591
592 var codePointToStringUnicode = function(codePoint) {
593 if (codePoint <= 0xFFFF) {
594 return codePointToString(codePoint);
595 }
596 return '\\u{' + codePoint.toString(16).toUpperCase() + '}';
597 };
598
599 var symbolToCodePoint = function(symbol) {
600 var length = symbol.length;
601 var first = symbol.charCodeAt(0);
602 var second;
603 if (
604 first >= HIGH_SURROGATE_MIN && first <= HIGH_SURROGATE_MAX &&
605 length > 1 // There is a next code unit.
606 ) {
607 // `first` is a high surrogate, and there is a next character. Assume
608 // it’s a low surrogate (else it’s invalid usage of Regenerate anyway).
609 second = symbol.charCodeAt(1);
610 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
611 return (first - HIGH_SURROGATE_MIN) * 0x400 +
612 second - LOW_SURROGATE_MIN + 0x10000;
613 }
614 return first;
615 };
616
617 var createBMPCharacterClasses = function(data) {
618 // Iterate over the data per `(start, end)` pair.
619 var result = '';
620 var index = 0;
621 var start;
622 var end;
623 var length = data.length;
624 if (dataIsSingleton(data)) {
625 return codePointToString(data[0]);
626 }
627 while (index < length) {
628 start = data[index];
629 end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
630 if (start == end) {
631 result += codePointToString(start);
632 } else if (start + 1 == end) {
633 result += codePointToString(start) + codePointToString(end);
634 } else {
635 result += codePointToString(start) + '-' + codePointToString(end);
636 }
637 index += 2;
638 }
639 return '[' + result + ']';
640 };
641
642 var createUnicodeCharacterClasses = function(data) {
643 // Iterate over the data per `(start, end)` pair.
644 var result = '';
645 var index = 0;
646 var start;
647 var end;
648 var length = data.length;
649 if (dataIsSingleton(data)) {
650 return codePointToStringUnicode(data[0]);
651 }
652 while (index < length) {
653 start = data[index];
654 end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
655 if (start == end) {
656 result += codePointToStringUnicode(start);
657 } else if (start + 1 == end) {
658 result += codePointToStringUnicode(start) + codePointToStringUnicode(end);
659 } else {
660 result += codePointToStringUnicode(start) + '-' + codePointToStringUnicode(end);
661 }
662 index += 2;
663 }
664 return '[' + result + ']';
665 };
666
667 var splitAtBMP = function(data) {
668 // Iterate over the data per `(start, end)` pair.
669 var loneHighSurrogates = [];
670 var loneLowSurrogates = [];
671 var bmp = [];
672 var astral = [];
673 var index = 0;
674 var start;
675 var end;
676 var length = data.length;
677 while (index < length) {
678 start = data[index];
679 end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
680
681 if (start < HIGH_SURROGATE_MIN) {
682
683 // The range starts and ends before the high surrogate range.
684 // E.g. (0, 0x10).
685 if (end < HIGH_SURROGATE_MIN) {
686 bmp.push(start, end + 1);
687 }
688
689 // The range starts before the high surrogate range and ends within it.
690 // E.g. (0, 0xD855).
691 if (end >= HIGH_SURROGATE_MIN && end <= HIGH_SURROGATE_MAX) {
692 bmp.push(start, HIGH_SURROGATE_MIN);
693 loneHighSurrogates.push(HIGH_SURROGATE_MIN, end + 1);
694 }
695
696 // The range starts before the high surrogate range and ends in the low
697 // surrogate range. E.g. (0, 0xDCFF).
698 if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
699 bmp.push(start, HIGH_SURROGATE_MIN);
700 loneHighSurrogates.push(HIGH_SURROGATE_MIN, HIGH_SURROGATE_MAX + 1);
701 loneLowSurrogates.push(LOW_SURROGATE_MIN, end + 1);
702 }
703
704 // The range starts before the high surrogate range and ends after the
705 // low surrogate range. E.g. (0, 0x10FFFF).
706 if (end > LOW_SURROGATE_MAX) {
707 bmp.push(start, HIGH_SURROGATE_MIN);
708 loneHighSurrogates.push(HIGH_SURROGATE_MIN, HIGH_SURROGATE_MAX + 1);
709 loneLowSurrogates.push(LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1);
710 if (end <= 0xFFFF) {
711 bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
712 } else {
713 bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
714 astral.push(0xFFFF + 1, end + 1);
715 }
716 }
717
718 } else if (start >= HIGH_SURROGATE_MIN && start <= HIGH_SURROGATE_MAX) {
719
720 // The range starts and ends in the high surrogate range.
721 // E.g. (0xD855, 0xD866).
722 if (end >= HIGH_SURROGATE_MIN && end <= HIGH_SURROGATE_MAX) {
723 loneHighSurrogates.push(start, end + 1);
724 }
725
726 // The range starts in the high surrogate range and ends in the low
727 // surrogate range. E.g. (0xD855, 0xDCFF).
728 if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
729 loneHighSurrogates.push(start, HIGH_SURROGATE_MAX + 1);
730 loneLowSurrogates.push(LOW_SURROGATE_MIN, end + 1);
731 }
732
733 // The range starts in the high surrogate range and ends after the low
734 // surrogate range. E.g. (0xD855, 0x10FFFF).
735 if (end > LOW_SURROGATE_MAX) {
736 loneHighSurrogates.push(start, HIGH_SURROGATE_MAX + 1);
737 loneLowSurrogates.push(LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1);
738 if (end <= 0xFFFF) {
739 bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
740 } else {
741 bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
742 astral.push(0xFFFF + 1, end + 1);
743 }
744 }
745
746 } else if (start >= LOW_SURROGATE_MIN && start <= LOW_SURROGATE_MAX) {
747
748 // The range starts and ends in the low surrogate range.
749 // E.g. (0xDCFF, 0xDDFF).
750 if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
751 loneLowSurrogates.push(start, end + 1);
752 }
753
754 // The range starts in the low surrogate range and ends after the low
755 // surrogate range. E.g. (0xDCFF, 0x10FFFF).
756 if (end > LOW_SURROGATE_MAX) {
757 loneLowSurrogates.push(start, LOW_SURROGATE_MAX + 1);
758 if (end <= 0xFFFF) {
759 bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
760 } else {
761 bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
762 astral.push(0xFFFF + 1, end + 1);
763 }
764 }
765
766 } else if (start > LOW_SURROGATE_MAX && start <= 0xFFFF) {
767
768 // The range starts and ends after the low surrogate range.
769 // E.g. (0xFFAA, 0x10FFFF).
770 if (end <= 0xFFFF) {
771 bmp.push(start, end + 1);
772 } else {
773 bmp.push(start, 0xFFFF + 1);
774 astral.push(0xFFFF + 1, end + 1);
775 }
776
777 } else {
778
779 // The range starts and ends in the astral range.
780 astral.push(start, end + 1);
781
782 }
783
784 index += 2;
785 }
786 return {
787 'loneHighSurrogates': loneHighSurrogates,
788 'loneLowSurrogates': loneLowSurrogates,
789 'bmp': bmp,
790 'astral': astral
791 };
792 };
793
794 var optimizeSurrogateMappings = function(surrogateMappings) {
795 var result = [];
796 var tmpLow = [];
797 var addLow = false;
798 var mapping;
799 var nextMapping;
800 var highSurrogates;
801 var lowSurrogates;
802 var nextHighSurrogates;
803 var nextLowSurrogates;
804 var index = -1;
805 var length = surrogateMappings.length;
806 while (++index < length) {
807 mapping = surrogateMappings[index];
808 nextMapping = surrogateMappings[index + 1];
809 if (!nextMapping) {
810 result.push(mapping);
811 continue;
812 }
813 highSurrogates = mapping[0];
814 lowSurrogates = mapping[1];
815 nextHighSurrogates = nextMapping[0];
816 nextLowSurrogates = nextMapping[1];
817
818 // Check for identical high surrogate ranges.
819 tmpLow = lowSurrogates;
820 while (
821 nextHighSurrogates &&
822 highSurrogates[0] == nextHighSurrogates[0] &&
823 highSurrogates[1] == nextHighSurrogates[1]
824 ) {
825 // Merge with the next item.
826 if (dataIsSingleton(nextLowSurrogates)) {
827 tmpLow = dataAdd(tmpLow, nextLowSurrogates[0]);
828 } else {
829 tmpLow = dataAddRange(
830 tmpLow,
831 nextLowSurrogates[0],
832 nextLowSurrogates[1] - 1
833 );
834 }
835 ++index;
836 mapping = surrogateMappings[index];
837 highSurrogates = mapping[0];
838 lowSurrogates = mapping[1];
839 nextMapping = surrogateMappings[index + 1];
840 nextHighSurrogates = nextMapping && nextMapping[0];
841 nextLowSurrogates = nextMapping && nextMapping[1];
842 addLow = true;
843 }
844 result.push([
845 highSurrogates,
846 addLow ? tmpLow : lowSurrogates
847 ]);
848 addLow = false;
849 }
850 return optimizeByLowSurrogates(result);
851 };
852
853 var optimizeByLowSurrogates = function(surrogateMappings) {
854 if (surrogateMappings.length == 1) {
855 return surrogateMappings;
856 }
857 var index = -1;
858 var innerIndex = -1;
859 while (++index < surrogateMappings.length) {
860 var mapping = surrogateMappings[index];
861 var lowSurrogates = mapping[1];
862 var lowSurrogateStart = lowSurrogates[0];
863 var lowSurrogateEnd = lowSurrogates[1];
864 innerIndex = index; // Note: the loop starts at the next index.
865 while (++innerIndex < surrogateMappings.length) {
866 var otherMapping = surrogateMappings[innerIndex];
867 var otherLowSurrogates = otherMapping[1];
868 var otherLowSurrogateStart = otherLowSurrogates[0];
869 var otherLowSurrogateEnd = otherLowSurrogates[1];
870 if (
871 lowSurrogateStart == otherLowSurrogateStart &&
872 lowSurrogateEnd == otherLowSurrogateEnd &&
873 otherLowSurrogates.length === 2
874 ) {
875 // Add the code points in the other item to this one.
876 if (dataIsSingleton(otherMapping[0])) {
877 mapping[0] = dataAdd(mapping[0], otherMapping[0][0]);
878 } else {
879 mapping[0] = dataAddRange(
880 mapping[0],
881 otherMapping[0][0],
882 otherMapping[0][1] - 1
883 );
884 }
885 // Remove the other, now redundant, item.
886 surrogateMappings.splice(innerIndex, 1);
887 --innerIndex;
888 }
889 }
890 }
891 return surrogateMappings;
892 };
893
894 var surrogateSet = function(data) {
895 // Exit early if `data` is an empty set.
896 if (!data.length) {
897 return [];
898 }
899
900 // Iterate over the data per `(start, end)` pair.
901 var index = 0;
902 var start;
903 var end;
904 var startHigh;
905 var startLow;
906 var endHigh;
907 var endLow;
908 var surrogateMappings = [];
909 var length = data.length;
910 while (index < length) {
911 start = data[index];
912 end = data[index + 1] - 1;
913
914 startHigh = highSurrogate(start);
915 startLow = lowSurrogate(start);
916 endHigh = highSurrogate(end);
917 endLow = lowSurrogate(end);
918
919 var startsWithLowestLowSurrogate = startLow == LOW_SURROGATE_MIN;
920 var endsWithHighestLowSurrogate = endLow == LOW_SURROGATE_MAX;
921 var complete = false;
922
923 // Append the previous high-surrogate-to-low-surrogate mappings.
924 // Step 1: `(startHigh, startLow)` to `(startHigh, LOW_SURROGATE_MAX)`.
925 if (
926 startHigh == endHigh ||
927 startsWithLowestLowSurrogate && endsWithHighestLowSurrogate
928 ) {
929 surrogateMappings.push([
930 [startHigh, endHigh + 1],
931 [startLow, endLow + 1]
932 ]);
933 complete = true;
934 } else {
935 surrogateMappings.push([
936 [startHigh, startHigh + 1],
937 [startLow, LOW_SURROGATE_MAX + 1]
938 ]);
939 }
940
941 // Step 2: `(startHigh + 1, LOW_SURROGATE_MIN)` to
942 // `(endHigh - 1, LOW_SURROGATE_MAX)`.
943 if (!complete && startHigh + 1 < endHigh) {
944 if (endsWithHighestLowSurrogate) {
945 // Combine step 2 and step 3.
946 surrogateMappings.push([
947 [startHigh + 1, endHigh + 1],
948 [LOW_SURROGATE_MIN, endLow + 1]
949 ]);
950 complete = true;
951 } else {
952 surrogateMappings.push([
953 [startHigh + 1, endHigh],
954 [LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1]
955 ]);
956 }
957 }
958
959 // Step 3. `(endHigh, LOW_SURROGATE_MIN)` to `(endHigh, endLow)`.
960 if (!complete) {
961 surrogateMappings.push([
962 [endHigh, endHigh + 1],
963 [LOW_SURROGATE_MIN, endLow + 1]
964 ]);
965 }
966
967 index += 2;
968 }
969
970 // The format of `surrogateMappings` is as follows:
971 //
972 // [ surrogateMapping1, surrogateMapping2 ]
973 //
974 // i.e.:
975 //
976 // [
977 // [ highSurrogates1, lowSurrogates1 ],
978 // [ highSurrogates2, lowSurrogates2 ]
979 // ]
980 return optimizeSurrogateMappings(surrogateMappings);
981 };
982
983 var createSurrogateCharacterClasses = function(surrogateMappings) {
984 var result = [];
985 forEach(surrogateMappings, function(surrogateMapping) {
986 var highSurrogates = surrogateMapping[0];
987 var lowSurrogates = surrogateMapping[1];
988 result.push(
989 createBMPCharacterClasses(highSurrogates) +
990 createBMPCharacterClasses(lowSurrogates)
991 );
992 });
993 return result.join('|');
994 };
995
996 var createCharacterClassesFromData = function(data, bmpOnly, hasUnicodeFlag) {
997 if (hasUnicodeFlag) {
998 return createUnicodeCharacterClasses(data);
999 }
1000 var result = [];
1001
1002 var parts = splitAtBMP(data);
1003 var loneHighSurrogates = parts.loneHighSurrogates;
1004 var loneLowSurrogates = parts.loneLowSurrogates;
1005 var bmp = parts.bmp;
1006 var astral = parts.astral;
1007 var hasLoneHighSurrogates = !dataIsEmpty(loneHighSurrogates);
1008 var hasLoneLowSurrogates = !dataIsEmpty(loneLowSurrogates);
1009
1010 var surrogateMappings = surrogateSet(astral);
1011
1012 if (bmpOnly) {
1013 bmp = dataAddData(bmp, loneHighSurrogates);
1014 hasLoneHighSurrogates = false;
1015 bmp = dataAddData(bmp, loneLowSurrogates);
1016 hasLoneLowSurrogates = false;
1017 }
1018
1019 if (!dataIsEmpty(bmp)) {
1020 // The data set contains BMP code points that are not high surrogates
1021 // needed for astral code points in the set.
1022 result.push(createBMPCharacterClasses(bmp));
1023 }
1024 if (surrogateMappings.length) {
1025 // The data set contains astral code points; append character classes
1026 // based on their surrogate pairs.
1027 result.push(createSurrogateCharacterClasses(surrogateMappings));
1028 }
1029 // https://gist.github.com/mathiasbynens/bbe7f870208abcfec860
1030 if (hasLoneHighSurrogates) {
1031 result.push(
1032 createBMPCharacterClasses(loneHighSurrogates) +
1033 // Make sure the high surrogates aren’t part of a surrogate pair.
1034 '(?![\\uDC00-\\uDFFF])'
1035 );
1036 }
1037 if (hasLoneLowSurrogates) {
1038 result.push(
1039 // It is not possible to accurately assert the low surrogates aren’t
1040 // part of a surrogate pair, since JavaScript regular expressions do
1041 // not support lookbehind.
1042 '(?:[^\\uD800-\\uDBFF]|^)' +
1043 createBMPCharacterClasses(loneLowSurrogates)
1044 );
1045 }
1046 return result.join('|');
1047 };
1048
1049 /*--------------------------------------------------------------------------*/
1050
1051 // `regenerate` can be used as a constructor (and new methods can be added to
1052 // its prototype) but also as a regular function, the latter of which is the
1053 // documented and most common usage. For that reason, it’s not capitalized.
1054 var regenerate = function(value) {
1055 if (arguments.length > 1) {
1056 value = slice.call(arguments);
1057 }
1058 if (this instanceof regenerate) {
1059 this.data = [];
1060 return value ? this.add(value) : this;
1061 }
1062 return (new regenerate).add(value);
1063 };
1064
1065 regenerate.version = '1.4.2';
1066
1067 var proto = regenerate.prototype;
1068 extend(proto, {
1069 'add': function(value) {
1070 var $this = this;
1071 if (value == null) {
1072 return $this;
1073 }
1074 if (value instanceof regenerate) {
1075 // Allow passing other Regenerate instances.
1076 $this.data = dataAddData($this.data, value.data);
1077 return $this;
1078 }
1079 if (arguments.length > 1) {
1080 value = slice.call(arguments);
1081 }
1082 if (isArray(value)) {
1083 forEach(value, function(item) {
1084 $this.add(item);
1085 });
1086 return $this;
1087 }
1088 $this.data = dataAdd(
1089 $this.data,
1090 isNumber(value) ? value : symbolToCodePoint(value)
1091 );
1092 return $this;
1093 },
1094 'remove': function(value) {
1095 var $this = this;
1096 if (value == null) {
1097 return $this;
1098 }
1099 if (value instanceof regenerate) {
1100 // Allow passing other Regenerate instances.
1101 $this.data = dataRemoveData($this.data, value.data);
1102 return $this;
1103 }
1104 if (arguments.length > 1) {
1105 value = slice.call(arguments);
1106 }
1107 if (isArray(value)) {
1108 forEach(value, function(item) {
1109 $this.remove(item);
1110 });
1111 return $this;
1112 }
1113 $this.data = dataRemove(
1114 $this.data,
1115 isNumber(value) ? value : symbolToCodePoint(value)
1116 );
1117 return $this;
1118 },
1119 'addRange': function(start, end) {
1120 var $this = this;
1121 $this.data = dataAddRange($this.data,
1122 isNumber(start) ? start : symbolToCodePoint(start),
1123 isNumber(end) ? end : symbolToCodePoint(end)
1124 );
1125 return $this;
1126 },
1127 'removeRange': function(start, end) {
1128 var $this = this;
1129 var startCodePoint = isNumber(start) ? start : symbolToCodePoint(start);
1130 var endCodePoint = isNumber(end) ? end : symbolToCodePoint(end);
1131 $this.data = dataRemoveRange(
1132 $this.data,
1133 startCodePoint,
1134 endCodePoint
1135 );
1136 return $this;
1137 },
1138 'intersection': function(argument) {
1139 var $this = this;
1140 // Allow passing other Regenerate instances.
1141 // TODO: Optimize this by writing and using `dataIntersectionData()`.
1142 var array = argument instanceof regenerate ?
1143 dataToArray(argument.data) :
1144 argument;
1145 $this.data = dataIntersection($this.data, array);
1146 return $this;
1147 },
1148 'contains': function(codePoint) {
1149 return dataContains(
1150 this.data,
1151 isNumber(codePoint) ? codePoint : symbolToCodePoint(codePoint)
1152 );
1153 },
1154 'clone': function() {
1155 var set = new regenerate;
1156 set.data = this.data.slice(0);
1157 return set;
1158 },
1159 'toString': function(options) {
1160 var result = createCharacterClassesFromData(
1161 this.data,
1162 options ? options.bmpOnly : false,
1163 options ? options.hasUnicodeFlag : false
1164 );
1165 if (!result) {
1166 // For an empty set, return something that can be inserted `/here/` to
1167 // form a valid regular expression. Avoid `(?:)` since that matches the
1168 // empty string.
1169 return '[]';
1170 }
1171 // Use `\0` instead of `\x00` where possible.
1172 return result.replace(regexNull, '\\0$1');
1173 },
1174 'toRegExp': function(flags) {
1175 var pattern = this.toString(
1176 flags && flags.indexOf('u') != -1 ?
1177 { 'hasUnicodeFlag': true } :
1178 null
1179 );
1180 return RegExp(pattern, flags || '');
1181 },
1182 'valueOf': function() { // Note: `valueOf` is aliased as `toArray`.
1183 return dataToArray(this.data);
1184 }
1185 });
1186
1187 proto.toArray = proto.valueOf;
1188
1189 // Some AMD build optimizers, like r.js, check for specific condition patterns
1190 // like the following:
1191 if (
1192 typeof define == 'function' &&
1193 typeof define.amd == 'object' &&
1194 define.amd
1195 ) {
1196 define(function() {
1197 return regenerate;
1198 });
1199 } else if (freeExports && !freeExports.nodeType) {
1200 if (freeModule) { // in Node.js, io.js, or RingoJS v0.8.0+
1201 freeModule.exports = regenerate;
1202 } else { // in Narwhal or RingoJS v0.7.0-
1203 freeExports.regenerate = regenerate;
1204 }
1205 } else { // in Rhino or a web browser
1206 root.regenerate = regenerate;
1207 }
1208
1209}(this));
Note: See TracBrowser for help on using the repository browser.