{"versions":{"0.1.5":{"name":"@nozbe/microfuzz","description":"A tiny, simple, fast fuzzy search library","version":"0.1.5","scripts":{"up":"yarn","ci:check":"concurrently -n 'test,eslint,flow,ts' -c 'auto' 'npm run test' 'npm run eslint' 'npm run flow' 'npm run ts' --kill-others-on-fail","ci":"npm run ci:check","flow":"flow check --max-warnings=0 --color=always","ts":"tsc","eslint":"eslint ./src -c ./.eslintrc.js --cache --cache-location ./.cache/.eslintcache","test":"jest","build":"rm -fr dist && babel src --out-dir dist --ignore 'src/__tests__' --copy-files --no-copy-ignored"},"keywords":["fuzzy search","command palette","jump to","autocomplete","react"],"author":{"name":"Radek Pietruszewski","email":"this.is@radex.io","url":"https://radex.io"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Nozbe/microfuzz.git"},"bugs":{"url":"https://github.com/Nozbe/microfuzz/issues"},"homepage":"https://github.com/Nozbe/microfuzz#readme","publishConfig":{"registry":"https://registry.npmjs.org/","access":"public"},"main":"dist/index.js","types":"dist/index.d.ts","devDependencies":{"@babel/cli":"^7.21.0","@babel/core":"^7.21.0","@babel/eslint-parser":"^7.19.1","@babel/plugin-transform-flow-comments":"^7.22.5","@babel/plugin-transform-react-jsx":"^7.21.0","@babel/preset-env":"^7.22.9","@typescript-eslint/eslint-plugin":"^5.53.0","@typescript-eslint/parser":"^5.53.0","chalk":"^4.1.0","chokidar-cli":"^3.0.0","concurrently":"^7.6.0","eslint":"^8.34.0","eslint-config-airbnb":"^19.0.4","eslint-config-prettier":"^8.6.0","eslint-plugin-flowtype":"^8.0.3","eslint-plugin-import":"^2.22.1","eslint-plugin-jest":"^27.2.1","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-react":"^7.32.2","eslint-plugin-react-hooks":"^4.6.0","flow-bin":"0.201.0","jest":"^29","patch-package":"^6.5.1","prettier":"^2.8.8","react":"^18.2.0","react-native":"^0.72.3","typescript":"^4.5.0"},"gitHead":"4cbcee09ad541033968e44461bdccba01b112221","_id":"@nozbe/microfuzz@0.1.5","_nodeVersion":"16.19.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-8Y8T79ZecTm+SDriRHInI7Y8U07TsUAhdJXSmJ0uqMKgAYjP6yxD+h11O1JQcPgQBJNXtM2KOjomffXDwHaKhg==","shasum":"681494ec041094370228a5a2bd4442e8688d434f","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@nozbe/microfuzz/-/microfuzz-0.1.5.tgz","fileCount":34,"unpackedSize":82384,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDueVVF44y0JvNFaNBlEuYdbpoF+9DYU2OfDuVU2sD+VAIhAI78y3jYgPrr6xFaC3l9NUAw/CEBZUz4nUJxmE6BQ8XQ"}],"size":20243},"_npmUser":{"name":"anonymous","email":"this.is@radex.io"},"directories":{},"maintainers":[{"name":"anonymous","email":"dev@nozbe.com"},{"name":"anonymous","email":"this.is@radex.io"},{"name":"anonymous","email":"tom@nozbe.com"},{"name":"anonymous","email":"gren.konrad@gmail.com"},{"name":"anonymous","email":"rozpierog@gmail.com"},{"name":"anonymous","email":"jarek@nozbe.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/microfuzz_0.1.5_1689686483182_0.5850512965022319"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2023-07-18T13:21:23.333Z","publish_time":1689686483333,"_source_registry_name":"default","contributors":[]},"1.0.0":{"name":"@nozbe/microfuzz","description":"A tiny, simple, fast fuzzy search library","version":"1.0.0","scripts":{"up":"yarn","ci:check":"concurrently -n 'test,eslint,flow,ts' -c 'auto' 'npm run test' 'npm run eslint' 'npm run flow' 'npm run ts' --kill-others-on-fail","ci":"npm run ci:check","flow":"flow check --max-warnings=0 --color=always","ts":"tsc","eslint":"eslint ./src -c ./.eslintrc.js --cache --cache-location ./.cache/.eslintcache","test":"jest","build":"rm -fr dist && babel src --out-dir dist --ignore 'src/__tests__' --copy-files --no-copy-ignored"},"keywords":["fuzzy search","command palette","jump to","autocomplete","react"],"author":{"name":"Radek Pietruszewski","email":"this.is@radex.io","url":"https://radex.io"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Nozbe/microfuzz.git"},"bugs":{"url":"https://github.com/Nozbe/microfuzz/issues"},"homepage":"https://github.com/Nozbe/microfuzz#readme","publishConfig":{"registry":"https://registry.npmjs.org/","access":"public"},"main":"dist/index.js","types":"dist/index.d.ts","devDependencies":{"@babel/cli":"^7.21.0","@babel/core":"^7.21.0","@babel/eslint-parser":"^7.19.1","@babel/plugin-transform-flow-comments":"^7.22.5","@babel/plugin-transform-react-jsx":"^7.21.0","@babel/preset-env":"^7.22.9","@typescript-eslint/eslint-plugin":"^5.53.0","@typescript-eslint/parser":"^5.53.0","chalk":"^4.1.0","chokidar-cli":"^3.0.0","concurrently":"^7.6.0","eslint":"^8.34.0","eslint-config-airbnb":"^19.0.4","eslint-config-prettier":"^8.6.0","eslint-plugin-flowtype":"^8.0.3","eslint-plugin-import":"^2.22.1","eslint-plugin-jest":"^27.2.1","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-react":"^7.32.2","eslint-plugin-react-hooks":"^4.6.0","flow-bin":"0.201.0","jest":"^29","patch-package":"^6.5.1","prettier":"^2.8.8","react":"^18.2.0","react-native":"^0.72.3","typescript":"^4.5.0"},"gitHead":"68b3d68553fdca5e8ef4147b000367f1e29594ab","_id":"@nozbe/microfuzz@1.0.0","_nodeVersion":"16.19.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-XKIg/guk+s1tkPTkHch9hfGOWgsKojT7BqSQddXTppOfVr3SWQhhTCqbgQaPTbppf9gc2kFeG0gpBZZ612UXHA==","shasum":"89a2b43d3ee9db1979e1144230253c97e838cc6a","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@nozbe/microfuzz/-/microfuzz-1.0.0.tgz","fileCount":34,"unpackedSize":82550,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqs/Cr/f6zL2tEn4ocpLb4wAguc66vUluZKMbQKmK5mgIgU2qtNHxUcTg9rLQ2tphDIVoTtEItzckZzDUcQOqdnkY="}],"size":20324},"_npmUser":{"name":"anonymous","email":"this.is@radex.io"},"directories":{},"maintainers":[{"name":"anonymous","email":"dev@nozbe.com"},{"name":"anonymous","email":"this.is@radex.io"},{"name":"anonymous","email":"tom@nozbe.com"},{"name":"anonymous","email":"gren.konrad@gmail.com"},{"name":"anonymous","email":"rozpierog@gmail.com"},{"name":"anonymous","email":"jarek@nozbe.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/microfuzz_1.0.0_1689689298301_0.4250950176821864"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2023-07-18T14:08:18.496Z","publish_time":1689689298496,"_source_registry_name":"default","contributors":[]}},"dist-tags":{"latest":"1.0.0","next":"0.1.5"},"name":"@nozbe/microfuzz","time":{"created":"2023-07-18T13:24:09.033Z","modified":"2025-06-03T08:42:30.725Z","0.1.5":"2023-07-18T13:21:23.333Z","1.0.0":"2023-07-18T14:08:18.496Z"},"readme":"<p align=\"center\">\n  <img src=\"https://github.com/Nozbe/microfuzz/raw/main/assets/nozbe_demo.gif\" alt=\"microfuzz in action in Nozbe\" width=\"624\" />\n</p>\n\n<h1 align=\"center\">\n  microfuzz\n</h1>\n\n<h4 align=\"center\">\n  A tiny, simple, fast JS fuzzy search library\n</h4>\n\n<p align=\"center\">\n  ✨ Easily add power user-friendly search, autocomplete, jump to, command palette to your app.\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/Nozbe/microfuzz/blob/master/LICENSE\">\n    <img src=\"https://img.shields.io/badge/License-MIT-blue.svg\" alt=\"MIT License\"/>\n  </a>\n\n  <a href=\"https://www.npmjs.com/package/@nozbe/microfuzz\">\n    <img src=\"https://img.shields.io/npm/v/@nozbe/microfuzz.svg\" alt=\"npm\"/>\n  </a>\n</p>\n\n|   | microfuzz |\n| - | ------------ |\n| 🤓 | **Fuzzy search**. Power users love it |\n| 🗜️ | **Tiny**. 2KB gzipped |\n| ✅ | **Simple**. Only a few options, reasonable defaults |\n| ⚡️ | **Fast**. Filter thousands of items in milliseconds |\n| 🧰 | **Framework-agnostic**. Plain JS, no dependencies |\n| ⚛️ | **React/React Native** helpers (optional) included |\n| ⚠️ | **Static typing** with [Flow](https://flow.org) or [TypeScript](https://typescriptlang.org) |\n\n## microfuzz pitch\n\nGeneral idea of how `microfuzz` works:\n\n- Case-insensitive and diacritics-insensitive search\n- Works with Latin script, Cyrillic, rudimentary CJK support\n- Limited fuzzing: matches query letters in order, but they don't have to be consecutive\n  (but transposition and missing characters are not allowed)\n- Some very poor fuzzy matches are rejected by default (see [_Fuzzy search strategies_](#fuzzy-search-strategies))\n- Additionally, matches query _words_ in any order\n- NOT full-text search. Stemming, soundex, levenstein, autocorrect are _not_ included\n- Sorts by how well text matches the query with simple heuristics (for equal fuzzy score, input\n  order is preserved, so you can pre-sort array if you want).\n- Returns ranges of matching characters for pretty highlighting\n- In-memory search, no indexing\n\n`microfuzz` is not a one-size-fits-all solution (see [_Alternatives to consider_](#alternatives-to-consider)).\n\n## Demo\n\n[**➡️ See demo**](https://nozbe.github.io/microfuzz/)\n\n## Using microfuzz (plain JS)\n\n```js\nimport createFuzzySearch from '@nozbe/microfuzz'\n\nconst list = [/* an array of strings to fuzzy search */]\nconst fuzzySearch = createFuzzySearch(list)\n\n// Run this whenever search term changes\n// Only matching items will be returned, sorted by how well they match `queryText`\nconst results = fuzzySearch(queryText)\n```\n\nThis is split into two steps for performance (`createFuzzySearch` pre-processes `list`, and you can cache/memoize function returned by it).\n\nIf `list` is an array of objects:\n\n```js\nconst fuzzySearch = createFuzzySearch(list, {\n  // search by `name` property\n  key: 'name',\n  // search by `description.text` property\n  getText: (item) => [item.description.text]\n  // search by multiple properties:\n  getText: (item) => [item.name, item.description.text]\n})\n```\n\n### Using microfuzz in React\n\nIf you use React or React Native, you can use these optional helpers for convenience:\n\n```js\nimport { useFuzzySearchList, Highlight } from '@nozbe/microfuzz/react'\n\n// `useFuzzySearchList` simply wraps `createFuzzySearch` with memoization built in\n// NOTE: For best performance, `getText` and `mapResultItem` should be memoized by user\nconst filteredList = useFuzzySearchList({\n  list,\n  // If `queryText` is blank, `list` is returned in whole\n  queryText,\n  // optional `getText` or `key`, same as with `createFuzzySearch`\n  getText: (item) => [item.name],\n  // arbitrary mapping function, takes `FuzzyResult<T>` as input\n  mapResultItem: ({ item, score, matches: [highlightRanges] }) => ({ item, highlightRanges })\n})\n\n// Render `filteredList`'s labels with matching characters highlighted\nfilteredList.map(({ item, highlightRanges }) => (\n  <Item key={item.key}>\n    <Label><Highlight text={item.name} ranges={highlightRanges} /></Label>\n  </Item>\n))\n```\n\n### Fuzzy search strategies\n\nYou can optionally pass `{ strategy: }` parameter to `createFuzzySearch` / `useFuzzySearchList`:\n\n- `'off'`        - no fuzzy search, only matches if item contains query (or contains query words in any order)\n- `'smart'`      - (default) matches letters in order, but poor quality matches are ignored\n- `'aggressive'` - matches letters in order with no restrictions (classic fuzzy search)\n\n## Alternatives to consider\n\nI wrote `microfuzz` simply because I didn't quite like how other fuzzy search libraries I found worked, **for my use case**. Your mileage may vary.\n\nIt's not the tiniest, the simplest, or the fastest implementation you can find. But it's tiny, simple, and fast enough, while providing fuzzy search heuristics and sorting that I found to work reasonably well in [Nozbe](https://nozbe.com), a project management app, where it's used to filter down or autocomplete lists of short labels — names of projects, sections, tasks, user names, etc.\n\nBy \"fast\" I mean that on my computer, with a list of ~4500 labels, the first search (one-letter search query) takes ~7ms, while subsequent searches take less than 1.5ms — all in-memory, without indexing. More than fast enough to search on every keystroke without any lag.\n\nIf you have much larger lists to fuzzy-search, you may find the performance unsatisfactory — consider implementations with simpler heuristics or indexing. For very long strings (notes, comments), fuzzy-searching may not be the right strategy — consider Full-Text Search (with indexing) instead.\n\nFeel free to contribute improvements to sorting heuristics or alternative search strategies (provided that the \"fast, simple, tiny\" criteria don't suffer too much).\n\nAlternatives:\n\n- [Fuse.js](https://github.com/krisk/Fuse) - popular implementation with **many more options**, including extended search and indexing. However, while its scoring (sorting) is much more sophisticated in theory, I found it unsatisfactory in practice.\n- [fuzzysort](https://github.com/farzher/fuzzysort) - faster and really good for fuzzy searching lists of file names/file paths, but I don't like its scoring for natural language labels. I borrowed the test data from fuzzysort so you can compare both demos side by side.\n- [MiniSearch](https://www.npmjs.com/package/minisearch)\n- [fuzzy](https://github.com/mattyork/fuzzy)\n- [fuzzy-search](https://github.com/wouterrutgers/fuzzy-search) - an even simpler implementation than microfuzz\n- [fuzzysearch](https://github.com/bevacqua/fuzzysearch) - tiniest implementation of the list\n\n## Author and license\n\n**microfuzz** was created by [@Nozbe](https://github.com/Nozbe).\n\n**microfuzz's** main author and maintainer is [Radek Pietruszewski](https://github.com/radex) ([website](https://radex.io) ⋅ [twitter](https://twitter.com/radexp) ⋅ [engineering posters](https://beamvalley.com))\n\n[See all contributors](https://github.com/Nozbe/microfuzz/graphs/contributors).\n\nmicrofuzz is available under the MIT license. See the [LICENSE file](https://github.com/Nozbe/microfuzz/LICENSE) for more info.","users":{}}