npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

yake-ts

v1.2.5

Published

Tiny, dependency-free YAKE keyword extractor — no classes, no caching, one pure function. English bundled, 33 more languages as opt-in imports.

Readme

yake-ts

npm version types CI license

Text in, ranked keywords out. 🔑

yake-ts implements YAKE — an unsupervised keyword extractor that scores candidate phrases from statistics of one document alone: word frequency, casing, position, spread across sentences, and co-occurrence. No model, no corpus, no training, no network call.

import { extractKeywords } from "yake-ts";

extractKeywords("fix flaky auth test in login flow")[0].keyword;
// "fix flaky auth"

One function, zero runtime dependencies, 5.7 kB

gzipped including the English stopword list. 33 more languages are separate imports you only pay for if you use them.

Code snippets, the API tables, the language list, and the bundle size above are generated from the real source/build output, not typed by hand — see scripts/docs/sync-readme.ts.

Picking a package

Several JS keyword extractors exist and they solve genuinely different problems:

| Package | What you get | What it costs | | --- | --- | --- | | yake-ts | YAKE scores from a single call; English inline, 33 languages opt-in; ESM, edge/browser-safe | young and unproven; Levenshtein-only dedup; no CJK segmentation | | @ade_oshineye/yaket | the same algorithm, plus scorer/tokenizer hooks, CLI, highlighter, Bobbin adapter, Python-parity + Cloudflare test lanes, benchmarks | ~370 kB unpacked, all 34 stopword sets reachable through one API; Node 20+; a much bigger API to learn | | yake-wasm | YAKE in Rust/WASM; fast on long documents; drops n-gram substrings so "data science" wins over "data" | a WASM init step in your bundler; stopwords are English-only and not configurable; last published 2022 | | retext-keywords | part-of-speech-aware keywords and keyphrases inside a unified pipeline | needs unified + retext + retext-pos; ~5 dependencies; results come back as stems on a vfile | | keyword-extractor | stopword removal in 20 languages, battle-tested (~220k downloads/week) | no ranking — you get a filtered word list, not keywords ordered by importance |

Short version: keyword-extractor if you only need stopwords gone, retext-keywords if you are already in the unified ecosystem, yaket if you need the extension points or upstream parity, yake-ts if you want YAKE's ranking in the smallest possible bundle with one import.

For POS tagging, NER, or CJK word segmentation, use a real NLP stack (spaCy, wink-nlp) — none of the above do that.

What's new

| Version | Highlights | | ------- | ---------- | | 1.2.0 | Tiny, dependency-free YAKE keyword extractor—one function, 34 languages, zero classes | | 0.1.0 | Initial release — extractKeywords, zero-dependency YAKE, English bundled + 33 more languages as subpath imports |

Full history in CHANGELOG.md.

Install

npm install yake-ts   # bun / pnpm / yarn all fine

Quick start

import { extractKeywords } from "yake-ts";

const keywords = extractKeywords("fix flaky auth test in login flow");
// [
//   { keyword: "fix flaky auth", normalized: "fix flaky auth", score: 0.017,
//     ngramSize: 3, occurrences: 1, sentenceIds: [0] },
//   ...
// ]

Results come back sorted, best first. Typical uses: tagging notes or CMS entries, naming a chat session from its first message, enriching search/RAG chunks without an LLM call.

The rules

Three things, and you've seen the whole tool.

1 · Lower score wins. score is a cost, not a relevance percentage. The list is already sorted ascending, so [0] is the strongest keyword — don't re-sort it descending.

2 · Everything happens per call. Scores come from the input text alone, so there is nothing to load, warm up, or reuse between calls. Pass a whole document rather than one sentence at a time: YAKE's position and spread features need more than one sentence to say anything.

3 · A language is a stopword list, not a tokenizer. Pass another language's set via the stopwords option and phrase detection adapts; word splitting stays the same Unicode word-boundary scan. Fine for space-delimited scripts, not for unsegmented Chinese or Japanese — see Languages.

API

extractKeywords(text: string, options?: YakeTsOptions): Keyword[]

Options

| Field | Type | Default | Description | | --- | --- | --- | --- | | maxNgramSize? | number | 3 | Max words per candidate keyword phrase. | | windowSize? | number | 1 | Co-occurrence window size for the relatedness feature. | | dedupeThreshold? | number | 0.9 | Similarity ceiling above which a candidate is dropped as a near-duplicate. 1 disables dedup. | | limit? | number | 10 | Max number of keywords to return. | | stopwords? | Iterable | bundled English | Stopwords to use. For other languages, import STOPWORDS from yake-ts/stopwords/<code> (e.g. yake-ts/stopwords/fr) and pass it here — each language is its own subpath export so you only pay for the ones you use. Or pass a fully custom set. |

Keyword

| Field | Type | Default | Description | | --- | --- | --- | --- | | keyword | string | | Surface form as it appeared in the source text. | | normalized | string | | Lowercased form used for matching/deduplication. | | score | number | | YAKE score — lower is more relevant. | | ngramSize | number | | Number of words in the phrase. | | occurrences | number | | How many times the phrase occurred in the text. | | sentenceIds | number[] | | Zero-based indices of sentences the phrase occurs in, ascending. |

Languages

English is bundled and used by default. 33 more ship as stopword-only subpath exports, so a consumer who never imports one pays zero bytes for it:

import { extractKeywords } from "yake-ts";
import { STOPWORDS as FRENCH } from "yake-ts/stopwords/fr";

extractKeywords("le chat est sur la table", { stopwords: FRENCH });

Available codes: ar, bg, br, cz, da, de, el, es, et, fa, fi, fr, hi, hr, hu, hy, id, it, ja, lt, lv, nl, no, pl, pt, ro, ru, sk, sl, sv, tr, uk, zh (vendored from @ade_oshineye/yaket's stopword bundle)

Adding your own words on top of a bundled list. Every language, including English, is a plain yake-ts/stopwords/<code> subpath export — yake-ts/stopwords/en works the same as /fr. Spread it into a Set with your own additions; this only imports the one list you name, so it costs nothing beyond what you were already paying:

import { STOPWORDS as EN } from "yake-ts/stopwords/en";

extractKeywords(text, { stopwords: new Set([...EN, "widget", "wigl"]) });

CJK needs pre-segmentation. Tokenization is a Unicode word-boundary scan, so Chinese and Japanese text — which has no spaces between words — comes back as one run-on token per script run, and the zh/ja stopword lists can't fix that. Segment it yourself (e.g. with Intl.Segmenter) and space-join the result before calling extractKeywords.

Limitations

  • Not byte-for-byte upstream YAKE. It is a port of a port: the algorithm core comes from @ade_oshineye/yaket, vendored rather than depended on, which itself documents drift from Python YAKE's segtok tokenizer. Expect the same top keywords, not identical float scores.
  • Dedup is Levenshtein similarity only, where yaket lets you choose seqm, levs, or jaro. Good enough for short candidate phrases; if you need Python's seqm behavior, use yaket.
  • Single documents only. No corpus statistics, no TF-IDF across a collection, no topic modeling.
  • Short input gives thin results. A five-word title has almost no statistics to score.
  • No lemmatization or POS filtering, so plural and singular forms rank as separate candidates.

Need something this doesn't do? Open an issue — feature requests welcome.

Credits

The algorithm is from the YAKE paper: Campos, Mangaravite, Pasquali, Jorge, Nunes, Jatowt, YAKE! Keyword Extraction from Single Documents using Multiple Local Features, Information Sciences 509 (2020), 257–289 — 10.1016/j.ins.2019.09.013. Reference implementation: LIAAD/yake.

Development

bun install
bun run test         # bun test
bun run typecheck    # tsc --noEmit
bun run build        # vite → dist/
bun run format       # biome check --write

License

MIT © jayF0x