/* @flow */ /** * Compares a string to a second value that, if it fits a certain convention, * is converted to a regular expression before the comparison. * If it doesn't fit the convention, then two strings are compared. * * Any strings starting and ending with `/` are interpreted * as regular expressions. */ module.exports = function matchesStringOrRegExp( input /*: string | Array*/, comparison /*: string | Array*/ ) /*: false | { match: string, pattern: string}*/ { if (!Array.isArray(input)) { return testAgainstStringOrArray(input, comparison); } for (const inputItem of input) { const testResult = testAgainstStringOrArray(inputItem, comparison); if (testResult) { return testResult; } } return false; }; function testAgainstStringOrArray(value, comparison) { if (!Array.isArray(comparison)) { return testAgainstString(value, comparison); } for (const comparisonItem of comparison) { const testResult = testAgainstString(value, comparisonItem); if (testResult) { return testResult; } } return false; } function testAgainstString(value, comparison) { const firstComparisonChar = comparison[0]; const lastComparisonChar = comparison[comparison.length - 1]; const secondToLastComparisonChar = comparison[comparison.length - 2]; const comparisonIsRegex = firstComparisonChar === "/" && (lastComparisonChar === "/" || (secondToLastComparisonChar === "/" && lastComparisonChar === "i")); const hasCaseInsensitiveFlag = comparisonIsRegex && lastComparisonChar === "i"; if (comparisonIsRegex) { const valueMatches = hasCaseInsensitiveFlag ? new RegExp(comparison.slice(1, -2), "i").test(value) : new RegExp(comparison.slice(1, -1)).test(value); return valueMatches ? { match: value, pattern: comparison } : false; } return value === comparison ? { match: value, pattern: comparison } : false; }