Last active
October 10, 2019 04:31
-
-
Save westc/d26029d106b06f9fc441599f3300f3e3 to your computer and use it in GitHub Desktop.
YourJS Candidate Function: Creates a search term checking function. Allows for quotes, a regexp, musts (+), must not [AKA negation] (-) and normal terms.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Creates a function that when called will try to match the given string | |
* against `strTerm`. | |
* @param strTerm {string} | |
* The string that will be parsed and used to test one or more strings. | |
* @param opt_options {?Object} | |
* Optional. An object containing all of the options to be used. The | |
* `ignoreCase` property (defaults to true) can be added specified to | |
* allow/disallow non-RegExp terms to match strings regardless of casing. | |
* The `matchWordStart` (defaults to false) can be added to allow plain words | |
* to match even if word only starts with the word entered in the term. The | |
* `ignoreErrors` (defaults to false) can be added to indicate whether | |
* malformed will throw JS errors. | |
*/ | |
function term(strTerm, opt_options) { | |
opt_options = Object(opt_options); | |
var terms = []; | |
var DEFAULT_MUSTS = []; | |
strTerm.replace( | |
/(?:(\+)|(-))?(?:\/((?:[^\\\/]+|\\.)+)\/(i?)|"((?:[^"]+|"")*)"|(\S+))/g, | |
function (match, hasPlus, hasMinus, rgxBody, rgxFlags, quoteBody, word) { | |
try { | |
var must = hasPlus === '+' ? true : hasMinus === '-' ? false : undefined; | |
terms.push({ | |
rgx: rgxBody | |
? new RegExp(rgxBody, (rgxFlags || '') + 'g') | |
: new RegExp( | |
(quoteBody || word).replace( | |
/(^\b)|(\s)|([\[\]\{\}\(\)\+\$\^\\\|\?])|("")|(\*)|(\b$)/g, | |
function (match, breakStart, space, specialChar, isQuote, isAsterisk, breakEnd) { | |
return space | |
? '\\s+' | |
: specialChar | |
? '\\' + specialChar | |
: isQuote | |
? '"' | |
: isAsterisk | |
? '.*' | |
: (breakStart === '' || (breakEnd === '' && (!opt_options.matchWordStart || quoteBody))) | |
? '\\b' | |
: match; | |
} | |
), | |
'g' + (opt_options.ignoreCase === false ? '' : 'i') | |
), | |
must: hasPlus === '+' ? true : hasMinus === '-' ? false : undefined | |
}); | |
DEFAULT_MUSTS.push(must !== true); | |
} | |
catch (e) { | |
if (opt_options.ignoreErrors) { | |
console.warn(e); | |
} | |
else { | |
throw e; | |
} | |
} | |
} | |
); | |
return function (str) { | |
var musts = DEFAULT_MUSTS.slice(); | |
var matchWraps = []; | |
terms.forEach(function (term, termIndex) { | |
var match; | |
while (match = term.rgx.exec(str)) { | |
if (match[0] === '') { | |
term.rgx.lastIndex++; | |
} | |
matchWraps.push({ match: match, term: term, termIndex: termIndex }); | |
} | |
}); | |
matchWraps = matchWraps.sort(function (a, b) { | |
return (a.match.index - b.match.index) || (a.termIndex - b.termIndex); | |
}).filter(function (matchWrap, matchWrapIndex) { | |
var keepIt = !matchWrapIndex; | |
if (!keepIt) { | |
var prevMatch = matchWraps[matchWrapIndex - 1].match; | |
var prevMatchEnd = prevMatch.index + prevMatch[0].length; | |
keepIt = matchWrap.match.index >= prevMatchEnd; | |
} | |
if (keepIt) { | |
musts[matchWrap.termIndex] = matchWrap.term.must; | |
} | |
return keepIt; | |
}); | |
return !musts.some(function (must) { return must === false; }) | |
&& !!matchWraps.length | |
&& matchWraps.map(function (matchWrap) { return matchWrap.match; }); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment