update
This commit is contained in:
507
html/tinyjs.md2.html
Normal file
507
html/tinyjs.md2.html
Normal file
@@ -0,0 +1,507 @@
|
||||
<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 haven’t figured out participation rules for
|
||||
node-only libraries, and I’m 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. It’s 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. I’ve been generous
|
||||
and expanded the size limit for this category to 4.5 kB (if you’re
|
||||
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 they’re 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 & 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>it’s 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 & 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} -> 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 -> 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 & format
|
||||
ms durations, e.g. <code>"1m" <-> 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 you’d 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, you’d 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 it’s not
|
||||
someting I’d 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> Don’t 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 don’t
|
||||
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 -> 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&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&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 -> 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> -> <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 -> 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 don’t 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>
|
||||
Reference in New Issue
Block a user