### Generic Library Setup Function Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html A utility function to set up various fuzzy search libraries. It handles both synchronous and asynchronous setup processes, storing the search, toStr, and clear functions on the library object. It ensures that a clear function is always available, defaulting to a no-operation function if not provided. ```javascript function setup(lib, haystack) { let o = lib.setup(haystack, lib.opts); if (o instanceof Promise) { return o.then(({search, toStr, clear}) => { lib.search = search; lib.toStr = toStr; lib.clear = clear ?? _noop; }); } else { let {search, toStr, clear} = o; lib.search = search; lib.toStr = toStr; lib.clear = clear ?? _noop; return Promise.resolve(); } } ``` -------------------------------- ### Install uFuzzy via npm Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Installs the uFuzzy library using npm, a package manager for Node.js. This is the standard way to add uFuzzy to your Node.js project. ```bash npm i @leeoniya/ufuzzy ``` -------------------------------- ### FuzzySearch Library Setup Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Initializes and configures the FuzzySearch library for performing fuzzy searches on a list of strings. It maps input data and sets options for case sensitivity and sorting. ```javascript haystack = haystack.map(s => ({s})); let fuzzySearch = new FuzzySearch(haystack, ['s'], opts); return { search: needle => { return fuzzySearch.search(needle); }, toStr: m => m.s, }; ``` -------------------------------- ### uFuzzy Custom Match Highlighting (innerHTML) Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Shows how to customize the match highlighting in uFuzzy by providing a custom marking function. This example uses `` tags for marking and generates HTML output. ```javascript let haystack = [ 'foo', 'bar', 'cowbaz', ]; let needle = 'ba'; let u = new uFuzzy(); let idxs = u.filter(haystack, needle); let info = u.info(idxs, haystack, needle); let order = u.sort(info, haystack, needle); let innerHTML = ''; const mark = (part, matched) => matched ? '' + part + '' : part; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; innerHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark, ) + '
'; } console.log(innerHTML); ``` -------------------------------- ### Configure Charsets and Alphabets for uFuzzy Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md This snippet demonstrates how to configure uFuzzy options for different alphabets and character sets. It shows examples for Latin, Latin with Norwegian/Russian extensions, and a universal Unicode mode. Note that Unicode mode is significantly slower. Case-sensitive search is not supported. ```javascript let opts = { alpha: "a-z" }; let opts = { interSplit: "[^A-Za-z\\d']+", intraSplit: "[a-z][A-Z]", intraBound: "[A-Za-z]\\d|\\d[A-Za-z]|[a-z][A-Z]", intraChars: "[a-z\\d']", intraContr: "'[[a-z]{1,2}\\b", }; let opts = { alpha: "a-zæøå" }; let opts = { interSplit: "[^A-Za-zæøåÆØÅ\\d']+", intraSplit: "[a-zæøå][A-ZÆØÅ]", intraBound: "[A-Za-zæøåÆØÅ]\\d|\\d[A-Za-zæøåÆØÅ]|[a-zæøå][A-ZÆØÅ]", intraChars: "[a-zæøå\\d']", intraContr: "'[[a-zæøå]{1,2}\\b", }; let opts = { alpha: "a-zа-яё" }; let opts = { interSplit: "[^A-Za-zА-ЯЁа-яё\\d']+", intraSplit: "[a-z][A-Z]|[а-яё][А-ЯЁ]", intraBound: "[A-Za-zА-ЯЁа-яё]\\d|\\d[A-Za-zА-ЯЁа-яё]|[a-z][A-Z]|[а-яё][А-ЯЁ]", intraChars: "[a-zа-яё\\d']", intraContr: "'[[a-z]{1,2}\\b", }; let opts = { unicode: true, interSplit: "[^\\p{L}\\d']+", intraSplit: "\\p{Ll}\\p{Lu}", intraBound: "\\p{L}\\d|\\d\\p{L}|\\p{Ll}\\p{Lu}", intraChars: "[\\p{L}\\d']", intraContr: "'\\p{L}{1,2}\\b", }; ``` -------------------------------- ### NDX Fuzzy Search Indexing and Querying Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Utilizes the ndx library for fuzzy search. It creates an index from the haystack, allowing for efficient querying. The setup involves defining term filters, splitters, and field getters. The search function queries the index based on the needle. ```javascript const { createIndex, indexAdd, indexQuery } = ndx; const termFilter = (term) => term.toLowerCase(); const splitterRe = /[^a-z0-9]+/gi; const splitter = (s) => s.split(splitterRe); const numFields = 1; const fieldGetters = [doc => doc]; const fieldBoostFactors = [1]; const index = createIndex(numFields, splitter, termFilter); for (let i = 0; i < haystack.length; i++) indexAdd(index, fieldGetters, i, haystack[i]); return { search: needle => indexQuery(index, fieldBoostFactors, 1.2, 0.75, needle), toStr: m => `${+m.score.toFixed(2)} ` + haystack[m.key] } ``` -------------------------------- ### FuzzySearch2 Initialization Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Sets up the FuzzySearch2 library, providing the data source and configuration options for search operations. This snippet shows the initial instantiation of the searcher object. ```javascript let searcher = new FuzzySearch2({ source: hayst ``` -------------------------------- ### Initialize and Update ufuzzy Instance Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This code initializes a new ufuzzy instance with provided options and includes logic to clean up unused options like 'sort', 'intraChars', and 'interChars' if they are null. It then sets up event listeners for various UI elements to update these options dynamically and re-initialize the ufuzzy instance, triggering a search update. This allows for real-time configuration changes. ```javascript setup: (haystack, opts) => { if (opts.sort == null) delete opts.sort; if (opts.intraChars == null) delete opts.intraChars; if (opts.interChars == null) delete opts.interChars; let u = new uFuzzy(opts); // ... event listeners for UI elements to update opts and re-create uFuzzy instance } ``` -------------------------------- ### Basic Fuzzy Search with uFuzzy Source: https://context7.com/leeoniya/ufuzzy/llms.txt Performs a basic fuzzy search to filter a haystack of strings against a needle. It returns an array of indices of matching items in the haystack. No complex setup is required, and it's ideal for simple list filtering. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); let haystack = [ 'puzzle', 'Super Awesome Thing (now with stuff!)', 'FileName.js', '/feeding/the/catPic.jpg', 'The quick brown fox', 'cathedral', 'category' ]; let needle = 'feed cat'; let uf = new uFuzzy(); // Pre-filter haystack to find potential matches let idxs = uf.filter(haystack, needle); if (idxs != null && idxs.length > 0) { console.log('Matched indices:', idxs); // [3] console.log('Matched items:', idxs.map(i => haystack[i])); // Output: ['/feeding/the/catPic.jpg'] } ``` -------------------------------- ### Match Highlighting with uFuzzy Source: https://context7.com/leeoniya/ufuzzy/llms.txt Demonstrates how to highlight matched portions of search results using custom HTML tags. The `highlight()` function can be used with default `` tags or a custom highlighter function for flexible formatting. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); let haystack = [ 'foo', 'bar', 'cowbaz', 'basketball' ]; let needle = 'ba'; let uf = new uFuzzy(); let idxs = uf.filter(haystack, needle); let info = uf.info(idxs, haystack, needle); let order = uf.sort(info, haystack, needle); // Basic highlighting with tags let innerHTML = ''; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; innerHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx] ) + '
'; } console.log(innerHTML); // Output: bar
cowbaz
basketball
// Custom highlighting with tags const mark = (part, matched) => matched ? '' + part + '' : part; let customHTML = ''; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; customHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark ) + '
'; } console.log(customHTML); // Output: bar
cowbaz
basketball
``` -------------------------------- ### JavaScript Performance Timing Function Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This JavaScript function `timeIt` is a simple utility for measuring the execution time of asynchronous operations. It takes an async function as input, records the start and end times using `performance.now()`, and returns the duration in milliseconds. ```javascript async function timeIt(fn) { let start = performance.now(); await fn(); return performance.now() - start; } ``` -------------------------------- ### uFuzzy Basic Match Highlighting (innerHTML) Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Demonstrates how to highlight matched parts of strings using uFuzzy's `highlight` function with basic innerHTML output. It uses the default marking function to wrap matches with `` tags. ```javascript let haystack = [ 'foo', 'bar', 'cowbaz', ]; let needle = 'ba'; let u = new uFuzzy(); let idxs = u.filter(haystack, needle); let info = u.info(idxs, haystack, needle); let order = u.sort(info, haystack, needle); let innerHTML = ''; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; innerHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], ) + '
'; } console.log(innerHTML); ``` -------------------------------- ### Implement Custom Sort Function for Ranking Source: https://context7.com/leeoniya/ufuzzy/llms.txt Allows for custom ranking logic by providing a 'sort' function in the options. This function can prioritize results based on criteria like match start position, length of matched characters, or alphabetic order, enabling fine-grained control over search result ordering. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); // Custom sort that prioritizes start position and match length let opts = { sort: (info, haystack, needle) => { let { idx, start, chars } = info; return idx.map((v, i) => i).sort((ia, ib) => ( // Earliest start position first start[ia] - start[ib] || // Most characters matched chars[ib] - chars[ia] || // Alphabetic fallback haystack[idx[ia]].localeCompare(haystack[idx[ib]]) )); } }; let uf = new uFuzzy(opts); let haystack = [ 'The Cathedral', 'cat', 'category', 'catalog' ]; let needle = 'cat'; let idxs = uf.filter(haystack, needle); let info = uf.info(idxs, haystack, needle); let order = uf.sort(info, haystack, needle); console.log('Custom sorted results:'); order.forEach(orderIdx => { let idx = info.idx[orderIdx]; console.log(haystack[idx]); }); // Output: cat, catalog, category, The Cathedral ``` -------------------------------- ### JavaScript Type Ahead Sorting Algorithm Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This JavaScript function, `typeAheadSort`, implements a custom sorting algorithm for type-ahead suggestions in μFuzzy. It prioritizes results based on factors like contiguous characters matched, fuzziness, match start position, and match length, ensuring the most relevant suggestions appear first. ```javascript // copy & tweak from core const cmp = new Intl.Collator('en').compare; const typeAheadSort = (info, haystack, needle) => { let { idx, chars, terms, interLft2, interLft1, /* interRgt2, // interRgt1, */ start, intraIns, interIns, } = info; return idx.map((v, i) => i).sort((ia, ib) => ( // most contig chars matched chars[ib] - chars[ia] || // least char intra-fuzz (most contiguous) intraIns[ia] - intraIns[ib] || // earliest start of match start[ia] - start[ib] || // shortest match first haystack[idx[ia]].length - haystack[idx[ib]].length || // most prefix bounds, boosted by full term matches ((terms[ib] + interLft2[ib] + 0.5 * interLft1[ib]) - (terms[ia] + interLft2[ia] + 0.5 * interLft1[ia])) || // highest density of match (least span) // span[ia] - span[ib] || // highest density of match (least term inter-fuzz) interIns[ia] - interIns[ib] || // alphabetic cmp(haystack[idx[ia]], haystack[idx[ib]]) )); }; ``` -------------------------------- ### uFuzzy Integrated Search Wrapper Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Explains the `uf.search` method, a convenient wrapper that combines filtering, info gathering, and sorting steps. It supports out-of-order matching and multiple substring exclusions. ```javascript uFuzzy.search(haystack, needle, outOfOrder = 0, infoThresh = 1e3) => [idxs, info, order] ``` -------------------------------- ### uFuzzy DOM/JSX Match Highlighting Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Illustrates how to use uFuzzy's `highlight` function to generate DOM elements for matched strings, suitable for use in frameworks like React. It includes custom marking and appending functions. ```javascript let haystack = [ 'foo', 'bar', 'cowbaz', ]; let needle = 'ba'; let u = new uFuzzy(); let idxs = u.filter(haystack, needle); let info = u.info(idxs, haystack, needle); let order = u.sort(info, haystack, needle); let domElems = []; const mark = (part, matched) => { let el = matched ? document.createElement('mark') : document.createElement('span'); el.textContent = part; return el; }; const append = (accum, part) => { accum.push(part); }; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; let matchEl = document.createElement('div'); let parts = uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark, [], append, ); matchEl.append(...parts); domElems.push(matchEl); } document.getElementById('matches').append(...domElems); ``` -------------------------------- ### Load External Libraries Dynamically - JavaScript Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This code snippet dynamically loads external JavaScript libraries based on a list of names. It finds library configurations, creates script elements for each, appends them to the document body, and resolves a promise once the script has loaded. This allows for on-demand loading of fuzzy search algorithm implementations. ```javascript let libNames = getLibNames(); let proms = []; libNames.forEach(name => { let lib = libs.find(lib => lib.name == name); if (lib) { proms.push(new Promise((resolve, reject) => { let sc = document.createElement('script'); sc.src = lib.script; sc.onload = e => { resolve(lib); }; document.body.appendChild(sc); })); } }); Promise.all(proms) ``` -------------------------------- ### Add items to Fuzzyset and search Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Demonstrates how to initialize Fuzzyset, add multiple strings to its index, and then perform a search for a given needle. The `toStr` function is used to extract the original string from a match. ```javascript let fuzzySet = FuzzySet(); for (let i = 0; i < haystack.length; i++) fuzzySet.add(haystack[i]); return { search: needle => { return fuzzySet.get(needle); }, toStr: m => m[1], }; ``` -------------------------------- ### QuickScore Search with Match Highlighting Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Implements fuzzy search using the QuickScore library. It includes a utility function to wrap matched substrings with HTML `` tags for visual highlighting. ```javascript const wrapMatches = (string, matches) => { const substrings = []; let previousEnd = 0; for (const [start, end] of matches) { const prefix = string.substring(previousEnd, start); const match = `${string.substring(start, end)}`; substrings.push(prefix, match); previousEnd = end; } substrings.push(string.substring(previousEnd)); return substrings.join(''); }; const qs = new quickScore.QuickScore(haystack); return { search: needle => { return qs.search(needle); }, toStr: m => { return `${+m.score.toFixed(3)} ` + wrapMatches(m.item, m.matches); }, }; ``` -------------------------------- ### Create and search FlexSearch index Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Initializes a FlexSearch index with custom options and adds entries to it. The `search` function then queries the index for a given needle, returning results with IDs that can be mapped back to the original haystack. ```javascript const index = new FlexSearch.Index(opts); const searchOpts = { limit: Infinity, suggest: true }; for (let i = 0; i < haystack.length; i++) index.add(i, haystack[i]); return { search: needle => { return index.search(needle, searchOpts); }, toStr: id => haystack[id], }; ``` -------------------------------- ### Fetch and Build Index from JSON Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/inverted-index.html Fetches data from a JSON file (`./testdata.json`), concatenates its values into a single array, and then builds an inverted index from this data. This is typically used for setting up the search index when the application loads. ```javascript fetch('./testdata.json').then(r => r.json()).then(data => { let haystack = []; for (let k in data) haystack = haystack.concat(data[k]); console.time("build index"); index = buildIndex(haystack); console.timeEnd("build index"); }); ``` -------------------------------- ### Initialize Fuzzy Search and Event Listeners - JavaScript Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This snippet initializes fuzzy search functionality after libraries are loaded. It retrieves the search query, sets up display containers for results, and defines a `run` function to perform searches and render results. It also attaches an input event listener to the search bar to trigger searches dynamically and includes a benchmarking mode for performance testing. ```javascript .then(async libs => { let search = document.getElementById('search').value; for (let name of libNames) { let l = libs.find(lib => lib.name == name); let res = document.createElement('pre'); document.body.appendChild(res); let hzQty = Math.min(libs.length, 4); res.style.width = Math.floor(100 / hzQty) + '%'; if (libs.length > 4) res.style.height = 1200 / (libs.length / hzQty) + 'px'; let run = async (needle, render = true) => { let elapsed = 0; let matches = []; if (needle == '') l.clear(); else { elapsed = await timeIt(async () => { matches = await l.search(needle) ?? []; }); } if (render) res.innerHTML = fmtResult(l, matches, l.toStr, haystack, elapsed); }; console.time('setup ' + name); let setupRet = await setup(l, haystack); console.timeEnd('setup ' + name); setTimeout(() => { run(search); }, 0); document.getElementById("search").addEventListener('input', e => { let needle = e.target.value if (tmpOnlyLib == null || tmpOnlyLib == l.name) run(needle); }); if (BENCH) { async function typeAndDel(str) { for (let i = 0; i < str.length; i++) { run(str.slice(0, i+1), false); await delay(20); } for (let i = str.length - 1; i >= -1; i--) { run(str.slice(0, i+1), false); await delay(20); } } let go = async () => { res.innerHTML = 'RUNNING BENCHMARK...'; await typeAndDel('test'); await typeAndDel('chest'); await typeAndDel('super ma'); await typeAndDel('mania'); await typeAndDel('puzz'); await typeAndDel('prom rem stor'); await typeAndDel('twil'); res.innerHTML = 'DONE!'; }; setTimeout(go, 1000); } } }); ``` -------------------------------- ### Custom Configuration Options for ufuzzy Matching Source: https://context7.com/leeoniya/ufuzzy/llms.txt Allows fine-tuning of the fuzzy matching algorithm through a configuration object passed to the uFuzzy constructor. Options like `intraMode`, `intraIns`, `interIns`, `interLft`, and `interRgt` control error tolerance and boundary matching. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); // Configure for stricter matching let opts = { intraMode: 1, // Enable single-error tolerance intraIns: 1, // Allow 1 extra char between term chars interIns: 10, // Allow max 10 chars between terms interLft: 1, // Require loose left boundary interRgt: 1 // Require loose right boundary }; let uf = new uFuzzy(opts); let haystack = [ 'mania', 'maniac', 'TrackMania', 'romanian', 'mania_game' ]; let needle = 'mania'; let idxs = uf.filter(haystack, needle); let info = uf.info(idxs, haystack, needle); let order = uf.sort(info, haystack, needle); console.log('Strict boundary matches:'); order.forEach(orderIdx => { let idx = info.idx[orderIdx]; console.log(haystack[idx]); }); // Output: mania, maniac, TrackMania, mania_game // (excludes 'romanian' due to boundary rules) ``` -------------------------------- ### Include uFuzzy in Browser Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Includes the uFuzzy library in an HTML file using a script tag. This makes the uFuzzy functionality available globally in the browser's JavaScript environment. ```javascript ``` -------------------------------- ### JavaScript Library Configuration for μFuzzy Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This JavaScript code snippet initializes the configuration for the μFuzzy library. It retrieves various search parameters from URL query strings, such as `intraIns`, `interIns`, `intraChars`, `interChars`, `interLft`, and `interRgt`, to customize the fuzzy search behavior. ```javascript let tmpOnlyLib = null; let libs = [ { name: 'uFuzzy', script: '../dist/uFuzzy.iife.js', fulltext: false, repo: 'https://github.com/leeoniya/uFuzzy', demo: 'https://leeoniya.github.io/uFuzzy/demos/compare.html', opts: { intraIns: (tmpVar = urlParams.get('intraIns')) == null ? 0 : tmpVar == 'inf' ? Infinity : +tmpVar, interIns: (tmpVar = urlParams.get('interIns')) == null ? Infinity : tmpVar == 'inf' ? Infinity : +tmpVar, intraChars: (tmpVar = urlParams.get('intraChars')), interChars: (tmpVar = urlParams.get('interChars')), interLft: (tmpVar = urlParams.get('interLft')) != null ? +tmpVar : 0, interRgt: (tmpVar = urlParams.get('interRgt')) != null ? +tmpVar : 0, } } ]; ``` -------------------------------- ### Match Highlighting Source: https://context7.com/leeoniya/ufuzzy/llms.txt Highlights matched portions of search results using custom HTML tags. ```APIDOC ## Match Highlighting ### Description Highlights matched portions of search results using custom HTML tags. ### Method `highlight(text, ranges, [formatter])` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); let haystack = [ 'foo', 'bar', 'cowbaz', 'basketball' ]; let needle = 'ba'; let uf = new uFuzzy(); let idxs = uf.filter(haystack, needle); let info = uf.info(idxs, haystack, needle); let order = uf.sort(info, haystack, needle); // Basic highlighting with tags let innerHTML = ''; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; innerHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx] ) + '
'; } console.log(innerHTML); // Output: bar
cowbaz
basketball
// Custom highlighting with tags const mark = (part, matched) => matched ? '' + part + '' : part; let customHTML = ''; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; customHTML += uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark ) + '
'; } console.log(customHTML); // Output: bar
cowbaz
basketball
``` ### Response #### Success Response (200) - **Highlighted HTML String** (string) - An HTML string with matched portions highlighted. #### Response Example ```html bar
cowbaz
basketball
``` ``` -------------------------------- ### Data Loading and Haystack Setting Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Fetches data from 'testdata.json', processes it based on selected list names from URL parameters or UI elements, and sets the haystack for the fuzzy search libraries. It also triggers an input event to update the search results. ```javascript fetch('./testdata.json').then(r => r.json()).then(data => { // let haystack = data.steam_games; // let haystack = data.wordlist_58k; // let haystack = data.test; // let haystack = data.metric_name; let listNames = urlParams.get('lists'); if (listNames == null) listNames = allListNames; else listNames = listNames.split(','); let haystack = listNames.flatMap(k => data[k]); let listsEl = document.getElementById('lists'); function setHaystack(_haystack) { haystack = _haystack; getLibNames().forEach(name => { let lib = libs.find(lib => lib.name == name); setup(lib, haystack); }); document.getElementById('search').dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); } listsEl.addEventListener('change', e => { listNames = [...listsEl.querySelectorAll('option')].filter(option => option.selected).map(option => option.value); setHaystack(listNames.flatMap(k => data[k])); document.querySelector('#droptip').style.display = 'block'; document.querySelector('#dropfilename').textContent = ''; }); let noop = e => { e.stopPropagation(); e.preventDefault(); }; let fileDropEl = document.getElementById('filedrop'); fileDropEl.ondragenter = noop; fileDropEl.ondragover = noop; fileDropEl ``` -------------------------------- ### Event Listener for Search Input Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/inverted-index.html Attaches an event listener to an HTML input element for search queries. When the input value changes, it triggers a search using the `searchIndex` function and displays a limited number of results. It also logs the search time for performance monitoring. Assumes `index` is populated and `resultsEl` is a valid DOM element. ```javascript const queryEl = document.querySelector("#query"); const resultsEl = document.querySelector("#results"); let index; let renderLimit = 1e3; queryEl.addEventListener("input", e => { let query = e.target.value.trim(); if (query === "") resultsEl.textContent = ""; else { console.time('search'); let lineNums = searchIndex(index, query); console.timeEnd('search'); resultsEl.textContent = lineNums.slice(0, renderLimit).map(lineNum => index.lines[lineNum]).join("\n"); } }); ``` -------------------------------- ### Fuzzysort Search with Highlighting Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Integrates the fuzzysort library for fuzzy searching. It prepares data for efficient searching and provides a function to highlight search matches within the results. ```javascript haystack = haystack.map(s => fuzzysort.prepare(s)); return { search: needle => { return fuzzysort.go(needle, haystack, opts); }, toStr: m => { return `${+m.score.toFixed(4)} ` + fuzzysort.highlight(m, '', ''); }, }; ``` -------------------------------- ### JavaScript Utility Functions for μFuzzy Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This JavaScript code defines utility functions for the μFuzzy library, including a delay function, URL parameter parsing, and formatting numbers and results. It handles setting up initial search parameters from the URL and prepares the output for display. ```javascript const delay = async (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)); let urlParams = new URLSearchParams(location.search); let tmpVar; // previous sig support (published urls) if ((tmpVar = urlParams.get('intraMax')) != null) urlParams.set('intraIns', tmpVar); if (urlParams.get('intraSub') != null || urlParams.get('intraTrn') != null || urlParams.get('intraDel') != null) urlParams.set('intraMode', '1'); const BENCH = urlParams.get('bench') != null; for (let [k, v] of urlParams) { let inp = document.getElementById(k); if (inp) { if (inp.matches('input[type=checkbox]')) inp.checked = v != '0' && v != 'false'; else if (k == 'lists') { let lists = new Set(v.split(',')); [...inp.querySelectorAll('option')].forEach(option => { option.selected = lists.has(option.value); }); } else inp.value = v == 'inf' ? '' : v; if (k == 'search') document.title = 'μFuzzy - ' + v; } } if (urlParams.get('lists') == null) { [...document.querySelectorAll('#lists option')].forEach(option => { option.selected = true; }); } document.getElementById('clippy').addEventListener('click', e => { e.target.style.display = 'none'; }); const fmtNum = new Intl.NumberFormat('en-US').format; function fmtResult(lib, found, toStr, haystack, elapsed) { let allCount = fmtNum(haystack.length); let foundCount = fmtNum(found.length); if (BENCH) found = []; else found = found.slice(0, 1000).map(s => toStr(s).replace(/[ ]+/gm, ' ')); return [ `${lib.name} repo` + (lib.demo ? ` demo` : ''), '='.repeat(50), `${foundCount} results (of ${allCount}), ${elapsed.toFixed(1)}ms`, '', found.join('\n'), ].join('\n'); } ``` -------------------------------- ### Indexing and searching with MiniSearch Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Sets up MiniSearch for full-text searching. It indexes an array of objects, allowing for searches based on the 's' field. Results are returned with a score and the original string. ```javascript let miniSearch = new MiniSearch({ fields: ['s'], searchOptions: { prefix: true } }); miniSearch.addAll(haystack.map((s, i) => ({s, id: i}))); return { search: needle => { return miniSearch.search(needle, { combineWith: 'AND' }); }, toStr: m => `${+m.score.toFixed(2)} ` + haystack[m.id], }; ``` -------------------------------- ### Create Highlighted DOM Elements with ufuzzy Source: https://context7.com/leeoniya/ufuzzy/llms.txt Generates DOM elements with marked matches for direct insertion into a webpage. It uses custom mark and append functions to create and structure the highlighted output. Requires the 'document' object for DOM manipulation. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); let haystack = ['basketball', 'football', 'baseball']; let needle = 'ball'; let uf = new uFuzzy(); let idxs = uf.filter(haystack, needle); let info = uf.info(idxs, haystack, needle); let order = uf.sort(info, haystack, needle); // Custom mark function that creates DOM elements const mark = (part, matched) => { let el = matched ? document.createElement('mark') : document.createElement('span'); el.textContent = part; return el; }; // Custom append function for DOM elements const append = (accum, part) => { accum.push(part); }; let domElems = []; for (let i = 0; i < order.length; i++) { let infoIdx = order[i]; let matchEl = document.createElement('div'); let parts = uFuzzy.highlight( haystack[info.idx[infoIdx]], info.ranges[infoIdx], mark, [], append ); matchEl.append(...parts); domElems.push(matchEl); } // Insert into page document.getElementById('matches').append(...domElems); ``` -------------------------------- ### Score and sort matches with LiquidMetal Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This code demonstrates using LiquidMetal to score strings in a haystack against a needle. It calculates a score for each string, filters those with a score greater than 0, and sorts them by score. ```javascript let scores = Array(haystack.length); for (let i = 0; i < haystack.length; i++) { scores.push({ i, score: LiquidMetal.score(haystack[i], needle), }); } return scores.filter(m => m.score > 0).sort((a, b) => a.score - b.score); ``` -------------------------------- ### uFuzzy Search Phases: Filter, Info, Sort Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Explains the three distinct phases involved in a uFuzzy search operation. The Filter phase uses a fast RegExp for initial matching. The Info phase gathers detailed statistics and substring positions. The Sort phase orders the final results, optionally using a custom sort function. ```javascript // 1. Filter phase: Fast RegExp compilation from needle // Returns array of matched indices. // 2. Info phase: Collects detailed stats, substring match positions, and filters by prefix/suffix rules. // Re-compiles needle into two more-expensive RegExps. // Should be run on a reduced subset of the haystack (usually from Filter phase). // 3. Sort phase: Uses Array.sort() on the info object to determine final result order. // A custom sort function can be provided: { sort: (info, haystack, needle) => idxsOrder } ``` -------------------------------- ### Multi-Language Support Source: https://context7.com/leeoniya/ufuzzy/llms.txt Configure uFuzzy to support non-Latin alphabets and Unicode characters for broader search compatibility. ```APIDOC ## Multi-Language Support ### Description Configure for non-Latin alphabets and Unicode characters. ### Method `new uFuzzy(options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); // Configure for Cyrillic (Russian) support let opts = { alpha: 'a-zа-яё' // Latin + Russian }; let uf = new uFuzzy(opts); let haystack = [ 'Привет мир', 'Привет друг', 'Здравствуй' ]; let needle = 'прив'; let idxs = uf.filter(haystack, needle); console.log('Cyrillic matches:'); idxs.forEach(idx => console.log(haystack[idx])); // Output: Привет мир, Привет друг // Universal Unicode support (50-75% slower) let unicodeOpts = { unicode: true, interSplit: '[^\p{L}\d\']+', intraSplit: '\p{Ll}\p{Lu}', intraBound: '\p{L}\d|\d\p{L}|\p{Ll}\p{Lu}', intraChars: '[\p{L}\d\']', intraContr: '\'\p{L}{1,2}\b' }; let ufUnicode = new uFuzzy(unicodeOpts); ``` ### Response #### Success Response (200) Initializes a uFuzzy instance with the specified options for multi-language support. #### Response Example No direct response, but the instance `uf` or `ufUnicode` is configured for the specified language/Unicode search. ``` -------------------------------- ### fzf-for-js Fuzzy Search Implementation Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Implements fuzzy searching using fzf-for-js with case-insensitive matching. It finds matches for a given needle and formats the results by highlighting matched characters. The `toStr` function dynamically generates the highlighted string. ```javascript { name: 'fzf-for-js', script: './lib/fzf.iife.min.js', fulltext: false, repo: 'https://github.com/ajitid/fzf-for-js', opts: {}, setup: (haystack, opts) => { const fzf = new Fzf.Fzf(haystack, { casing: 'case-insensitive', normalize: false, }); let toStr; return { search: needle => { let matches = fzf.find(needle); if (matches.length <= 1e3) { toStr = m => { let item = m.item; let pos = m.positions; let s = ''; for (let i = 0; i < item.length; i++) { if (pos.has(i)) s += '' + item[i] + ''; else s += item[i]; } return s; }; } else toStr = m => m.item; return matches; }, toStr: m => toStr(m) }; }, search: null, toStr: null } ``` -------------------------------- ### Advanced Search with Ranking Source: https://context7.com/leeoniya/ufuzzy/llms.txt Retrieves ranked and sorted fuzzy search results along with detailed match information. ```APIDOC ## Advanced Search with Ranking ### Description Retrieves ranked and sorted fuzzy search results along with detailed match information. ### Method `info(idxs, haystack, needle)` and `sort(info, haystack, needle)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); let haystack = [ 'puzzle', 'Super Mario Bros', 'super mario world', 'Mario Kart', 'Super Smash Bros', 'superman returns' ]; let needle = 'super ma'; let uf = new uFuzzy(); let idxs = uf.filter(haystack, needle); if (idxs != null && idxs.length > 0) { let infoThresh = 1000; if (idxs.length <= infoThresh) { // Collect detailed match statistics let info = uf.info(idxs, haystack, needle); // Get sorted order based on match quality let order = uf.sort(info, haystack, needle); // Display results in ranked order console.log('Top matches:'); for (let i = 0; i < order.length; i++) { let idx = info.idx[order[i]]; console.log(`${i + 1}. ${haystack[idx]}`); } // Output: // 1. Super Mario Bros // 2. super mario world // 3. Super Smash Bros } } ``` ### Response #### Success Response (200) - **info** (Object) - Contains detailed match statistics including `idx` (indices) and `ranges` (matched character ranges). - **order** (Array) - An array of indices representing the ranked order of matches. #### Response Example ```json { "info": { "idx": [1, 2, 4], "ranges": [[0, 5], [0, 5], [0, 5]] }, "order": [0, 1, 2] } ``` ``` -------------------------------- ### Fuse.js Search with Match Highlighting Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Utilizes the Fuse.js library for fuzzy searching. It includes a helper function to format search results by highlighting matched indices. ```javascript // const index = Fuse.createIndex([], haystack); const index = null; const fuse = new Fuse(haystack, opts, index); // https://github.com/krisk/Fuse/issues/6#issuecomment-455813098 const highlightFuse = (inputText, regions = []) => { let content = ''; let nextUnhighlightedRegionStartingIndex = 0; regions.forEach(region => { const lastRegionNextIndex = region[1] + 1; content += [ inputText.substring(nextUnhighlightedRegionStartingIndex, region[0]), '', inputText.substring(region[0], lastRegionNextIndex), '', ].join(''); nextUnhighlightedRegionStartingIndex = lastRegionNextIndex; }); content += inputText.substring(nextUnhighlightedRegionStartingIndex); return content; }; return { search: needle => { // debugger; return fuse.search(needle); }, toStr: m => `${+m.score.toFixed(4)} ` + highlightFuse(m.item, m.matches[0].indices), }; ``` -------------------------------- ### Import uFuzzy in Node.js Source: https://github.com/leeoniya/ufuzzy/blob/main/README.md Imports the uFuzzy library into your Node.js project using the require function. This makes the uFuzzy functionality available for use in your scripts. ```javascript const uFuzzy = require('@leeoniya/ufuzzy'); ``` -------------------------------- ### fast-fuzzy Search Implementation Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html Integrates the fast-fuzzy library for efficient fuzzy string searching. It initializes a `Searcher` with the haystack and provides a search method that returns direct matches. ```javascript { name: 'fast-fuzzy', script: './lib/fast-fuzzy.iife.min.js', fulltext: false, repo: 'https://github.com/EthanRutherford/fast-fuzzy', opts: {}, setup: (haystack, opts) => { const searcher = new fastfuzzy.Searcher(haystack); return { search: needle => { return searcher.search(needle); }, toStr: m => m }; }, search: null, toStr: null } ``` -------------------------------- ### Handle File Drop and Parse Data - JavaScript Source: https://github.com/leeoniya/ufuzzy/blob/main/demos/compare.html This snippet handles the 'drop' event on an HTML element. It prevents default behavior, hides UI elements, retrieves the dropped file, and parses its content. The content can be either JSON or a delimited string, which is then used to set the 'haystack' for fuzzy searching. It also resets selection options. ```javascript l.ondrop = e => { noop(e); document.getElementById('clippy').style.display = 'none'; let file = e.dataTransfer.files[0]; document.querySelector('#droptip').style.display = 'none'; document.querySelector('#dropfilename').textContent = file.name; file.text().then(txt => { let d; try { d = JSON.parse(txt); } catch (e) { d = txt.trim().split(/[,\r\n]+/gm); } setHaystack(d); for (let opt of listsEl.querySelectorAll('option')) opt.selected = false; }); }; ```