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

hunmin-search

v0.2.0

Published

Hunmin Search — Korean fuzzy search: subsequence filter + Korean-aware Levenshtein scoring. Zero runtime dependencies.

Readme

Hunmin Search (hunmin-search)

English README (파일명은 npm 자동 포함 규칙 회피용입니다.)

한글·라틴 혼합 문자열에 대해 부분열(subsequence) 필터와 한글 완화 Levenshtein 점수로 후보를 정렬하는 소형 라이브러리입니다. 런타임 npm 의존성은 없습니다.

문서

요구 사항

  • Node.js 18 이상 권장 (engines 참고).

설치

로컬 패키지나 Git 의존성으로 연결하거나, npm에서 pnpm add hunmin-search로 설치합니다. 버전·CHANGELOG는 CHANGELOG.md, 배포 절차는 docs/ko/npm-publish.md를 참고하세요.

pnpm add ./path/to/hunmin-search
# 또는 빌드 후: pnpm pack → .tgz 설치

배포 tarball에는 dist/, README.md, LICENSE만 포함됩니다(files 필드). pnpm pack 또는 npm publish 전에 prepack으로 pnpm run build가 실행됩니다.

Node에서 쓰기

ESM (import)

import { searchKoRanked, searchKoDetailed } from 'hunmin-search';

searchKoRanked('홍길', ['홍길동', '서울']);
// [{ value: '홍길동', score: number }]

searchKoDetailed('길', ['홍길동'], { includeEditTrace: true });

CommonJS (require)

const { searchKoRanked, searchKoDetailed } = require('hunmin-search');

searchKoRanked('홍길', ['홍길동', '서울']);

같은 애플리케이션 안에서 ESM import와 CJS require로 이 패키지를 동시에 불러오면 듀얼 패키지 이슈(dual package hazard)가 생길 수 있습니다. 한 가지 모듈 형식만 쓰는 것을 권장합니다.

브라우저에서 쓰기

번들러 없이 스크립트만 넣는 경우, 빌드 산출물 dist/index.global.cjs를 로드하면 전역 객체 HunminSearch(tsup globalName)가 생깁니다.

<script src="./node_modules/hunmin-search/dist/index.global.cjs"></script>
<script>
  const hits = HunminSearch.searchKoRanked('홍길', ['홍길동', '서울']);
</script>

번들러(Vite·Webpack 등)에서는 package.json의 exports 서브패스 **hunmin-search/browser**를 쓰세요.

import { searchKoRanked } from 'hunmin-search/browser';

import 조건은 브라우저용 ESM 번들(dist/index.browser.js)로, require 조건은 CJS 빌드로 연결됩니다. IIFE(dist/index.global.cjs)는 <script src>로 파일 경로를 직접 지정할 때만 쓰며 exports에는 포함되지 않습니다. 설치 도구·모노레포에 따라 경로가 달라질 수 있습니다.

API 요약

  • searchKoRanked(query, candidates, options?) — 통과한 후보만 점수 내림차순(value, score만).
  • searchKoDetailed(...) — 동일 정렬 + subsequenceAlignments, editDistance(부분열 실패 시 null), 선택 editTrace.
  • 저수준: matchSubsequenceKo, levenshteinKo, rankByKoPipeline, 한글 분해·초성 유틸 등은 패키지 엔트리에서 re-export.

제약·메모

  • 인덱스는 UTF-16 코드 유닛 기준입니다. 이모지 같은 서로게이트 쌍은 인덱스 두 칸을 씁니다.
  • 대소문자를 무시할 때는 문자열 전체를 toLocaleLowerCase('en-US')로 소문자화한 뒤 비교합니다. 편집 거리와 점수 분모도 소문자화한 문자열 길이를 씁니다.
  • İ처럼 소문자화하면 길이가 늘어나는 문자는 subsequenceAlignments와 editTrace의 인덱스가 원문의 같은 위치를 여러 번 가리킬 수 있습니다. 인덱스는 항상 원문 범위 안에 있습니다. 하이라이트할 때는 중복을 합쳐서 쓰면 됩니다. editTrace는 소문자화한 문자열의 편집 경로이며 원문을 그대로 고치는 명령 목록은 아닙니다.
  • 그리스 대문자 Σ는 단어 끝에 오는지에 따라 σ나 ς로 바뀝니다. 질의와 후보를 따로 소문자화하기 때문에 같은 Σ도 양쪽에서 다르게 바뀔 수 있습니다.
  • 유니코드 정규화는 하지 않습니다. 완성형(NFC)과 분해형(NFD)은 다른 문자열이므로 호출하기 전에 질의와 후보를 NFC로 맞추세요. 반환되는 인덱스는 넘겨준 문자열 기준입니다. 정규화하기 전의 원문을 화면에 보여준다면 위치 변환이 따로 필요합니다.
const nfc = (s: string) => s.normalize('NFC');
searchKoRanked(nfc(query), candidates.map(nfc));
  • 편집 거리는 항상 최소 편집 거리입니다. similarSubstitutionCost(기본 0.01)의 범위와 오류 처리는 docs/ko/api-score.md에 있습니다.
  • Node 18은 공식 지원이 끝났지만 engines는 >=18을 유지합니다. 새 서비스에는 지원 중인 LTS를 쓰세요.
  • 긴 문자열이나 후보가 많으면 비용이 큽니다. pnpm bench로 환경별 성능을 확인할 수 있고, 배치 크기와 길이 상한은 호출하는 쪽에서 두는 것을 권장합니다.

개발

  • 기여 가이드: CONTRIBUTING.md · 변경 기록: CHANGELOG.md
  • 소스 타입체크: moduleResolution: Bundler, 상대 경로 import는 확장자 없이 작성합니다.
  • 빌드는 tsup으로 dist/에 ESM(.js), CJS(.cjs), 브라우저 ESM(.browser.js), 브라우저 IIFE(.global.cjs), 선언 파일을 냅니다.

일부 Vitest 테스트는 dist가 있어야 통과합니다. 로컬에서는 보통 아래 순서를 따릅니다(CI와 동일).

pnpm install
pnpm run typecheck
pnpm run build
pnpm test
pnpm run lint
pnpm run publint
pnpm run attw
pnpm run test:browser   # Playwright — Chromium 필요
pnpm run bench           # vitest bench — 성능 벤치마크

라이선스

MIT — LICENSE 파일 참고. 참조·이식한 타 라이브러리 로직이 있다면 각 소스 파일 주석의 출처를 따릅니다.