Skip to content

Instantly share code, notes, and snippets.

@westc
Created October 4, 2019 04:22
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/24600413a1ff3e8fb6f252d73f6da9c8 to your computer and use it in GitHub Desktop.
Save westc/24600413a1ff3e8fb6f252d73f6da9c8 to your computer and use it in GitHub Desktop.
Allow for fuzzy path matching.
// people[*]["firstName" | "lastName" | "fullName"]
// people[*][firstName | lastName | fullName]
// people[*][/^(first|last|full)Name$/]
// people.*[/^(first|last|full)Name$/]
// people.*./^(first|last|full)Name$/
// people[#0..9..2#]
// var RGX_REGEXES = /\/((?:[^\\\/]+|\\.)+)\/(i?)/; // match regexes (rgxBody, rgxFlags)
// var RGX_STRINGS = /("(?:[^\\"]+|\\.)*")/; // match strings (strRaw)
// var RGX_ASTERISKS = /(\*)/; // match * (isAsterisk)
// var RGX_INTEGERS = /(#(?:(-?\d+|\?)\.\.(-?\d+|\?)(?:\.\.(-?\d+))?#)?)/; // match integer ranges (isRange, numMin, numMax, numStep)
// var RGX_SIMPLE_NAMES = /([1-9]\d+|[\$_A-Za-z][\$\w]*)/; // match simple names and integers (strName)
var RGX_NAMES = /\/((?:[^\\\/]+|\\.)+)\/(i?)|("(?:[^\\"]+|\\.)*")|(\*)|(#(?:(-?\d+|\?)\.\.(-?\d+|\?)(?:\.\.(-?\d+))?#)?)|(0|[1-9]\d*|[\$_A-Za-z][\$\w]*)/g;
function fuzzPath(strPath) {
var level, candidate, levels = [];
strPath = strPath.replace(
RGX_NAMES,
function(source, expBody, expFlags, strRaw, isAsterisk, isRange, numMin, numMax, numStep, strName, index, strPath) {
var isNewLevel = /(^|\.|\[)\s*$/.test(strPath.slice(0, index));
if (isNewLevel) {
levels.push(level = []);
}
if (expBody) {
candidate = {
type: 'RegExp',
value: new RegExp(expBody, expFlags)
};
}
else if (strRaw || strName) {
candidate = {
type: 'String',
value: strName || JSON.parse(strRaw.replace(/\\(?:(0)|x([\dA-F]{2}))/g, '\\u00$1$1$2'))
};
}
else if (isAsterisk) {
candidate = { type: 'Anything' };
}
else if (isRange) {
if ((numMin || '?') === '?' && (numMax || '?') === '?') {
if ((numStep || '?') !== '?') {
throw new Error('"?..?" is an invalid fuzz range.');
}
candidate = { type: 'RegExp', value: /^-(?:0|[1-9]\d*)$/ };
}
else {
var isBasedOnMin = numMin !== '?';
numMin = isBasedOnMin ? +numMin : -Infinity;
numMax = numMax === '?' ? Infinity : +numMax;
numStep = numStep === '?' ? 1 : +numStep;
candidate = {
type: 'Function',
value: function (key) {
if (/^-(?:0|[1-9]\d*)$/.test(key)) {
key = +key;
return (numStep === 1 || ((isBasedOnMin ? key - numMin : (numMax - key)) / numStep) % 1 === 0) && numMin <= key && key <= numMax;
}
return false;
}
}
}
}
candidate.source = source;
level.push(candidate);
return '@';
}
);
if (!/^(?:\.@(?:\|@)*|\[@(?:\|@)*\])+$/.test(strPath.replace(/\s+/g, '').replace(/^[^\[]/, '.$&'))) {
throw new Error('This expression cannot be reduced any further:\t' + strPath);
}
return levels;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment