Skip to content

Commit

Permalink
bound mode renames
Browse files Browse the repository at this point in the history
  • Loading branch information
leeoniya committed Sep 23, 2022
1 parent 86f586e commit 713ec4f
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 142 deletions.
34 changes: 17 additions & 17 deletions demos/compare.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,19 @@

<div style="display: inline-block; width: 170px; vertical-align: middle;">
<label>
strictPre
<select id="strictPre">
lftMode
<select id="lftMode">
<option value="0"></option>
<option value="1">Loose</option>
<option value="2">Strict</option>
<option value="1">loose</option>
<option value="2">strict</option>
</select>
</label>
<label>
strictSuf
<select id="strictSuf">
rgtMode
<select id="rgtMode">
<option value="0"></option>
<option value="1">Loose</option>
<option value="2">Strict</option>
<option value="1">loose</option>
<option value="2">strict</option>
</select>
</label>
</div>
Expand Down Expand Up @@ -251,7 +251,7 @@
// copy & tweak from core
const cmp = new Intl.Collator('en').compare;
const typeAheadSort = (info, haystack, needle) => {
let { idx, term, pre0, pre1, suf0, suf1, span, start, intra, inter } = info;
let { idx, term, lft2, lft1, rgt2, rgt1, span, start, intra, inter } = info;

return idx.map((v, i) => i).sort((ia, ib) => (
// least char intra-fuzz (most contiguous)
Expand All @@ -262,8 +262,8 @@
haystack[idx[ia]].length - haystack[idx[ib]].length ||
// most prefix/suffix bounds, boosted by full term matches
(
(term[ib] + pre0[ib] + 0.5 * pre1[ib] + suf0[ib] + 0.5 * suf1[ib]) -
(term[ia] + pre0[ia] + 0.5 * pre1[ia] + suf0[ia] + 0.5 * suf1[ia])
(term[ib] + lft2[ib] + 0.5 * lft1[ib] + rgt2[ib] + 0.5 * rgt1[ib]) -
(term[ia] + lft2[ia] + 0.5 * lft1[ia] + rgt2[ia] + 0.5 * rgt1[ia])
) ||
// highest density of match (least span)
// span[ia] - span[ib] ||
Expand Down Expand Up @@ -360,8 +360,8 @@
interLimit: (tmpVar = urlParams.get('interLimit')) == null ? Infinity : tmpVar == 'inf' ? Infinity : +tmpVar,
// interChars: '.',

strictPre: (tmpVar = urlParams.get('strictPre')) != null ? +tmpVar : 0,
strictSuf: (tmpVar = urlParams.get('strictSuf')) != null ? +tmpVar : 0,
lftMode: (tmpVar = urlParams.get('lftMode')) != null ? +tmpVar : 0,
rgtMode: (tmpVar = urlParams.get('rgtMode')) != null ? +tmpVar : 0,

withRanges: (tmpVar = urlParams.get('withRanges')) == null || tmpVar == '' || tmpVar == 'true' || tmpVar == '1',

Expand Down Expand Up @@ -435,14 +435,14 @@
ufSearch(e);
});

document.getElementById('strictPre').addEventListener('change', e => {
opts.strictPre = +e.target.value;
document.getElementById('lftMode').addEventListener('change', e => {
opts.lftMode = +e.target.value;
u = new uFuzzy(opts);
ufSearch(e);
});

document.getElementById('strictSuf').addEventListener('change', e => {
opts.strictSuf = +e.target.value;
document.getElementById('rgtMode').addEventListener('change', e => {
opts.rgtMode = +e.target.value;
u = new uFuzzy(opts);
ufSearch(e);
});
Expand Down
70 changes: 39 additions & 31 deletions dist/uFuzzy.cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ const OPTS = {
interSplit: '[^A-Za-z0-9]+',
intraSplit: '[A-Za-z][0-9]|[0-9][A-Za-z]|[a-z][A-Z]',

strictPre: 0,
strictSuf: 0,
// inter-bounds mode
// 2 = strict (will only match 'man' on whitepace and punct boundaries: Mega Man, Mega_Man, mega.man)
// 1 = loose (plus allowance for alpha-num and case-change boundaries: MegaMan, 0007man)
// 0 = none (will match 'man' as any substring: megamaniac)
lftMode: 0,
rgtMode: 0,

// allowance between terms
interChars: '.',
Expand All @@ -45,15 +49,15 @@ const OPTS = {

// final sorting fn
sort: (info, haystack, needle) => {
let { idx, term, pre0, pre1, suf0, suf1, span, start, intra, inter } = info;
let { idx, term, lft2, lft1, rgt2, rgt1, span, start, intra, inter } = info;

return idx.map((v, i) => i).sort((ia, ib) => (
// least char intra-fuzz (most contiguous)
intra[ia] - intra[ib] ||
// most prefix/suffix bounds, boosted by full term matches
(
(term[ib] + pre0[ib] + 0.5 * pre1[ib] + suf0[ib] + 0.5 * suf1[ib]) -
(term[ia] + pre0[ia] + 0.5 * pre1[ia] + suf0[ia] + 0.5 * suf1[ia])
(term[ib] + lft2[ib] + 0.5 * lft1[ib] + rgt2[ib] + 0.5 * rgt1[ib]) -
(term[ia] + lft2[ia] + 0.5 * lft1[ia] + rgt2[ia] + 0.5 * rgt1[ia])
) ||
// highest density of match (least span)
// span[ia] - span[ib] ||
Expand All @@ -74,12 +78,16 @@ const lazyRepeat = (chars, limit) => (
chars + `{0,${limit}}?`
);

const mode2Tpl = '(?:\\b|_)';

function uFuzzy(opts) {
opts = Object.assign({}, OPTS, opts);

let intraSplit = new RegExp(opts.intraSplit, 'g');
let interSplit = new RegExp(opts.interSplit, 'g');

const { lftMode, rgtMode } = opts;

const prepQuery = (query, capt = 0) => {
// split on punct, whitespace, num-alpha, and upper-lower boundaries
let parts = query.trim().replace(intraSplit, m => m[0] + ' ' + m[1]).split(interSplit);
Expand All @@ -98,8 +106,8 @@ function uFuzzy(opts) {

// this only helps to reduce initial matches early when they can be detected
// TODO: might want a mode 3 that excludes _
let preTpl = opts.strictPre == 2 ? '(?:\\b|_)' : '';
let sufTpl = opts.strictSuf == 2 ? '(?:\\b|_)' : '';
let preTpl = lftMode == 2 ? mode2Tpl : '';
let sufTpl = rgtMode == 2 ? mode2Tpl : '';

let interCharsTpl = sufTpl + lazyRepeat(opts.interChars, opts.interLimit) + preTpl;

Expand All @@ -113,7 +121,7 @@ function uFuzzy(opts) {
reTpl = reTpl.join(interCharsTpl);

if (capt > 0) {
if (opts.strictPre == 2)
if (lftMode == 2)
reTpl = '(' + preTpl + ')' + reTpl + '(' + sufTpl + ')';
else
reTpl = '(.?)' + reTpl + '(.?)';
Expand Down Expand Up @@ -162,7 +170,7 @@ function uFuzzy(opts) {
// length of match
// span: field.slice(),

// contiguous (no fuzz) and bounded terms (intra=0, pre0/1, suf0/1)
// contiguous (no fuzz) and bounded terms (intra=0, lft2/1, rgt2/1)
// excludes terms that are contiguous but have < 2 bounds (substrings)
term: field.slice(),
// contiguous chars matched (currently, from full terms)
Expand All @@ -173,19 +181,19 @@ function uFuzzy(opts) {
intra: field.slice(), // between chars within terms

// hard/soft prefix/suffix counts
// e.g. MegaMan (pre0: 1, suf0: 1, pre1: 1, suf1: 1), Mega Man (pre0: 2, suf0: 2)
// e.g. MegaMan (lft2: 1, rgt2: 1, lft1: 1, rgt1: 1), Mega Man (lft2: 2, rgt2: 2)
// hard boundaries
pre0: field.slice(), // lftH, rgtH, or lft1 (match lftMode number)
suf0: field.slice(),
lft2: field.slice(), // lftH, rgtH, or lft1 (match lftMode number)
rgt2: field.slice(),
// soft boundaries
pre1: field.slice(), // lftS, rgtS
suf1: field.slice(),
lft1: field.slice(), // lftS, rgtS
rgt1: field.slice(),

ranges: opts.withRanges ? Array(idxs.length) : null,
};

// might discard idxs based on bounds checks
let mayDiscard = opts.strictPre == 1 || opts.strictSuf == 1;
let mayDiscard = lftMode == 1 || rgtMode == 1;

let ii = 0;

Expand All @@ -200,10 +208,10 @@ function uFuzzy(opts) {
// let span = m[0].length;

let disc = false;
let pre0 = 0;
let pre1 = 0;
let suf0 = 0;
let suf1 = 0;
let lft2 = 0;
let lft1 = 0;
let rgt2 = 0;
let rgt1 = 0;
let term = 0;

for (let j = 0, k = 2; j < parts.length; j++, k+=2) {
Expand Down Expand Up @@ -240,17 +248,17 @@ function uFuzzy(opts) {

// prefix info
if (lftCharIdx == -1 || interBound.test(mhstr[lftCharIdx]))
fullMatch && pre0++;
fullMatch && lft2++;
else {
if (opts.strictPre == 2) {
if (lftMode == 2) {
disc = true;
break;
}

if (intraBound.test(mhstr[lftCharIdx] + mhstr[lftCharIdx + 1]))
fullMatch && pre1++;
fullMatch && lft1++;
else {
if (opts.strictPre == 1) {
if (lftMode == 1) {
disc = true;
break;
}
Expand All @@ -261,17 +269,17 @@ function uFuzzy(opts) {

// suffix info
if (rgtCharIdx == mhstr.length || interBound.test(mhstr[rgtCharIdx]))
fullMatch && suf0++;
fullMatch && rgt2++;
else {
if (opts.strictSuf == 2) {
if (rgtMode == 2) {
disc = true;
break;
}

if (intraBound.test(mhstr[rgtCharIdx - 1] + mhstr[rgtCharIdx]))
fullMatch && suf1++;
fullMatch && rgt1++;
else {
if (opts.strictSuf == 1) {
if (rgtMode == 1) {
disc = true;
break;
}
Expand All @@ -295,10 +303,10 @@ function uFuzzy(opts) {

if (!disc) {
info.idx[ii] = idxs[i];
info.pre0[ii] = pre0;
info.pre1[ii] = pre1;
info.suf0[ii] = suf0;
info.suf1[ii] = suf1;
info.lft2[ii] = lft2;
info.lft1[ii] = lft1;
info.rgt2[ii] = rgt2;
info.rgt1[ii] = rgt1;
info.term[ii] = term;

info.start[ii] = start;
Expand Down
Loading

0 comments on commit 713ec4f

Please sign in to comment.