Skip to content

Instantly share code, notes, and snippets.

@westc
Last active October 10, 2019 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westc/d26029d106b06f9fc441599f3300f3e3 to your computer and use it in GitHub Desktop.
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.
/**
* 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