Files
awesome-awesomeness/html/tinyjs.md2.html
2025-07-18 23:13:11 +02:00

508 lines
25 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<h1 id="awesome-tiny-js-awesome">Awesome Tiny JS <a
href="https://awesome.re"><img src="https://awesome.re/badge-flat.svg"
alt="Awesome" /></a></h1>
<div data-align="center">
<p><a href="https://github.com/thoughtspile/awesome-tiny-js#readme">
<img src="./awesome-logo.png" width="300" height="207"> </a></p>
</div>
<p>Tiny front-end libraries to put your bundle on a diet. Rules:</p>
<ul>
<li>Size is under 2 kB-ish, min + gzip, with all dependencies, except
where noted.</li>
<li>For multi-purpose libraries, the size of a useful subset must be
under 2 kB-ish.</li>
<li>Useful client-side. I havent figured out participation rules for
node-only libraries, and Im not too worried about them.</li>
<li>Second-level libraries only allowed for React, Vue, Angular,
svelte.</li>
<li>100+ GitHub stars <em>or</em> 500+ weekly npm installs to focus on
tools with some community review.</li>
<li>No zero-JS (CSS- or type-only) libraries. Its not awesome-css or
something.</li>
</ul>
<h2 id="contents">Contents</h2>
<ul>
<li><a href="#ui-frameworks">UI Frameworks</a></li>
<li><a href="#event-emitters">Event Emitters</a></li>
<li><a href="#state-managers">State Managers</a>
<ul>
<li><a href="#signals">Signals</a></li>
<li><a href="#reactive-programming">Reactive Programming</a></li>
</ul></li>
<li><a href="#routers-and-url-utils">Routers and URL Utils</a></li>
<li><a href="#api-layer">API Layer</a></li>
<li><a href="#i18n">I18N</a></li>
<li><a href="#dates-and-time">Dates and Time</a></li>
<li><a href="#generic-utilities">Generic Utilities</a></li>
<li><a href="#validation">Validation</a></li>
<li><a href="#unique-id-generation">Unique ID Generation</a></li>
<li><a href="#colors">Colors</a></li>
<li><a href="#touch-gestures">Touch Gestures</a></li>
<li><a href="#text-search">Text Search</a></li>
</ul>
<h2 id="ui-frameworks">UI Frameworks</h2>
<p>UI frameworks (libraries?) provide declarative templates, event
bindings, and observable state to update the view. Ive been generous
and expanded the size limit for this category to 4.5 kB (if youre
boring, count them as 2 libraries), but also increased the star limit to
2K.</p>
<ul>
<li><a href="https://github.com/preactjs/preact">preact</a> - React-like
API (pre-hooks). Cool ecosystem of similarly tiny tools and components.
Highly recommended.
<img align="top" height="24" src="./img/preact.svg"></li>
</ul>
<p>The following libraries are small and cool, but note theyre about <a
href="https://npmtrends.com/preact-vs-hyperapp-vs-redom">500x less
popular than preact.</a> Kudos for deconstrucing the very essence of a
“framework”:</p>
<ul>
<li><a href="https://github.com/jorgebucaran/hyperapp">hyperapp</a> -
vDOM framework with pure JS syntax and immutable state,
<img align="top" height="24" src="./img/hyperapp.svg"></li>
<li><a href="https://github.com/redom/redom">redom</a> - Hyperapp-style
templates with <em>imperative</em> event listeners and updates,
<img align="top" height="24" src="./img/redom.svg"></li>
</ul>
<p>Now, for the <a
href="https://npmtrends.com/@arrow-js/core-vs-fre-vs-hyperapp-vs-redom-vs-superfine-vs-vanjs-core">openly
experimental</a> UI libraries:</p>
<ul>
<li><a href="https://github.com/frejs/fre">fre</a> - React-like library
with hooks and concurrency,
<img align="top" height="24" src="./img/fre.svg"></li>
<li><a href="https://github.com/vanjs-org/van">van</a> - vDOM-based
framework optimized for no-build setups,
<img align="top" height="24" src="./img/vanjs-core.svg"></li>
<li><a href="https://github.com/jorgebucaran/superfine">superfine</a> -
Hyperapp with state &amp; effect hooks removed,
<img align="top" height="24" src="./img/superfine.svg"></li>
<li><a href="https://github.com/justin-schroeder/arrow-js">arrowjs</a> -
Tagged templates + reactive data,
<img align="top" height="24" src="./img/arrow-jscore.svg"></li>
</ul>
<p>And if being declarative is not your thing:</p>
<ul>
<li><a href="https://github.com/franciscop/umbrella">umbrella</a> -
jQuery-style DOM manipulation library,
<img align="top" height="24" src="./img/umbrellajs.svg"></li>
</ul>
<h2 id="event-emitters">Event Emitters</h2>
<p>Event emitter pattern is fairly easy to implement yourself, but why
bother when you have these cool tools? With an arms race to build the
smallest one, the limit is 0.5 kB.</p>
<ul>
<li><a href="https://github.com/developit/mitt">mitt</a> - Plain event
emitter that I use on most projects,
<img align="top" height="24" src="./img/mitt.svg"></li>
<li><a href="https://github.com/ai/nanoevents">nanoevents</a> - Nicer
unsubscribe API, but no <code>*</code> event,
<img align="top" height="24" src="./img/nanoevents.svg"></li>
<li><a href="https://github.com/hustcc/onfire.js">onfire.js</a> - Also
has <code>.once</code> method,
<img align="top" height="24" src="./img/onfirejs.svg"></li>
</ul>
<h2 id="state-managers">State Managers</h2>
<p>State managers combine observable state with actions and framework
bindings, intended for app-wide state.</p>
<ul>
<li><a href="https://github.com/pmndrs/zustand">zustand</a> - Simple
stores with pleasant actions and selectors. Vanilla
<img align="top" height="24" src="./img/zustandvanilla.svg">, React
<img align="top" height="24" src="./img/zustand.svg"></li>
<li><a href="https://github.com/nanostores/nanostores">nanostores</a> -
Modular store with good tree-shaking support,
<img align="top" height="24" src="./img/nanostores.svg"> vanilla, +
React <img align="top" height="24" src="./img/nanostoresreact.svg">
extra. Supports all the top frameworks.</li>
<li><a href="https://github.com/marcisbee/exome">exome</a> - Atomic
stores with lots of framework connectors,
<img align="top" height="24" src="./img/exome.svg"> + React
<img align="top" height="24" src="./img/exomereact.svg"> extra. Supports
all the top frameworks.</li>
<li><a href="https://github.com/storeon/storeon">storeon</a> - Minimal
redux-styled store with lots of framework connectors,
<img align="top" height="24" src="./img/storeon.svg">. React extra
<img align="top" height="24" src="./img/storeonreact.svg"> + Vue,
Svelte, Angular.</li>
<li><a href="https://github.com/developit/unistore">unistore</a> -
Centralized store with actions,
<img align="top" height="24" src="./img/unistore.svg"> + React
<img align="top" height="24" src="./img/unistorereact.svg"></li>
<li><a href="https://github.com/teafuljs/teaful">teaful</a> - Store with
useState-like API, <img align="top" height="24" src="./img/teaful.svg">,
including React / preact connector.</li>
</ul>
<h3 id="signals">Signals</h3>
<p>A signal-styled state manager provides observable values (aka
<em>signals</em>), derived values and effects.</p>
<ul>
<li><a href="https://github.com/preactjs/signals"><span class="citation"
data-cites="preact/signals">@preact/signals</span></a> - The OG signals
from preact
<img align="top" height="24" src="./img/preactsignals-core.svg"> core,
<img align="top" height="24" src="./img/preactsignals-react.svg"> with
react integration.</li>
<li><a href="https://github.com/WebReflection/usignal">usignal</a> - A
smaller signal implementation,
<img align="top" height="24" src="./img/usignal.svg"></li>
<li><a href="https://github.com/elbywan/hyperactiv">hyperactiv</a> - 4
functions to make objects observable and listen to changes,
<img align="top" height="24" src="./img/hyperactiv.svg"></li>
<li><a href="https://github.com/fabiospampinato/flimsy">flimsy</a> -
Signals from Solid (it <em>almost</em> fit into UI frameworks category
itself). Author warning: <em>its probably buggy.</em>
<img align="top" height="24" src="./img/flimsy.svg"></li>
</ul>
<p>Honorable mention: <a href="https://github.com/vobyjs/oby">oby</a>
<em>could</em> make it <em>if</em> it had tree-shaking, but otherwise is
around 7 kB.</p>
<h3 id="reactive-programming">Reactive Programming</h3>
<p>Another well-known state management approach is reactive programmning
— operating on event streams, applying filters and transforms to end up
with an observable value. Think RxJS, but tiny:</p>
<ul>
<li><a href="https://github.com/paldepind/flyd">flyd</a> - Rx-styled
event streams, <img align="top" height="24" src="./img/flyd.svg"></li>
<li><a
href="https://github.com/staltz/callbag-basics">callbag-basics</a> -
Rx-style event streams,
<img align="top" height="24" src="./img/callbag-basics.svg"></li>
</ul>
<h2 id="routers-and-url-utils">Routers and URL Utils</h2>
<p>Do stuff on URL / history changes, with path matching and
parsing:</p>
<ul>
<li><a href="https://github.com/molefrog/wouter">wouter</a> -
Declarative router for React / preact,
<img align="top" height="24" src="./img/wouter.svg">, also available as
a standalone hook:
<img align="top" height="24" src="./img/wouteruse-browser-location.svg"></li>
<li><a href="https://github.com/nanostores/router"><span
class="citation"
data-cites="nanostores/router">@nanostores/router</span></a> - Routes as
a nanostores store (framework-agnostic),
<img align="top" height="24" src="./img/nanostoresrouter.svg"></li>
<li><a href="https://github.com/lukeed/navaid">navaid</a> -
History-based observable router,
<img align="top" height="24" src="./img/navaid.svg"></li>
</ul>
<p>Just want to parse or match URL paths without observing them? Here
you go:</p>
<ul>
<li><a href="https://github.com/lukeed/matchit">matchit</a> - Route
parser and matcher in
<img align="top" height="24" src="./img/matchit.svg"></li>
<li><a href="https://github.com/lukeed/regexparam">regexparam</a> -
Convert path to regexp in
<img align="top" height="24" src="./img/regexparam.svg"></li>
<li><a href="https://github.com/lukeed/qss">qss</a> - Parse querystrings
in <img align="top" height="24" src="./img/qss.svg">. Not sure you need
it, <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL">URL
API</a> support is good.</li>
</ul>
<h2 id="api-layer">API Layer</h2>
<p><code>fetch</code> API has some boilerplate associated with it:
serialize &amp; parse data, reject on non-200 response, etc. These tiny
packages handle it for you:</p>
<ul>
<li><a href="https://github.com/developit/redaxios">redaxios</a> -
Drop-in axios replacement for modern browsers,
<img align="top" height="24" src="./img/redaxios.svg"></li>
<li><a href="https://github.com/elbywan/wretch">wretch</a> - Chainable
API with error processing and lots of extra plugins,
<img align="top" height="24" src="./img/wretch.svg"></li>
<li><a href="https://github.com/truework/gretchen">gretchen</a> -
Chainable API with type-safe errors,
<img align="top" height="24" src="./img/gretchen.svg"></li>
</ul>
<p>If for some reason you still need a fetch polyfill, try this one:</p>
<ul>
<li><a href="https://github.com/developit/unfetch">unfetch</a> - Loose
fetch polyfill,
<img align="top" height="24" src="./img/unfetch.svg"></li>
</ul>
<h2 id="i18n">I18N</h2>
<p>A map of strings might seem enough to translate an app, but these
tools also handle interpolation and some extra goodies:</p>
<ul>
<li><a href="https://github.com/nanostores/i18n"><span class="citation"
data-cites="nanostores/i18n">@nanostores/i18n</span></a> - Detect
locale, load dictionaries, format dates / numbers,
<img align="top" height="24" src="./img/nanostoresin.svg"> including
nanostores.</li>
<li><a href="https://github.com/ibitcy/eo-locale">eo-locale</a> -
Interpolation and dates / numbers,
<img align="top" height="24" src="./img/eo-localecore.svg">, or
<img align="top" height="24" src="./img/eo-localereact.svg"> with react
bindings.</li>
<li><a href="https://github.com/lukeed/rosetta">rosetta</a> - Bare-bones
template strings (<code>{{hello}}, {{username}}</code>) and custom
functions for everyting else,
<img align="top" height="24" src="./img/rosetta.svg"></li>
<li><a href="https://github.com/lingui/js-lingui">lingui</a> - Small
core with template strings,
<img align="top" height="24" src="./img/linguicore.svg"></li>
</ul>
<h2 id="dates-and-time">Dates and Time</h2>
<p>Date and time manipulation in pure JS is verbose. Luckily, two of the
top date libraries have sensible size:</p>
<ul>
<li><a href="https://github.com/date-fns/date-fns/">date-fns</a> - Not
tiny as a whole, but <a
href="https://bundlephobia.com/package/date-fns">most functions</a> are
under 1 kB each (format and parse are quite heavy).</li>
<li><a href="https://github.com/iamkun/dayjs">dayjs</a> -
<em>Almost</em> moment.js-compatible API, covers most use cases,
<img align="top" height="24" src="./img/dayjsesm.svg"></li>
</ul>
<p>And some more packages that only do formatting:</p>
<ul>
<li><a href="https://github.com/aweary/tinytime">tinytime</a> - Simple
date / time formatter: <code>{h}:{mm} -&gt; 9:33</code>,
<img align="top" height="24" src="./img/tinytime.svg"></li>
<li><a href="https://github.com/lukeed/tinydate">tinydate</a> - Date /
time formatter, only supports padded numeric output
(<code>September -&gt; 09</code>),
<img align="top" height="24" src="./img/tinydate.svg"></li>
<li><a href="https://github.com/jonschlinkert/time-stamp">time-stamp</a>
- More of the same,
<img align="top" height="24" src="./img/time-stamp.svg"></li>
<li><a href="https://github.com/vercel/ms">ms</a> - Parse &amp; format
ms durations, e.g. <code>"1m" &lt;-&gt; 60000</code>,
<img align="top" height="24" src="./img/ms.svg"></li>
<li><a href="https://github.com/hustcc/timeago.js">timeago.js</a> -
Format dates into stuff like <em>X minutes ago</em> or <em>in X
hours,</em> <img align="top" height="24" src="./img/timeagojs.svg"></li>
<li><a href="https://github.com/lukeed/fromnow">fromnow</a> - More of
the same, <img align="top" height="24" src="./img/fromnow.svg"></li>
</ul>
<p>Note that the built-in <a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat"><code>Intl.DateTimeFormat</code></a>
has decent support.</p>
<h2 id="generic-utilities">Generic Utilities</h2>
<p>Something youd find in lodash or ramda, but smaller. Most are pretty
similar and very small, with minor differences in package structure
(single / package-per-helper) and tree shaking vs direct helper
import.</p>
<ul>
<li><a href="https://github.com/remeda/remeda">remeda</a> - 90
tree-shakable helpers <a
href="https://bundlephobia.com/package/remeda">(list).</a></li>
<li><a href="https://github.com/selfrefactor/rambda">rambda</a> - 187
tree-shakable helpers <a
href="https://bundlephobia.com/package/rambda">(list).</a></li>
<li><a href="https://github.com/angus-c/just">just</a> - 82 helpers in
separate packages <a
href="https://anguscroll.com/just/">(list).</a></li>
<li><a href="https://github.com/marpple/FxTS"><span class="citation"
data-cites="fxts/core">@fxts/core</span></a> - 96 tree-shakable helpers.
Lazy evaluation support.</li>
</ul>
<p>Honorable mention: <a
href="https://github.com/jashkenas/underscore">underscore,</a> contains
many sub-1 kB helpers. It does not tree-shake as well as the libraries
above due to codebase structure.</p>
<p>Note: lodash itself is not tree-shakable, but has made many attempts
at modulaity with <code>lodash.method</code> packages, imports from
<code>lodash/method</code>, and <code>lodash-es</code>, none of which
work well in practice.</p>
<p>Also note that much of the original lodash functionality comes
built-in with modern ES. Prefer native versions over libraries as your
browser target allows.</p>
<h2 id="validation">Validation</h2>
<p>To check if an object matches an expected schema, youd often use
zod, yup, joi or ajv. But 90% of the time you can get what you need in
under 2 kB. <em>Note:</em> I compare a base validation subset (core +
object / array + string / number / boolean) under tree-shaking to avoid
punishing libs that have more features.</p>
<ul>
<li><a href="https://github.com/imbrn/v8n">v8n</a> - zod-style API with
fine-grained checks:
<code>v8n().string().minLength(5).first("H").last("o")</code>. No tree
shaking, <img align="top" height="24" src="./img/vn.svg"></li>
<li><a href="https://github.com/thoughtspile/banditypes">banditypes</a>
- The smallest validation library:
<img align="top" height="24" src="./img/banditypes.svg"></li>
<li><a
href="https://github.com/ianstormtaylor/superstruct">superstruct</a> -
The most popular modular validation library with good tree-shaking,
<img align="top" height="24" src="./img/superstruct.svg"></li>
<li><a href="https://github.com/fabian-hiller/valibot">valibot</a> -
Another modular validation library,
<img align="top" height="24" src="./img/valibot.svg"></li>
<li><a href="https://github.com/antonioru/deep-waters">deep-waters</a> -
Composable functional validators,
<img align="top" height="24" src="./img/deep-waterscompose-deep-watershasShape-deep-watersarrayOf-deep-watersisString-deep-watersisNumber-deep-watersisBoolean.svg">.</li>
</ul>
<h2 id="unique-id-generation">Unique ID Generation</h2>
<p>Unique ID generation does not take a lot of code, but its not
someting Id want to write myself. Limit is 500 bytes. Also note that
the <a
href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID">native
<code>crypto.randomUUID</code></a> has <a
href="https://caniuse.com/mdn-api_crypto_randomuuid">OK support.</a></p>
<ul>
<li><a href="https://github.com/lukeed/uuid"><span class="citation"
data-cites="lukeed/uuid">@lukeed/uuid</span></a> - Real UUIDs,
<img align="top" height="24" src="./img/lukeeduuid.svg"></li>
<li><a href="https://github.com/ai/nanoid">nanoid</a> - Random IDs with
larger alphabet,
<img align="top" height="24" src="./img/nanoid.svg"></li>
<li><a href="https://github.com/lukeed/uid">uid</a> - More of the same,
<img align="top" height="24" src="./img/uid.svg"></li>
<li><a href="https://github.com/lukeed/hexoid">hexoid</a> - Hexadecimal
IDs, <img align="top" height="24" src="./img/hexoid.svg"></li>
</ul>
<h2 id="colors">Colors</h2>
<p>Color manipulation is rare in pure UI development, but very helpful
for data visualization, and uses <a
href="https://en.wikipedia.org/wiki/HSL_and_HSV#Color_conversion_formulae">freaky
math.</a> Dont fry your brain, take these:</p>
<ul>
<li><a href="https://github.com/omgovich/colord">colord</a> - Manipulate
colors and convert between spaces,
<img align="top" height="24" src="./img/colord.svg">. Extra features
come as plugins, 150b to 1.5 kB each.</li>
<li><a href="https://github.com/stayradiated/colr">colr</a> - More of
the same, <img align="top" height="24" src="./img/colr.svg" ></li>
<li><a href="https://github.com/cdonohue/polychrome">polychrome</a> -
More of the same,
<img align="top" height="24" src="./img/polychrome.svg"></li>
<li><a
href="https://github.com/davidmerfield/randomColor">randomcolor</a> -
Attractive random colors with configuration.
<img align="top" height="24" src="./img/randomcolor.svg"></li>
</ul>
<h2 id="touch-gestures">Touch Gestures</h2>
<p>Touch gestures like swipe, drag, pinch or doubletap are a staple of
mobile UX, but recognizing a series of touchmove / pointer events as a
gesture is tricky, and testing is painful. Here are two libraries that
do the heavy lifting for you:</p>
<ul>
<li><a href="https://github.com/AlloyTeam/AlloyFinger">alloyfinger</a> -
Pan, swipe, tap, doubletap, longpress, <em>and</em> pinch / rotate. My
personal favorite.
<img align="top" height="24" src="./img/alloyfinger.svg">.</li>
<li><a href="https://github.com/sciactive/tinygesture">tinygesture</a> -
Configurable pan, swipe, tap, doubletap, longpress.
<img align="top" height="24" src="./img/tinygesture.svg">.</li>
</ul>
<p>Even if you want to detect gestures yourself, juggling mouse, touch
and pointer events is hard enough, and browser inconsistencies dont
help. Here are two more libraries to assist with that:</p>
<ul>
<li><a
href="https://github.com/GoogleChromeLabs/pointer-tracker">pointer-tracker</a>
- Unified interface for mouse, touch and pointer events,
<img align="top" height="24" src="./img/pointer-tracker.svg"></li>
<li><a href="https://github.com/rafgraph/detect-it">detect-it</a> -
Detect present and primary input method (touch / mouse) and supported
events, <img align="top" height="24" src="./img/detect-it.svg"></li>
</ul>
<p>Honorable mentions: <a
href="https://github.com/any86/any-touch">any-touch</a> attempts a
modular approach to gesture detection, but the core is around 2 kB
without any gesture recognizers. <a
href="https://github.com/react-component/gesture">rc-gesture,</a> used
in ant design system, could be the only react component on the list, but
babel-runtime / corejs polyfills hard-wired into the build push the ~2.5
kB size to over 10 kB.</p>
<h2 id="text-search">Text Search</h2>
<p>Text search is important for client-side filtering and autosuggests.
Naive <code>option.includes(search)</code> has no sensible order on the
results, and ignoring word boundaries gives unexpected matches like
<em>spa -&gt; newSPAper.</em> First, here are some libraries that
prioritize word matches:</p>
<ul>
<li><a href="https://github.com/bvaughn/js-search">js-search</a> -
Feature-rich and customizable: multi-field indices, stop words, custom
stemmers and tokenizers.
<img align="top" height="24" src="./img/js-search.svg"></li>
<li><a href="https://github.com/localvoid/ndx">ndx</a> - Similar to
js-search, differs in <a
href="https://kmwllc.com/index.php/2020/03/20/understanding-tf-idf-and-bm-25/">ranking</a>
and is less strict for multi-word queries <a
href="https://leeoniya.github.io/uFuzzy/demos/compare.html?libs=js-search,ndx,Wade&amp;search=twilight%20sag">(compare)</a>.
Supports field weights.
<img align="top" height="24" src="./img/ndx-ndxquery.svg"></li>
<li><a href="https://github.com/kbrsh/wade">wade</a> - Also similar, <a
href="https://leeoniya.github.io/uFuzzy/demos/compare.html?libs=js-search,Wade,ndx&amp;search=twilight%20sag">(compare)</a>
<img align="top" height="24" src="./img/wade.svg"></li>
<li><a href="https://github.com/thesephist/libsearch">libsearch</a> -
Index-free search (slower, but easier to use) with sane ordering
<img align="top" height="24" src="./img/libsearch.svg"></li>
</ul>
<p>One way to find sensible inexact matches is <em>stemming</em>
converting words to a root form. <em>Walked</em> will match
<em>walking,</em> etc. Here are a few <a
href="https://vijinimallawaarachchi.com/2017/05/09/porter-stemming-algorithm/">Porter
stemmers</a> for English language:</p>
<ul>
<li><a href="https://github.com/words/stemmer">stemmer</a> -
<img align="top" height="24" src="./img/stemmer.svg"></li>
<li><a href="https://github.com/jedp/porter-stemmer">porter-stemmer</a>
- <img align="top" height="24" src="./img/porter-stemmer.svg"></li>
</ul>
<p>For non-English words, I only have honorable mentions: <a
href="https://github.com/fortnightlabs/snowball-js">snowball-js</a> is
17 kB with 15 languages, <a
href="https://github.com/MihaiValentin/lunr-languages">lunr-languages</a>
supports 30 languages but only works with <a
href="https://github.com/olivernn/lunr.js">lunr,</a> the most promising
one is <a
href="https://github.com/NaturalNode/natural/tree/master/lib/natural/stemmers">natural</a>
but it depends on Node.js.</p>
<h3 id="fuzzy-search">Fuzzy search</h3>
<p><strong>Fuzzy search</strong> is another take on inexact matching —
the words can be modified. First, we have libraries that only allow
insertion: spacecat -&gt; SPACECrAfT. Not perfect for general-purpose
text search, but great for filename, command, or URL lookups.</p>
<ul>
<li><a href="https://github.com/mattyork/fuzzy">fuzzy</a> - Index-free,
can highlight matches.
<img align="top" height="24" src="./img/fuzzy.svg"></li>
<li><a
href="https://github.com/wouterrutgers/fuzzy-search">fuzzy-search</a> -
With stateful index.
<img align="top" height="24" src="./img/fuzzy-search.svg"></li>
<li><a href="https://github.com/jhawthorn/fzy.js">fzy.js</a> - Matches
one string at a time, tree-shakeable scores and match highlighting.
<img align="top" height="24" src="./img/fzyjs.svg"> total, or ~150 bytes
for <code>hasMatch</code> only.</li>
<li><a href="https://github.com/bevacqua/fuzzysearch">fuzzysearch</a> -
One string at a time, does not compute score / rank.
<img align="top" height="24" src="./img/fuzzysearch.svg"></li>
<li><a href="https://github.com/rmm5t/liquidmetal">liquidmetal</a> -
Quicksilver algorithm, prioritizes matches at start of word for command
abbreviations (e.g. <code>gp</code> -&gt; <code>git push</code>). One
string at a time.
<img align="top" height="24" src="./img/liquidmetal.svg"></li>
<li><a
href="https://github.com/fwextensions/quick-score">quick-score</a> -
Another quicksilver-based lib, tweaked for long strings. Built-in list
filtering and sorting,
<img align="top" height="24" src="./img/quick-score.svg"> or 1.2 kB for
single-string scoring.</li>
</ul>
<p>Finally, one library is specifically built for spellchecking:</p>
<ul>
<li><a href="https://github.com/Glench/fuzzyset.js">fuzzyset</a> - Find
misspellings, e.g. missipissi -&gt; Missisipi,
<img align="top" height="24" src="./img/fuzzyset.svg"> Commercial usage
costs $42.</li>
</ul>
<h2 id="contributing">Contributing</h2>
<p>Suggestions welcome! See <a
href="contributing.md">contributing.md</a>, or drop an <a
href="https://github.com/thoughtspile/awesome-tiny-js/issues">issue</a>.</p>
<h2 id="footnotes">Footnotes</h2>
<p>See <a href="wip.md">WIP</a> for possibly awesome libraries I have
found, but not yet analyzed deeply, and <a
href="incubate.md">incubate</a> for awesome libraries that dont meet
popularity criteria yet.</p>
<p>Collected and reviewed by <a
href="https://blog.thoughtspile.tech">Vladimir Klepov</a> in 2023.</p>
<p><a href="https://github.com/thoughtspile/awesome-tiny-js">tinyjs.md
Github</a></p>