@ycookiey/yfuzzy 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,55 +5,37 @@
5
5
  [![minzipped](https://badgen.net/bundlephobia/minzip/@ycookiey/yfuzzy)](https://bundlephobia.com/package/@ycookiey/yfuzzy)
6
6
  [![license](https://img.shields.io/npm/l/@ycookiey/yfuzzy)](./LICENSE)
7
7
 
8
- 日本語特化のあいまい検索ライブラリ。ローマ字混じり入力・訓令式/ヘボン式の並列照合・子音(頭文字)マッチ・誤字許容を 1 パッケージに統合。依存ゼロ・ESM・TypeScript 型付き。
8
+ 日本語特化のあいまい検索ライブラリ。ローマ字混じり入力・ヘボン式/訓令式の同時照合・子音だけのマッチ・誤字許容を 1 パッケージに統合。依存ゼロ・ESM・TypeScript 型付き。
9
9
 
10
10
  ```
11
11
  shinjuku / sinjuku / しんじゅく / シンジュク → すべて「シンジュク」にヒット
12
- kmnr → 「カミナリ」にヒット(頭文字)
13
- カナリ → 「カミナリ」にヒット(飛び石)
12
+ kmnr → 「カミナリ」にヒット(子音だけ)
13
+ カナリ → 「カミナリ」にヒット(とびとび一致)
14
14
  センタイ → 「センダイ」にヒット(誤字)
15
15
  ```
16
16
 
17
17
  ## なぜ yfuzzy か
18
18
 
19
- 既存のあいまい検索ライブラリ(fuse.js / fuzzysort / uFuzzy / match-sorter など)は英語・ラテン文字圏を前提に設計されており、アクセント除去や Unicode 正規化は持つものの、**ローマ字↔かな・訓令式/ヘボン式といった日本語入力の概念を持たない**。
19
+ 既存のあいまい検索ライブラリ(fuse.js / fuzzysort / MiniSearch / uFuzzy / match-sorter など)はラテン文字圏を前提に設計されており、diacritics(発音区別符号)の除去や Unicode 正規化には対応するものの、**ローマ字とかなの変換や、ヘボン式・訓令式の違いを扱わない**。
20
20
 
21
- 日本語 UI の検索ボックスでは、利用者は—
22
-
23
- - ローマ字で打つ(`sinjuku` / `shinjuku`)
24
- - かなを部分的に打つ(`しぶ`)
25
- - 子音だけ打つ(`kmnr`)
26
-
27
- —のに対し、データはかな・カタカナ・漢字(の読み)で保持されている。yfuzzy はこの「入力とデータの表記ギャップ」を埋めることに特化する。
21
+ 日本語 UI では、利用者はローマ字・部分的なかな・子音だけ(上の例)で打つ一方、データはひらがな・カタカナ・漢字(の読み)で保持されている。yfuzzy はこの表記のずれを埋めることに特化している。
28
22
 
29
23
  ## スコープ
30
24
 
31
- **向いている**: 日本語の読み(かな)を索引にした短い文字列の検索 — 駅名・地名・商品名・人名の読み、type-ahead / オートコンプリート。
25
+ **向いている**: 日本語の読み(かな)を索引にした短い文字列の検索。駅名・地名・商品名・人名などの読みに対する、逐次検索(type-ahead)やオートコンプリート。
32
26
 
33
27
  **向いていない**:
34
28
 
35
- - **漢字をそのまま検索**: yfuzzy は漢字を読みに変換しない(リテラル一致のみ)。読みで当てたいなら読み仮名を用意し `getText` で返す([使い方](#使い方)参照)。
29
+ - **漢字をそのまま検索**: yfuzzy は漢字を読みに変換しない(文字どおりの一致のみ)。読みで当てたいなら読み仮名を用意し `getText` で返す([使い方](#使い方)参照)。
36
30
  - **ラテン文字の汎用あいまい検索 / 全文検索**(複数フィールド・トークン化・TF-IDF): fuse.js / MiniSearch 等が成熟している。用途で使い分けるとよい。
37
31
 
38
- ## 特長
39
-
40
- - **ローマ字入力 → かな照合**(IME 不要。訓令式・ヘボン式どちらの綴りでも)
41
- - **子音だけの頭文字検索**(`kmnr` → `カミナリ`)
42
- - **飛び石 subsequence** + 境界/連続を優先するスコアリング
43
- - **誤字許容**(編集距離。前方/末尾欠落は上位層が拾い、中間の置換/挿入/削除/転置に特化)
44
- - **ハイライト用インデックス**を元文字列上で返す(ローマ字経由でも正確に逆マップし、長音の穴なし)
45
- - **単発関数 / 索引構築**の両 API、TypeScript 型付き(`SearchResult<T>` に `item` が流れる)
46
- - **依存ゼロ**(wanakana の必要部分のみ改変同梱)
47
-
48
32
  ## 類似パッケージとの比較
49
33
 
50
34
  | 機能 | yfuzzy | [fuse.js](https://www.fusejs.io/) | [fuzzysort](https://github.com/farzher/fuzzysort) | [MiniSearch](https://github.com/lucaong/minisearch) | [uFuzzy](https://github.com/leeoniya/uFuzzy) | [match-sorter](https://github.com/kentcdodds/match-sorter) |
51
35
  |---|:--:|:--:|:--:|:--:|:--:|:--:|
52
- | ローマ字入力 → かな | ✅ | ➖ | ➖ | ➖ | ➖ | ➖ |
53
- | 訓令式 / ヘボン式 並列 | ✅ | ➖ | ➖ | ➖ | ➖ | ➖ |
54
- | かな正規化(半角/全角・ひら↔カタ) | ✅ | ➖ | ➖ | ➖ | ➖ | ➖ |
55
- | 頭文字(子音)マッチ | ✅ | ➖ | 🔸 | ➖ | 🔸 | 🔸 |
56
- | 飛び石 subsequence | ✅ | 🔸 | ✅ | ➖ | ✅ | 🔸 |
36
+ | 日本語入力(ローマ字↔かな・ヘボン/訓令・かな正規化) | ✅ | ➖ | ➖ | ➖ | ➖ | ➖ |
37
+ | 子音だけのマッチ | ✅ | ➖ | 🔸 | ➖ | 🔸 | 🔸 |
38
+ | とびとび一致(subsequence) | ✅ | 🔸 | ✅ | ➖ | ✅ | 🔸 |
57
39
  | 誤字許容(編集距離) | ✅ | ✅ | ➖ | ✅ | 🔸 | ➖ |
58
40
  | ハイライト位置の返却 | ✅ | ✅ | ✅ | 🔸 | ✅ | ➖ |
59
41
  | 索引の事前構築 | ✅ | ✅ | ✅ | ✅ | ➖ | ➖ |
@@ -61,7 +43,7 @@ kmnr → 「カミナリ」にヒット
61
43
  | ラテン文字の diacritics 除去 | ➖ | ✅ | ➖ | 🔸 | ✅ | ✅ |
62
44
  | 依存ゼロ | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
63
45
 
64
- 凡例: ✅ 組み込み / 🔸 部分的・間接的(または要カスタム) / ➖ なし。各ライブラリの調査時点の既定挙動を基準とし、多くはカスタム関数で拡張できる。本表は「日本語入力対応+主要なあいまいマッチ機能」に観点を絞ったもの。
46
+ 凡例: ✅ 組み込み / 🔸 部分的・間接的(または要カスタム) / ➖ なし。各ライブラリの調査時点の既定挙動を基準とした。多くはカスタム関数で拡張できる。本表は「日本語入力対応+主要なあいまいマッチ機能」に観点を絞ったもの。
65
47
 
66
48
  ## インストール
67
49
 
@@ -86,7 +68,7 @@ search('sinjuku', stations);
86
68
 
87
69
  ### オブジェクト配列(getText)
88
70
 
89
- `getText` で検索対象の文字列を取り出す。漢字を読みで当てたい場合も、読み仮名を返せばよい(読みの付与は利用者責務)。
71
+ `getText` で検索対象の文字列を取り出す。漢字を読みで当てたい場合も、読み仮名を返せばよい(読みは利用者側で用意する)。
90
72
 
91
73
  ```ts
92
74
  const items = [
@@ -96,9 +78,6 @@ const items = [
96
78
 
97
79
  search('しんじゅく', items, { getText: (x) => x.yomi });
98
80
  // → [{ item: { label: '新宿', … }, refIndex: 1, score: 1, tier: 1 }]
99
-
100
- search('toukyou', items, { getText: (x) => x.label });
101
- // → [] ← label(漢字)はそのまま照合されるので当たらない
102
81
  ```
103
82
 
104
83
  ### 索引の再利用(createIndex)
@@ -109,41 +88,31 @@ search('toukyou', items, { getText: (x) => x.label });
109
88
  import { createIndex } from '@ycookiey/yfuzzy';
110
89
 
111
90
  const index = createIndex(stations);
112
- index.search('しぶ'); // → シブヤ
113
- index.search('しな', { limit: 5 }); // per-call で検索オプションを上書き
91
+ index.search('しぶ'); // → 先頭は シブヤ(短い語なので tier3 候補も続く)
92
+ index.search('しな', { limit: 5 }); // 呼び出しごとに検索オプションを上書き
114
93
  ```
115
94
 
116
95
  ### ハイライト(includeMatches)
117
96
 
118
- `includeMatches: true` で、**元文字列上**の一致区間 `[start, end)`(半開・昇順・マージ済み)を返す(tier 1/2 のみ)。
97
+ `includeMatches: true` で、**元文字列上**の一致区間 `[start, end)`(半開・昇順、隣接や重複は統合済み)を返す(後述の tier 1・2 でのみ)。各区間を `text.slice` で切り出して囲めばハイライトになる。
119
98
 
120
99
  ```ts
121
100
  const r = search('keki', ['ケーキ'], { includeMatches: true });
122
- // r[0].matches → [[0, 3]] ← 長音「ー」を含めて穴なし
123
-
124
- function highlight(text: string, ranges: readonly [number, number][]): string {
125
- let out = '';
126
- let last = 0;
127
- for (const [s, e] of ranges) {
128
- out += text.slice(last, s) + '<mark>' + text.slice(s, e) + '</mark>';
129
- last = e;
130
- }
131
- return out + text.slice(last);
132
- }
101
+ // r[0].matches → [[0, 3]] ← 長音「ー」も含めて隙間なく連続
133
102
  ```
134
103
 
135
104
  ## マッチの仕組み
136
105
 
137
- クエリは tier 昇順で評価され、最初に一致した層で確定する。`score` は 0–1(高いほど良い)で、層ごとにレンジが分離する。
106
+ クエリは tier 1 から順に評価され、最初に一致した tier で確定する(既定は tier 1〜3。`maxTier: 4` で tier 4 も有効化)。`score` は 0〜1 で、上の tier ほど高い。
138
107
 
139
- | tier | 層 | 例 | score 帯 |
108
+ | tier | 内容 | 例 | score の範囲(目安) |
140
109
  |---|---|---|---|
141
- | 1 | 完全一致(かな/ローマ字の前方・部分一致) | `シンジュク`→`シンジュク` | (0.75, 1] |
142
- | 2 | 柔軟(subsequence・境界/連続ボーナス・頭文字) | `kmnr`→`カミナリ` | (0.5, 0.75) |
143
- | 3 | 誤字許容(編集距離、中間の置換/挿入/削除/転置) | `センタイ`→`センダイ` | (0.25, 0.5) |
144
- | 4 | 構造類似(Tversky bigram、デフォルト無効) | 大きく崩れた入力 | (0, 0.25] |
110
+ | 1 | 直接一致(かな/ローマ字が前方・部分一致) | `シンジュク`→`シンジュク` | 0.75〜1.0 |
111
+ | 2 | 柔軟一致(とびとびでも可。語頭・連続を優遇、子音だけの入力も可) | `kmnr`→`カミナリ` | 0.5〜0.75 |
112
+ | 3 | 誤字許容(編集距離、中間の置換/挿入/削除/入れ替え) | `センタイ`→`センダイ` | 0.25〜0.5 |
113
+ | 4 | 構造類似(2 文字単位の重なりによる類似〔Tversky 係数〕、既定で無効) | 大きく崩れた入力 | 0〜0.25 |
145
114
 
146
- `score` 帯が重ならないため、利用者は閾値だけで「確実なヒット」と「もしかして」を分離できる。結果は `score` 降順(同点は `refIndex` 昇順で安定)。
115
+ 各 tier は幅およそ 0.25 の帯に収まり、スコアが tier 間の境界(0.25 / 0.5 / 0.75)ちょうどになることはない。そのため閾値ひとつで「確実なヒット」と「あいまいな候補(『もしかして』表示向け)」を分離できる。結果は `score` 降順(同点は `refIndex` 昇順で安定)。
147
116
 
148
117
  ## API
149
118
 
@@ -153,7 +122,7 @@ function highlight(text: string, ranges: readonly [number, number][]): string {
153
122
 
154
123
  ### `createIndex(items, options?) → SearchIndex`
155
124
 
156
- 事前構築した索引を返す。`index.search(query, searchOptions?)` で per-call の検索オプションを上書きできる。`index.size` で件数。
125
+ 事前構築した索引を返す。`index.search(query, searchOptions?)` で呼び出しごとに検索オプションを上書きできる。`index.size` で件数。
157
126
 
158
127
  ### オプション
159
128
 
@@ -161,16 +130,16 @@ function highlight(text: string, ranges: readonly [number, number][]): string {
161
130
 
162
131
  | 名前 | 型 | 既定 | 説明 |
163
132
  |---|---|---|---|
164
- | `getText` | `(item: T) => string` | — | オブジェクト配列で検索対象文字列を取り出す(`T[]` のとき必須) |
165
- | `romaji` | `'hepburn' \| 'kunrei' \| 'both' \| false` | `'both'` | ローマ字照合の方式。`false` でかな空間のみ |
166
- | `separatorExpansion` | `boolean \| string[]` | `false` | 区切り文字を「除去」「境界」両経路で展開(`true` で `['-', ' ', '・', '_']`) |
133
+ | `getText` | `(item: T) => string` | なし | オブジェクト配列で検索対象文字列を取り出す(`T[]` のとき必須) |
134
+ | `romaji` | `'hepburn' \| 'kunrei' \| 'both' \| false` | `'both'` | ローマ字照合の方式。`false` でローマ字照合せず、かなのみで照合 |
135
+ | `separatorExpansion` | `boolean \| string[]` | `false` | 区切り文字を、取り除いた形と区切りとして扱う形の両方で照合(`true` で `['-', ' ', '・', '_']`) |
167
136
 
168
137
  検索時オプション(`index.search` で上書き可):
169
138
 
170
139
  | 名前 | 型 | 既定 | 説明 |
171
140
  |---|---|---|---|
172
141
  | `limit` | `number` | 無制限 | 返却件数の上限 |
173
- | `maxTier` | `1 \| 2 \| 3 \| 4` | `3` | 実行する層の上限(`4` で構造類似層を有効化) |
142
+ | `maxTier` | `1 \| 2 \| 3 \| 4` | `3` | 実行する tier の上限(`4` で構造類似の tier を有効化) |
174
143
  | `minScore` | `number` | `0` | この score 未満を除外 |
175
144
  | `includeMatches` | `boolean` | `false` | `matches` を含める |
176
145
 
@@ -180,7 +149,7 @@ function highlight(text: string, ranges: readonly [number, number][]): string {
180
149
  type SearchResult<T> = {
181
150
  item: T;
182
151
  refIndex: number; // items 内の位置
183
- score: number; // 0–1、高いほど良い
152
+ score: number; // 0〜1、高いほど良い
184
153
  tier: 1 | 2 | 3 | 4;
185
154
  matches?: readonly [number, number][]; // includeMatches 時、tier 1/2 のみ
186
155
  };
@@ -188,8 +157,8 @@ type SearchResult<T> = {
188
157
 
189
158
  ## 性能
190
159
 
191
- 短い文字列の索引向け(数百〜数十万件)。文字集合プレフィルタと tier 打ち切りにより、1 クエリの実測は概ね 千件 ~1.5ms / 1 万件 ~10ms / 10 万件 ~90ms(環境依存)。同条件で fuse.js より高速。`maxTier` を下げる / `romaji: 'kunrei'` で片方式に絞ると更に軽くなる。索引構築は 10 万件で ~0.7s(一度きり)。
160
+ 短い文字列の索引向け(数百〜数十万件)。内部の前段フィルタと早期打ち切りにより、1 クエリの実測値は千件で約 1.5ms、1 万件で約 10ms、10 万件で約 90ms(環境依存)。同条件で fuse.js より高速。`maxTier` を下げる、または `romaji` を一方の方式だけに絞ると更に軽くなる。索引構築は 10 万件で約 0.7 秒(一度きり)。
192
161
 
193
162
  ## ライセンス
194
163
 
195
- MIT。ローマ字→かな変換に [WanaKana](https://github.com/WaniKani/WanaKana)(MIT)のコードを改変同梱している。詳細は [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)。
164
+ MIT。ローマ字→かな変換に [WanaKana](https://github.com/WaniKani/WanaKana)(MIT)のコードを改変のうえ同梱している。詳細は [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)。
package/dist/query.d.ts CHANGED
@@ -3,6 +3,14 @@ import { type RomajiOption } from './romaji/convert.js';
3
3
  export interface NormalizedQuery {
4
4
  /** 正規化カナ形 */
5
5
  readonly kana: string;
6
+ /** 正規化カナ形が1コードポイントか(tier 1 の1文字レンジ分離用、spec 4.1) */
7
+ readonly singleChar: boolean;
8
+ /**
9
+ * かな変換前のリテラル形(spec 2.2)。英数1コードポイントのクエリが変換で
10
+ * 形を変えた場合(母音 a/i/u/e/o と n)のみ非 null。tier 1 かな空間で並列照合し、
11
+ * ASCII データへの中間一致が変換で不可能になるのを防ぐ
12
+ */
13
+ readonly literal: string | null;
6
14
  /** 訓令式ローマ字(romaji オプションで無効時 null) */
7
15
  readonly kunrei: string | null;
8
16
  /** ヘボン式ローマ字(romaji オプションで無効時 null) */
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAK7B,oBAAoB;AACpB,MAAM,WAAW,eAAe;IAC9B,aAAa;IACb,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;CAC7B;AAED,yBAAyB;AACzB,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,eAAe,CAajF;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAGlE"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAK7B,oBAAoB;AACpB,MAAM,WAAW,eAAe;IAC9B,aAAa;IACb,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;CAC7B;AAED,yBAAyB;AACzB,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,eAAe,CAgBjF;AAOD,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAGlE"}
package/dist/query.js CHANGED
@@ -11,11 +11,14 @@ import { generateBigrams } from './bigram.js';
11
11
  import { charMask } from './charmask.js';
12
12
  /** クエリ文字列(1経路分)を正規化する */
13
13
  export function normalizeQuery(raw, romaji) {
14
- const kana = applyTransforms(toKana(applyTransforms(raw, 'preKana')), 'postKana');
14
+ const pre = applyTransforms(raw, 'preKana');
15
+ const kana = applyTransforms(toKana(pre), 'postKana');
15
16
  const kunrei = kunreiEnabled(romaji) ? kanaToRomaji(kana, KUNREI) : null;
16
17
  const hepburn = hepburnEnabled(romaji) ? kanaToRomaji(kana, HEPBURN) : null;
17
18
  return {
18
19
  kana,
20
+ singleChar: isSingleCodePoint(kana),
21
+ literal: /^[a-z0-9]$/.test(pre) && pre !== kana ? pre : null,
19
22
  kunrei,
20
23
  hepburn,
21
24
  kanaMask: charMask(kana),
@@ -24,6 +27,11 @@ export function normalizeQuery(raw, romaji) {
24
27
  bigrams: null,
25
28
  };
26
29
  }
30
+ function isSingleCodePoint(s) {
31
+ if (s.length === 0)
32
+ return false;
33
+ return s.length === String.fromCodePoint(s.codePointAt(0)).length;
34
+ }
27
35
  /** tier 4 実行時に bigram を遅延生成してキャッシュする */
28
36
  export function ensureQueryBigrams(q) {
29
37
  if (q.bigrams === null)
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,6CAA6C;AAC7C,EAAE;AACF,wDAAwD;AACxD,wDAAwD;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,MAAM,EACN,OAAO,EACP,aAAa,EACb,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAkBzC,yBAAyB;AACzB,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,MAAoB;IAC9D,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzE,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,OAAO;QACL,IAAI;QACJ,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC;QACxB,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,kBAAkB,CAAC,CAAkB;IACnD,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;QAAE,CAAC,CAAC,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,OAAO,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,6CAA6C;AAC7C,EAAE;AACF,wDAAwD;AACxD,wDAAwD;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,MAAM,EACN,OAAO,EACP,aAAa,EACb,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA0BzC,yBAAyB;AACzB,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,MAAoB;IAC9D,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzE,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,OAAO;QACL,IAAI;QACJ,UAAU,EAAE,iBAAiB,CAAC,IAAI,CAAC;QACnC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;QAC5D,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC;QACxB,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAS;IAClC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC,MAAM,CAAC;AACrE,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,kBAAkB,CAAC,CAAkB;IACnD,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;QAAE,CAAC,CAAC,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,OAAO,CAAC;AACnB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tier1-exact.d.ts","sourceRoot":"","sources":["../../src/tiers/tier1-exact.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAS,MAAM,YAAY,CAAC;AA4CjD,eAAO,MAAM,UAAU,EAAE,OAyBxB,CAAC"}
1
+ {"version":3,"file":"tier1-exact.d.ts","sourceRoot":"","sources":["../../src/tiers/tier1-exact.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAS,MAAM,YAAY,CAAC;AA8DjD,eAAO,MAAM,UAAU,EAAE,OA+BxB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  // tier 1: 完全マッチ層(spec 4.1)。クエリ文字列がデータに連続して現れる。
2
- // サブマッチ4種を固定優先順で評価し、intraScore 最大を採用(同点は先順位=表の記載順)。
3
- // 優先順(spec 5章タイブレーク): かな前方 > かな部分 > romaji前方(訓令>ヘボン) > romaji部分(訓令>ヘボン)。
2
+ // サブマッチを固定優先順で評価し、intraScore 最大を採用(同点は先順位=表の記載順)。
3
+ // 優先順(spec 5章タイブレーク): かな前方 > かな部分 > リテラル前方 > リテラル部分 >
4
+ // romaji前方(訓令>ヘボン) > romaji部分(訓令>ヘボン)。
4
5
  const KANA_PREFIX = 1.0;
5
6
  const KANA_SUBSTRING = 0.9;
6
7
  const ROMAJI_PREFIX = 0.97;
@@ -12,20 +13,31 @@ function range(len, offset) {
12
13
  p.push(offset + i);
13
14
  return p;
14
15
  }
15
- function prefix(query, data, space, factor) {
16
+ // 1文字クエリ(正規化後1コードポイント)のレンジ分離(spec 4.1):
17
+ // 前方一致系 = 0.5 + raw/2 ∈ (0.5, 1]、部分一致系 = raw/2 ∈ (0, 0.5]。
18
+ // coverage 差で短いデータの部分一致が長いデータの前方一致を逆転しないことを保証する。
19
+ // 完全一致(coverage 1.0 の前方)は 1.0 のまま。
20
+ function mapScore(raw, isPrefix, single) {
21
+ if (!single)
22
+ return raw;
23
+ return isPrefix ? 0.5 + raw / 2 : raw / 2;
24
+ }
25
+ function prefix(query, data, space, factor, single) {
16
26
  if (query.length === 0 || data.length === 0)
17
27
  return null;
18
28
  if (!data.startsWith(query))
19
29
  return null;
20
- return { intraScore: (query.length / data.length) * factor, space, offset: 0, len: query.length };
30
+ const raw = (query.length / data.length) * factor;
31
+ return { intraScore: mapScore(raw, true, single), space, offset: 0, len: query.length };
21
32
  }
22
- function substring(query, data, space, factor, minLen) {
33
+ function substring(query, data, space, factor, minLen, single) {
23
34
  if (query.length < minLen || data.length === 0)
24
35
  return null;
25
36
  const idx = data.indexOf(query);
26
37
  if (idx <= 0)
27
38
  return null; // 0 = 前方一致(別サブマッチが担当)、<0 = 非一致
28
- return { intraScore: (query.length / data.length) * factor, space, offset: idx, len: query.length };
39
+ const raw = (query.length / data.length) * factor;
40
+ return { intraScore: mapScore(raw, false, single), space, offset: idx, len: query.length };
29
41
  }
30
42
  export const tier1Exact = (q, e) => {
31
43
  let best = null;
@@ -37,20 +49,26 @@ export const tier1Exact = (q, e) => {
37
49
  const kana = e.kana.text;
38
50
  const kunrei = e.kunrei?.text ?? '';
39
51
  const hepburn = e.hepburn?.text ?? '';
52
+ const single = q.singleChar;
40
53
  // 1. かな前方一致
41
- consider(prefix(q.kana, kana, 'kana', KANA_PREFIX));
54
+ consider(prefix(q.kana, kana, 'kana', KANA_PREFIX, single));
42
55
  // 2. かな部分一致(かなは1文字でも可)
43
- consider(substring(q.kana, kana, 'kana', KANA_SUBSTRING, 1));
44
- // 3. romaji 前方一致(訓令 → ヘボン。前方は最小長条件なし)
56
+ consider(substring(q.kana, kana, 'kana', KANA_SUBSTRING, 1, single));
57
+ // 3. リテラル前方/部分一致(かな変換で形が変わった英数1文字クエリのみ。かな空間)
58
+ if (q.literal !== null) {
59
+ consider(prefix(q.literal, kana, 'kana', KANA_PREFIX, single));
60
+ consider(substring(q.literal, kana, 'kana', KANA_SUBSTRING, 1, single));
61
+ }
62
+ // 4. romaji 前方一致(訓令 → ヘボン。前方は最小長条件なし)
45
63
  if (q.kunrei !== null)
46
- consider(prefix(q.kunrei, kunrei, 'kunrei', ROMAJI_PREFIX));
64
+ consider(prefix(q.kunrei, kunrei, 'kunrei', ROMAJI_PREFIX, single));
47
65
  if (q.hepburn !== null)
48
- consider(prefix(q.hepburn, hepburn, 'hepburn', ROMAJI_PREFIX * HEPBURN_PENALTY));
49
- // 4. romaji 部分一致(訓令 → ヘボン。クエリ romaji 2文字以上)
66
+ consider(prefix(q.hepburn, hepburn, 'hepburn', ROMAJI_PREFIX * HEPBURN_PENALTY, single));
67
+ // 5. romaji 部分一致(訓令 → ヘボン。クエリ romaji 2文字以上)
50
68
  if (q.kunrei !== null)
51
- consider(substring(q.kunrei, kunrei, 'kunrei', ROMAJI_SUBSTRING, 2));
69
+ consider(substring(q.kunrei, kunrei, 'kunrei', ROMAJI_SUBSTRING, 2, single));
52
70
  if (q.hepburn !== null)
53
- consider(substring(q.hepburn, hepburn, 'hepburn', ROMAJI_SUBSTRING * HEPBURN_PENALTY, 2));
71
+ consider(substring(q.hepburn, hepburn, 'hepburn', ROMAJI_SUBSTRING * HEPBURN_PENALTY, 2, single));
54
72
  if (best === null)
55
73
  return null;
56
74
  const c = best;
@@ -1 +1 @@
1
- {"version":3,"file":"tier1-exact.js","sourceRoot":"","sources":["../../src/tiers/tier1-exact.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,oDAAoD;AACpD,yEAAyE;AAMzE,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,qBAAqB;AAWnD,SAAS,KAAK,CAAC,GAAW,EAAE,MAAc;IACxC,MAAM,CAAC,GAAa,EAAE,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;QAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,KAAa,EAAE,IAAY,EAAE,KAAY,EAAE,MAAc;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACpG,CAAC;AAED,SAAS,SAAS,CAChB,KAAa,EACb,IAAY,EACZ,KAAY,EACZ,MAAc,EACd,MAAc;IAEd,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,+BAA+B;IAC1D,OAAO,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAY,CAAC,CAAkB,EAAE,CAAa,EAAE,EAAE;IACvE,IAAI,IAAI,GAAqB,IAAI,CAAC;IAClC,wCAAwC;IACxC,MAAM,QAAQ,GAAG,CAAC,CAAmB,EAAQ,EAAE;QAC7C,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;YAAE,IAAI,GAAG,CAAC,CAAC;IAChF,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;IAEtC,YAAY;IACZ,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IACpD,uBAAuB;IACvB,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,sCAAsC;IACtC,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI;QAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;IACnF,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;QAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC;IACzG,4CAA4C;IAC5C,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI;QAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;QAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;IAElH,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,CAAC,GAAc,IAAI,CAAC;IAC1B,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;AAClG,CAAC,CAAC"}
1
+ {"version":3,"file":"tier1-exact.js","sourceRoot":"","sources":["../../src/tiers/tier1-exact.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,54 +1,58 @@
1
- {
2
- "name": "@ycookiey/yfuzzy",
3
- "version": "0.1.1",
4
- "description": "Japanese-aware fuzzy search library",
5
- "license": "MIT",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
- "author": "ycookiey",
10
- "keywords": [
11
- "fuzzy",
12
- "fuzzy-search",
13
- "search",
14
- "japanese",
15
- "kana",
16
- "romaji",
17
- "katakana",
18
- "hiragana",
19
- "typeahead",
20
- "autocomplete"
21
- ],
22
- "type": "module",
23
- "main": "./dist/index.js",
24
- "types": "./dist/index.d.ts",
25
- "exports": {
26
- ".": {
27
- "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js"
29
- }
30
- },
31
- "files": [
32
- "dist",
33
- "README.md",
34
- "LICENSE",
35
- "THIRD_PARTY_NOTICES.md"
36
- ],
37
- "scripts": {
38
- "build": "tsc -p tsconfig.build.json",
39
- "typecheck": "tsc -p tsconfig.json",
40
- "test": "vitest run",
41
- "test:watch": "vitest",
42
- "bench": "npm run build && node bench/run.js",
43
- "prepublishOnly": "npm run build"
44
- },
45
- "devDependencies": {
46
- "fuse.js": "^7.4.2",
47
- "fuzzysort": "^3.1.0",
48
- "typescript": "^6.0.3",
49
- "vitest": "^4.1.8"
50
- },
51
- "engines": {
52
- "node": ">=18"
53
- }
54
- }
1
+ {
2
+ "name": "@ycookiey/yfuzzy",
3
+ "version": "0.2.0",
4
+ "description": "Japanese-aware fuzzy search library",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "author": "ycookiey",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/ycookiey/yfuzzy.git"
13
+ },
14
+ "keywords": [
15
+ "fuzzy",
16
+ "fuzzy-search",
17
+ "search",
18
+ "japanese",
19
+ "kana",
20
+ "romaji",
21
+ "katakana",
22
+ "hiragana",
23
+ "typeahead",
24
+ "autocomplete"
25
+ ],
26
+ "type": "module",
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE",
39
+ "THIRD_PARTY_NOTICES.md"
40
+ ],
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.build.json",
43
+ "typecheck": "tsc -p tsconfig.json",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "bench": "npm run build && node bench/run.js",
47
+ "prepublishOnly": "npm run build"
48
+ },
49
+ "devDependencies": {
50
+ "fuse.js": "^7.4.2",
51
+ "fuzzysort": "^3.1.0",
52
+ "typescript": "^6.0.3",
53
+ "vitest": "^4.1.8"
54
+ },
55
+ "engines": {
56
+ "node": ">=18"
57
+ }
58
+ }