npm.io
0.3.1 • Published yesterday

@codejoo/ffuzzy

Licence
MIT
Version
0.3.1
Deps
0
Size
123 kB
Vulns
0
Weekly
0

@codejoo/ffuzzy

Fast fuzzy search for the web — a WASM port of the ffuzzy C engine.

Five search modes · TypeScript · browser + Node · ~57 KB full / ~43 KB lite

Install

npm install @codejoo/ffuzzy

Quick start

import ffuzzyModule, { FuzzyCorpus } from '@codejoo/ffuzzy';

const M = await ffuzzyModule();

// Plain strings
const corpus = FuzzyCorpus.strings(M, ['src/main.ts', 'README.md', 'package.json']);
corpus.fuzzy('src').forEach(h => console.log(h.obj, h.score));
corpus.dispose();

// Generic objects — hits carry the original object
const files = new FuzzyCorpus(M, myFiles, { stringOf: f => f.path });
const hit = files.prefix('src/')[0];
hit.obj;  // original object
files.dispose();

Lite build

~14 KB smaller; covers ASCII + CJK. No Cyrillic/Greek case-fold or accent-strip.

import ffuzzyModuleLite, { FuzzyCorpus } from '@codejoo/ffuzzy/lite';

const M = await ffuzzyModuleLite();

Search modes

All modes accept an optional second argument to override corpus defaults.

corpus.fuzzy    ('src m')   // subsequence — supports ! ^ ' $ operators
corpus.substring('src/')    // contiguous substring
corpus.prefix   ('src/')    // must start with query
corpus.postfix  ('.ts')     // must end with query
corpus.exact    ('main.ts') // whole-string match

Options

import { FuzzyCorpus, FuzzyCase, FuzzyNorm } from '@codejoo/ffuzzy';

const corpus = new FuzzyCorpus(M, items, {
  stringOf: item => item.name,
  options: {
    caseMatching: FuzzyCase.smart,    // 0 respect · 1 ignore · 2 smart (default)
    normalization: FuzzyNorm.smart,   // 0 never · 1 smart/accent-strip (default)
    limit: 50,                        // max results (0 = unlimited)
    highlight: true,                  // populate FuzzyHit.indices
  },
  matchPaths: false,   // treat '/' as path separator
  preferPrefix: false, // bias toward prefix matches
});

Per-call overrides:

corpus.fuzzy('query', { limit: 10, caseMatching: FuzzyCase.respect });

Multi-key search (pinyin / romaji)

import { FuzzyCorpus, FuzzyKey, FuzzyKeyKind } from '@codejoo/ffuzzy';

corpus.addKeyed(item, [
  FuzzyKey.kind('zhongguo', FuzzyKeyKind.pinyin),
  FuzzyKey.kind('zg',       FuzzyKeyKind.initials),
]);

Hit highlighting

FuzzyHit.indices contains codepoint positions. Convert to UTF-16 before applying to DOM:

import { fuzzyCodepointToUtf16 } from '@codejoo/ffuzzy';

const hit = corpus.fuzzy('src')[0];
const u16 = fuzzyCodepointToUtf16(hit.obj, hit.indices);
// apply u16 offsets to DOM Range / highlight API

using statement

using corpus = FuzzyCorpus.strings(M, items); // auto-disposed at scope exit

FuzzyHit shape

interface FuzzyHit<T> {
  obj:         T;        // original item
  index:       number;   // insertion index in corpus
  score:       number;   // higher = better; only comparable within one query
  matchedKind: number;   // FuzzyKeyKind of the matched key
  matchedKey:  number;   // key index within the item
  indices:     number[]; // matched codepoint positions (empty if highlight:false)
}

Build from source

The .js files are generated by Emscripten. Requires emsdk on PATH:

bash scripts/build-wasm.sh   # from repo root
# or from wasm/ directory:
npm run build

License

MIT

Keywords