Created
October 4, 2019 04:22
-
-
Save westc/24600413a1ff3e8fb6f252d73f6da9c8 to your computer and use it in GitHub Desktop.
Allow for fuzzy path matching.
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
// 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