UNPKG

2.45 kBJavaScriptView Raw
1'use strict';
2
3/**
4 * Compares a string to a second value that, if it fits a certain convention,
5 * is converted to a regular expression before the comparison.
6 * If it doesn't fit the convention, then two strings are compared.
7 *
8 * Any strings starting and ending with `/` are interpreted
9 * as regular expressions.
10 *
11 * @param {string} input
12 * @param {string | RegExp | Array<string | RegExp>} comparison
13 *
14 * @returns {false | {match: string, pattern: (string | RegExp) }}
15 */
16module.exports = function matchesStringOrRegExp(input, comparison) {
17 if (!Array.isArray(input)) {
18 return testAgainstStringOrRegExpOrArray(input, comparison);
19 }
20
21 for (const inputItem of input) {
22 const testResult = testAgainstStringOrRegExpOrArray(inputItem, comparison);
23
24 if (testResult) {
25 return testResult;
26 }
27 }
28
29 return false;
30};
31
32/**
33 * @param {string} value
34 * @param {string | RegExp | Array<string | RegExp>} comparison
35 */
36function testAgainstStringOrRegExpOrArray(value, comparison) {
37 if (!Array.isArray(comparison)) {
38 return testAgainstStringOrRegExp(value, comparison);
39 }
40
41 for (const comparisonItem of comparison) {
42 const testResult = testAgainstStringOrRegExp(value, comparisonItem);
43
44 if (testResult) {
45 return testResult;
46 }
47 }
48
49 return false;
50}
51
52/**
53 * @param {string} value
54 * @param {string | RegExp} comparison
55 */
56function testAgainstStringOrRegExp(value, comparison) {
57 // If it's a RegExp, test directly
58 if (comparison instanceof RegExp) {
59 return comparison.test(value) ? { match: value, pattern: comparison } : false;
60 }
61
62 // Check if it's RegExp in a string
63 const firstComparisonChar = comparison[0];
64 const lastComparisonChar = comparison[comparison.length - 1];
65 const secondToLastComparisonChar = comparison[comparison.length - 2];
66
67 const comparisonIsRegex =
68 firstComparisonChar === '/' &&
69 (lastComparisonChar === '/' ||
70 (secondToLastComparisonChar === '/' && lastComparisonChar === 'i'));
71
72 const hasCaseInsensitiveFlag = comparisonIsRegex && lastComparisonChar === 'i';
73
74 // If so, create a new RegExp from it
75 if (comparisonIsRegex) {
76 const valueMatches = hasCaseInsensitiveFlag
77 ? new RegExp(comparison.slice(1, -2), 'i').test(value)
78 : new RegExp(comparison.slice(1, -1)).test(value);
79
80 return valueMatches ? { match: value, pattern: comparison } : false;
81 }
82
83 // Otherwise, it's a string. Do a strict comparison
84 return value === comparison ? { match: value, pattern: comparison } : false;
85}