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

kor-string-similarity

v2.0.0

Published

Korean-aware string similarity based on the Dice coefficient over jamo (phoneme) bigrams

Readme

kor-string-similarity

Korean-aware string similarity for JavaScript and TypeScript.

It scores how alike two strings are, from 0 to 1, using the Sørensen–Dice coefficient. Most Dice libraries compare whole characters. This one first splits each Hangul syllable into its jamo (초성·중성·종성), so strings that differ only inside a syllable still score as close:

| a | b | score | | ------------ | ------------ | ------ | | 안녕하세요 | 안녕하세요 | 1 | | 안녕하세요 | 안뇽하세여 | 0.73 | | 사과 | 사자 | 0.5 | | 각난닫 | 톹풒흏 | 0 |

Other characters (Latin letters, digits, symbols, spaces) are compared as they are, and comparison ignores case, so Korean, English and mixed text all work.

Install

npm install kor-string-similarity

Requires Node.js 22 or newer. TypeScript types are included.

Usage

import { compareTwoStrings, findBestMatch, arrangeBySimilarity } from "kor-string-similarity";
// or: const { compareTwoStrings } = require("kor-string-similarity");

compareTwoStrings("다람쥐 헌 쳇바퀴에 타고파", "고양이 새 쳇바퀴에 안 타고파");
// => 0.6578947368421053

findBestMatch("다람쥐 헌 쳇바퀴에 타고파", [
  "고양이 새 쳇바퀴에 안 타고파",
  "다람쥐 헌 쳇바퀴에 타고파",
]);
// => { text: "다람쥐 헌 쳇바퀴에 타고파", similarity: 1, ... }

arrangeBySimilarity("다람쥐 헌 쳇바퀴에 타고파", [
  "다람쥐 헌 쳇바퀴에 타고파",
  "고양이 새 쳇바퀴에 안 타고파",
  "생쥐 새 쳇바퀴에 타고파",
]);
// => [
//   { text: "다람쥐 헌 쳇바퀴에 타고파", similarity: 1, ... },
//   { text: "생쥐 새 쳇바퀴에 타고파", similarity: 0.7536231884057971, ... },
//   { text: "고양이 새 쳇바퀴에 안 타고파", similarity: 0.6578947368421053, ... },
// ]

API

compareTwoStrings(target: string, compared: string): number

Returns the similarity between two strings, from 0 (nothing in common) to 1 (identical).

findBestMatch(target: string, candidates: string[]): Match | undefined

Returns the candidate most similar to target. If several candidates tie, the first one wins. Returns undefined if candidates is empty.

arrangeBySimilarity(target: string, candidates: string[]): Match[]

Returns every candidate with its score, most similar first. Candidates with equal scores keep their original order. The input array is not changed.

Match

interface Match {
  text: string;       // the candidate string
  similarity: number; // 0 to 1
  _text: string;      // deprecated: same value as `text`
}

_text is the field name from 1.x. It is still returned so existing code keeps working, but it is deprecated and will be removed in the next major version. Use text instead.

Errors

Every function throws a TypeError if target is not a string, or if candidates is not an array of strings.

How it works

  1. Split into phonemes. The input is first NFC-normalized, so decomposed Hangul (common in macOS filenames) matches ordinary text. Each Hangul syllable then becomes three tokens: its initial consonant, vowel and final consonant. A syllable with no final consonant gets an empty placeholder. Every other character, including emoji, is one token of its own. "각a" → ㄱ ㅏ ㄱ a
  2. Build bigrams. Each token is paired with the one after it. The last token is paired with an end marker, so even a one-letter string has one bigram. ㄱ ㅏ ㄱ a → ㄱㅏ, ㅏㄱ, ㄱa, a⟨end⟩
  3. Score. The result is the Dice coefficient of the two bigram lists: 2 × shared bigrams / (bigrams in a + bigrams in b). Each bigram can be matched only once.

Because the text is compared at the jamo level, changing one vowel or final consonant affects only a few bigrams instead of the whole syllable.

Migrating from 1.x

2.0 gives the same scores as 1.x for ordinary text. What changed:

  • Decomposed (NFD) Hangul is now normalized, so it scores the same as precomposed text. In 1.x it was not recognized as Hangul.
  • Characters outside the Basic Multilingual Plane, such as emoji, are compared as whole characters. In 1.x they were split into two UTF-16 halves, so different emoji could look partly alike.
  • Invalid input now throws a TypeError. In 1.x the functions returned an Error object.
  • candidates must be an array of strings. In 1.x any object was accepted, and non-string items were converted to strings.
  • Deep imports such as kor-string-similarity/strSeparator.js are gone. Import from the package root only.
  • Node.js 22 or newer is required.
  • Results have a new text field. The old _text field is still returned with the same value but is deprecated, so switch match._text to match.text when you upgrade.

See CHANGELOG.md for the full list of changes.

Development

npm install
npm test   # builds with tsc, then runs the tests in test/ using node:test

License

ISC