Aho–Corasick multi‑pattern string matcher for Node and the browser. Typed, isomorphic, and overlap‑aware.
import { build } from 'tiny-aho-corasick';
const ac = build(['he', 'she', 'his', 'hers']);
const hits = ac.search('ushers');
console.log(hits);
/*
[
{ start: 1, end: 4, index: 1, pattern: 'she', payload: 1 },
{ start: 2, end: 4, index: 0, pattern: 'he', payload: 0 },
{ start: 2, end: 6, index: 3, pattern: 'hers', payload: 3 },
]
*/
// grab the matched substrings
console.log(hits.map(m => 'ushers'.slice(m.start, m.end))); // [ 'she', 'he', 'hers' ]With payloads and ignoreCase:
import { build } from 'tiny-aho-corasick';
type Info = { kind: 'animal' | 'vehicle' };
const ac = build<Info>(
[
['Cat', { kind: 'animal' }],
['car', { kind: 'vehicle' }],
],
{ ignoreCase: true }
);
for (const m of ac.matchAll('A CAT in a car')) {
console.log(m.pattern, m.payload.kind, m.start, m.end);
}
// Cat animal 2 5
// car vehicle 11 14build(patterns, options?): Matcher<number>
patterns: readonly string[]- Returns a matcher where
payloadis the pattern index (0‑based).
build<T>(patterns, options?): Matcher<T>
patterns: readonly [string, T][]- Returns a matcher where
payloadis yourT.
AhoOptions
ignoreCase?: boolean- If
true, patterns and text are lower‑cased internally before building/searching.
- If
Matcher
matchAll(text: string): IterableIterator<Match<T>>- Lazily yields all matches, including overlaps.
search(text: string): Match<T>[]- Collects all matches into an array.
test(text: string): boolean- Returns
trueif there is at least one match.
- Returns
Match
start: numberend: numberindex: number- Index of the pattern in the input list.
pattern: string- Original (non‑normalized) pattern string you provided.
payload: T
MIT