the reminder not showing content on the card at dashboard view and the quizes are hardcoded must move to the db make api's for it
289 lines
6.3 KiB
JavaScript
289 lines
6.3 KiB
JavaScript
/*!
|
|
* to-regex-range <https://github.com/micromatch/to-regex-range>
|
|
*
|
|
* Copyright (c) 2015-present, Jon Schlinkert.
|
|
* Released under the MIT License.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const isNumber = require('is-number');
|
|
|
|
const toRegexRange = (min, max, options) => {
|
|
if (isNumber(min) === false) {
|
|
throw new TypeError('toRegexRange: expected the first argument to be a number');
|
|
}
|
|
|
|
if (max === void 0 || min === max) {
|
|
return String(min);
|
|
}
|
|
|
|
if (isNumber(max) === false) {
|
|
throw new TypeError('toRegexRange: expected the second argument to be a number.');
|
|
}
|
|
|
|
let opts = { relaxZeros: true, ...options };
|
|
if (typeof opts.strictZeros === 'boolean') {
|
|
opts.relaxZeros = opts.strictZeros === false;
|
|
}
|
|
|
|
let relax = String(opts.relaxZeros);
|
|
let shorthand = String(opts.shorthand);
|
|
let capture = String(opts.capture);
|
|
let wrap = String(opts.wrap);
|
|
let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap;
|
|
|
|
if (toRegexRange.cache.hasOwnProperty(cacheKey)) {
|
|
return toRegexRange.cache[cacheKey].result;
|
|
}
|
|
|
|
let a = Math.min(min, max);
|
|
let b = Math.max(min, max);
|
|
|
|
if (Math.abs(a - b) === 1) {
|
|
let result = min + '|' + max;
|
|
if (opts.capture) {
|
|
return `(${result})`;
|
|
}
|
|
if (opts.wrap === false) {
|
|
return result;
|
|
}
|
|
return `(?:${result})`;
|
|
}
|
|
|
|
let isPadded = hasPadding(min) || hasPadding(max);
|
|
let state = { min, max, a, b };
|
|
let positives = [];
|
|
let negatives = [];
|
|
|
|
if (isPadded) {
|
|
state.isPadded = isPadded;
|
|
state.maxLen = String(state.max).length;
|
|
}
|
|
|
|
if (a < 0) {
|
|
let newMin = b < 0 ? Math.abs(b) : 1;
|
|
negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
|
|
a = state.a = 0;
|
|
}
|
|
|
|
if (b >= 0) {
|
|
positives = splitToPatterns(a, b, state, opts);
|
|
}
|
|
|
|
state.negatives = negatives;
|
|
state.positives = positives;
|
|
state.result = collatePatterns(negatives, positives, opts);
|
|
|
|
if (opts.capture === true) {
|
|
state.result = `(${state.result})`;
|
|
} else if (opts.wrap !== false && (positives.length + negatives.length) > 1) {
|
|
state.result = `(?:${state.result})`;
|
|
}
|
|
|
|
toRegexRange.cache[cacheKey] = state;
|
|
return state.result;
|
|
};
|
|
|
|
function collatePatterns(neg, pos, options) {
|
|
let onlyNegative = filterPatterns(neg, pos, '-', false, options) || [];
|
|
let onlyPositive = filterPatterns(pos, neg, '', false, options) || [];
|
|
let intersected = filterPatterns(neg, pos, '-?', true, options) || [];
|
|
let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive);
|
|
return subpatterns.join('|');
|
|
}
|
|
|
|
function splitToRanges(min, max) {
|
|
let nines = 1;
|
|
let zeros = 1;
|
|
|
|
let stop = countNines(min, nines);
|
|
let stops = new Set([max]);
|
|
|
|
while (min <= stop && stop <= max) {
|
|
stops.add(stop);
|
|
nines += 1;
|
|
stop = countNines(min, nines);
|
|
}
|
|
|
|
stop = countZeros(max + 1, zeros) - 1;
|
|
|
|
while (min < stop && stop <= max) {
|
|
stops.add(stop);
|
|
zeros += 1;
|
|
stop = countZeros(max + 1, zeros) - 1;
|
|
}
|
|
|
|
stops = [...stops];
|
|
stops.sort(compare);
|
|
return stops;
|
|
}
|
|
|
|
/**
|
|
* Convert a range to a regex pattern
|
|
* @param {Number} `start`
|
|
* @param {Number} `stop`
|
|
* @return {String}
|
|
*/
|
|
|
|
function rangeToPattern(start, stop, options) {
|
|
if (start === stop) {
|
|
return { pattern: start, count: [], digits: 0 };
|
|
}
|
|
|
|
let zipped = zip(start, stop);
|
|
let digits = zipped.length;
|
|
let pattern = '';
|
|
let count = 0;
|
|
|
|
for (let i = 0; i < digits; i++) {
|
|
let [startDigit, stopDigit] = zipped[i];
|
|
|
|
if (startDigit === stopDigit) {
|
|
pattern += startDigit;
|
|
|
|
} else if (startDigit !== '0' || stopDigit !== '9') {
|
|
pattern += toCharacterClass(startDigit, stopDigit, options);
|
|
|
|
} else {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count) {
|
|
pattern += options.shorthand === true ? '\\d' : '[0-9]';
|
|
}
|
|
|
|
return { pattern, count: [count], digits };
|
|
}
|
|
|
|
function splitToPatterns(min, max, tok, options) {
|
|
let ranges = splitToRanges(min, max);
|
|
let tokens = [];
|
|
let start = min;
|
|
let prev;
|
|
|
|
for (let i = 0; i < ranges.length; i++) {
|
|
let max = ranges[i];
|
|
let obj = rangeToPattern(String(start), String(max), options);
|
|
let zeros = '';
|
|
|
|
if (!tok.isPadded && prev && prev.pattern === obj.pattern) {
|
|
if (prev.count.length > 1) {
|
|
prev.count.pop();
|
|
}
|
|
|
|
prev.count.push(obj.count[0]);
|
|
prev.string = prev.pattern + toQuantifier(prev.count);
|
|
start = max + 1;
|
|
continue;
|
|
}
|
|
|
|
if (tok.isPadded) {
|
|
zeros = padZeros(max, tok, options);
|
|
}
|
|
|
|
obj.string = zeros + obj.pattern + toQuantifier(obj.count);
|
|
tokens.push(obj);
|
|
start = max + 1;
|
|
prev = obj;
|
|
}
|
|
|
|
return tokens;
|
|
}
|
|
|
|
function filterPatterns(arr, comparison, prefix, intersection, options) {
|
|
let result = [];
|
|
|
|
for (let ele of arr) {
|
|
let { string } = ele;
|
|
|
|
// only push if _both_ are negative...
|
|
if (!intersection && !contains(comparison, 'string', string)) {
|
|
result.push(prefix + string);
|
|
}
|
|
|
|
// or _both_ are positive
|
|
if (intersection && contains(comparison, 'string', string)) {
|
|
result.push(prefix + string);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Zip strings
|
|
*/
|
|
|
|
function zip(a, b) {
|
|
let arr = [];
|
|
for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);
|
|
return arr;
|
|
}
|
|
|
|
function compare(a, b) {
|
|
return a > b ? 1 : b > a ? -1 : 0;
|
|
}
|
|
|
|
function contains(arr, key, val) {
|
|
return arr.some(ele => ele[key] === val);
|
|
}
|
|
|
|
function countNines(min, len) {
|
|
return Number(String(min).slice(0, -len) + '9'.repeat(len));
|
|
}
|
|
|
|
function countZeros(integer, zeros) {
|
|
return integer - (integer % Math.pow(10, zeros));
|
|
}
|
|
|
|
function toQuantifier(digits) {
|
|
let [start = 0, stop = ''] = digits;
|
|
if (stop || start > 1) {
|
|
return `{${start + (stop ? ',' + stop : '')}}`;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function toCharacterClass(a, b, options) {
|
|
return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;
|
|
}
|
|
|
|
function hasPadding(str) {
|
|
return /^-?(0+)\d/.test(str);
|
|
}
|
|
|
|
function padZeros(value, tok, options) {
|
|
if (!tok.isPadded) {
|
|
return value;
|
|
}
|
|
|
|
let diff = Math.abs(tok.maxLen - String(value).length);
|
|
let relax = options.relaxZeros !== false;
|
|
|
|
switch (diff) {
|
|
case 0:
|
|
return '';
|
|
case 1:
|
|
return relax ? '0?' : '0';
|
|
case 2:
|
|
return relax ? '0{0,2}' : '00';
|
|
default: {
|
|
return relax ? `0{0,${diff}}` : `0{${diff}}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cache
|
|
*/
|
|
|
|
toRegexRange.cache = {};
|
|
toRegexRange.clearCache = () => (toRegexRange.cache = {});
|
|
|
|
/**
|
|
* Expose `toRegexRange`
|
|
*/
|
|
|
|
module.exports = toRegexRange;
|