cjk_index 0.2.0 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +62 -0
- data/LICENSE-Unicode +39 -0
- data/NOTICE +17 -0
- data/README.md +164 -41
- data/data/ja-kyujitai.tsv +423 -292
- data/data/ko-hanyang-pua.tsv +5666 -0
- data/data/zh-hant-hans-safe.tsv +2774 -0
- data/exe/cjk_index +6 -0
- data/lib/cjk_index/bridgetown.rb +100 -0
- data/lib/cjk_index/builder.rb +247 -89
- data/lib/cjk_index/cli.rb +240 -0
- data/lib/cjk_index/index_file.rb +4 -0
- data/lib/cjk_index/jekyll.rb +21 -5
- data/lib/cjk_index/normalizer.rb +60 -12
- data/lib/cjk_index/postings.rb +218 -0
- data/lib/cjk_index/rake_task.rb +71 -0
- data/lib/cjk_index/runtime.js +243 -29
- data/lib/cjk_index/runtime.rb +1 -0
- data/lib/cjk_index/searcher.rb +101 -37
- data/lib/cjk_index/tokenizer.rb +30 -0
- data/lib/cjk_index/version.rb +1 -1
- data/lib/cjk_index.rb +1 -0
- metadata +16 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9c9ffe634562d740738f6d9b9cf97ade5f5ab6d32a80b6bfd349496435d9e88b
|
|
4
|
+
data.tar.gz: 6cc0aebdedd14b07cdcf9dda3dcc9b849b80d135149444f057daed4cc620c004
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee41c34d99efe6e17f8936f3211b62aaab6fdafa54b714f685458c641a56263a46b506de9f703a4cd1c6f470c32e0d336b1914547655a433641ecbf9cdc5fcc0
|
|
7
|
+
data.tar.gz: 608805cba3a84e8c1bb8425e09c8ff3bdcb2bd4da6443f6ca63eeb6d2e3952e75b0166db871e853383d3531cb40d7f48052cc70540f2ae7fd8bd5ae372424af7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0 (2026-10-28)
|
|
4
|
+
|
|
5
|
+
Indexes built with 0.x should be rebuilt: the `ja` table changed, and the
|
|
6
|
+
index now records a digest of its tables (see below). Formats 2 and 3 are
|
|
7
|
+
still read.
|
|
8
|
+
|
|
9
|
+
Large collections:
|
|
10
|
+
|
|
11
|
+
- Index format `cjk_index/4`: posting lists as compact strings (about a third
|
|
12
|
+
smaller gzipped, three times smaller before compression).
|
|
13
|
+
- Split indexes: `Builder#write_split(dir, shard_size:)` and
|
|
14
|
+
`Builder#each_split_file` write a manifest and shards of about 32 KB; the
|
|
15
|
+
browser fetches shards as queries need them (`index.searchAsync`,
|
|
16
|
+
`index.prepare`). `CJKIndex.load` and `Searcher.load` read a split index;
|
|
17
|
+
Jekyll: `split: true`.
|
|
18
|
+
- `Builder#write(path)` writes one file without building the JSON in memory;
|
|
19
|
+
`Builder.read(path)` reads a file or a split index.
|
|
20
|
+
- Building keeps posting lists encoded and normalizes faster: 3,000 full
|
|
21
|
+
texts take 0.56 GB instead of 2.3 GB at peak, and 37 s instead of 62 s.
|
|
22
|
+
- Updating a loaded index is slower without YJIT (one update about 0.25 s at
|
|
23
|
+
17,000 records); one update and its write in `IndexFile` cost about the
|
|
24
|
+
same as before.
|
|
25
|
+
|
|
26
|
+
Variant tables:
|
|
27
|
+
|
|
28
|
+
- `ja`: 409 pairs (was 291), generated from the Jōyō Kanji Table, the
|
|
29
|
+
Jinmeiyō kanji list and Unihan kZVariant. 籐/藤, 聯/連 and 彎/湾 no longer
|
|
30
|
+
fold.
|
|
31
|
+
- New opt-in tables: `zh-safe` (Traditional/Simplified pairs that are
|
|
32
|
+
one-to-one both ways, so 後/后 and 發/髮 stay apart) and `ko` (old Hangul
|
|
33
|
+
in the Hanyang Private Use Area to standard jamo). `zh` is unchanged.
|
|
34
|
+
- `script/variant_tables.rb` generates the tables from their sources.
|
|
35
|
+
- The index records `variant_digest`, a digest of what its tables fold; Ruby
|
|
36
|
+
and the browser script refuse an index whose digest differs.
|
|
37
|
+
- The browser highlights matches in conjoining jamo, half-width kana with
|
|
38
|
+
sound marks and old Hangul in the Private Use Area.
|
|
39
|
+
|
|
40
|
+
More ways to build an index:
|
|
41
|
+
|
|
42
|
+
- `cjk_index` command: `build` (CSV, JSON or JSON Lines), `search`, `runtime`.
|
|
43
|
+
- `CJKIndex::RakeTask`.
|
|
44
|
+
- Bridgetown 2 plugin (`require "cjk_index/bridgetown"`).
|
|
45
|
+
- Examples for Bridgetown and Rails (`examples/`), notes in
|
|
46
|
+
`docs/notes/adapters.md`.
|
|
47
|
+
- Migration guide from lunr.js, in English and Japanese
|
|
48
|
+
(`docs/migrating-from-lunr.md`).
|
|
49
|
+
|
|
50
|
+
Filters:
|
|
51
|
+
|
|
52
|
+
- A `value` filter compares value ids instead of folded strings, in Ruby
|
|
53
|
+
and in the browser (#14): filtering 17,000 records by one author takes
|
|
54
|
+
1.7 ms instead of 2.7 ms.
|
|
55
|
+
|
|
56
|
+
Fixes:
|
|
57
|
+
|
|
58
|
+
- A `year` filter on a Time or Date (Jekyll gives a post's `date` as a Time)
|
|
59
|
+
gave no year.
|
|
60
|
+
- The Jekyll plugin gave the builder only the index fields of a collection
|
|
61
|
+
document, so a filter on another front-matter field was empty.
|
|
62
|
+
- A query word named like a JavaScript object member ("constructor") scored
|
|
63
|
+
differently in the browser than in Ruby.
|
|
64
|
+
|
|
3
65
|
## 0.2.0 (2026-10-28)
|
|
4
66
|
|
|
5
67
|
- Filters: `Builder.new(filters:)` with `value` and `year` filters;
|
data/LICENSE-Unicode
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
UNICODE LICENSE V3
|
|
2
|
+
|
|
3
|
+
COPYRIGHT AND PERMISSION NOTICE
|
|
4
|
+
|
|
5
|
+
Copyright © 1991-2026 Unicode, Inc.
|
|
6
|
+
|
|
7
|
+
NOTICE TO USER: Carefully read the following legal agreement. BY
|
|
8
|
+
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
|
|
9
|
+
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
|
|
10
|
+
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
|
|
11
|
+
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
14
|
+
copy of data files and any associated documentation (the "Data Files") or
|
|
15
|
+
software and any associated documentation (the "Software") to deal in the
|
|
16
|
+
Data Files or Software without restriction, including without limitation
|
|
17
|
+
the rights to use, copy, modify, merge, publish, distribute, and/or sell
|
|
18
|
+
copies of the Data Files or Software, and to permit persons to whom the
|
|
19
|
+
Data Files or Software are furnished to do so, provided that either (a)
|
|
20
|
+
this copyright and permission notice appear with all copies of the Data
|
|
21
|
+
Files or Software, or (b) this copyright and permission notice appear in
|
|
22
|
+
associated Documentation.
|
|
23
|
+
|
|
24
|
+
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
25
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
26
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
27
|
+
THIRD PARTY RIGHTS.
|
|
28
|
+
|
|
29
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
|
|
30
|
+
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
|
|
31
|
+
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
32
|
+
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
33
|
+
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
|
|
34
|
+
FILES OR SOFTWARE.
|
|
35
|
+
|
|
36
|
+
Except as contained in this notice, the name of a copyright holder shall
|
|
37
|
+
not be used in advertising or otherwise to promote the sale, use or other
|
|
38
|
+
dealings in these Data Files or Software without prior written
|
|
39
|
+
authorization of the copyright holder.
|
data/NOTICE
CHANGED
|
@@ -5,3 +5,20 @@ data/zh-hant-hans.tsv is derived from OpenCC (https://github.com/BYVoid/OpenCC),
|
|
|
5
5
|
data/dictionary/TSCharacters.txt, Copyright (c) 2010-2026 Carbo Kuo and contributors,
|
|
6
6
|
licensed under the Apache License, Version 2.0 (see LICENSE-OpenCC).
|
|
7
7
|
Changes are described at the top of that file.
|
|
8
|
+
|
|
9
|
+
data/zh-hant-hans-safe.tsv is derived from OpenCC data/dictionary/TSCharacters.txt and
|
|
10
|
+
STCharacters.txt, under the same license and copyright as above.
|
|
11
|
+
|
|
12
|
+
data/ja-kyujitai.tsv is derived in part from the Unicode Han Database (Unihan), Unicode 18.0.0
|
|
13
|
+
(https://www.unicode.org/Public/18.0.0/ucd/Unihan.zip), Copyright (c) 1991-2026 Unicode, Inc.,
|
|
14
|
+
licensed under the Unicode License v3 (see LICENSE-Unicode). The fields used (kJapaneseOldVariant,
|
|
15
|
+
kJoyoKanji, kJinmeiyoKanji, kZVariant) record the Joyo Kanji Table (Cabinet Notice No. 2 of 2010)
|
|
16
|
+
and the Jinmeiyo Kanji of the Family Register Act Enforcement Regulations, which as official
|
|
17
|
+
notices and ordinances are not subject to copyright in Japan (Copyright Act, art. 13).
|
|
18
|
+
|
|
19
|
+
data/ko-hanyang-pua.tsv is converted from the table in the hypua crate by kiwiyou
|
|
20
|
+
(https://github.com/kiwiyou/hypua, commit 7e47655730d4cfea89564768ebb277b86072eef9), which its
|
|
21
|
+
author released under the Unlicense (a public domain dedication). The mapping is the same as that
|
|
22
|
+
of hypua2jamo by mete0r (LGPL-3.0-or-later code); both are based on the KTUG Hanyang PUA Table
|
|
23
|
+
Project (http://faq.ktug.org/faq/HanyangPuaTableProject), which states no license. See
|
|
24
|
+
docs/notes/variant-tables.md.
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# cjk_index
|
|
2
2
|
|
|
3
|
+
日本語の説明: [docs/ja/README.md](docs/ja/README.md)
|
|
4
|
+
|
|
3
5
|
Dictionary-free full-text search for Chinese, Japanese and Korean text, in
|
|
4
6
|
pure Ruby. Build the index in Ruby, then query it in Ruby (`CJKIndex::Searcher`)
|
|
5
7
|
or in the browser with a small script that has no dependencies. Both return
|
|
@@ -24,7 +26,8 @@ even when it is an exact title. cjk_index instead:
|
|
|
24
26
|
native extension (the same idea as [kensaku](https://github.com/whispcat/kensaku));
|
|
25
27
|
- folds variants on both sides: NFKC, lowercase, katakana → hiragana,
|
|
26
28
|
old-form kanji → modern form (「圖」→「図」), 々 expanded (「佐々木」→「佐佐木」),
|
|
27
|
-
and optionally Traditional ↔ Simplified Chinese (from OpenCC)
|
|
29
|
+
and optionally Traditional ↔ Simplified Chinese (from OpenCC) and old
|
|
30
|
+
Hangul in the Private Use Area;
|
|
28
31
|
- ranks with BM25 per field, with field boosts;
|
|
29
32
|
- marks matches in the original text (`highlight`, `excerpt`), even when the
|
|
30
33
|
query and the text differ only by these variants;
|
|
@@ -32,10 +35,13 @@ even when it is an exact title. cjk_index instead:
|
|
|
32
35
|
one typo;
|
|
33
36
|
- generates the browser script from the same tables as the Ruby code, so
|
|
34
37
|
indexing and querying cannot drift apart (checked by the test suite under
|
|
35
|
-
Node; the script also refuses an index built with other tables)
|
|
38
|
+
Node; the script also refuses an index built with other tables);
|
|
39
|
+
- splits a large index into a small manifest and shards that the browser
|
|
40
|
+
fetches only when a query needs them.
|
|
36
41
|
|
|
37
|
-
The browser script is about
|
|
38
|
-
with the Chinese table as well.
|
|
42
|
+
The browser script is about 9 KB gzipped with the Japanese table, 24 KB
|
|
43
|
+
with the Chinese table as well. Index it from Ruby, Jekyll, Bridgetown, a
|
|
44
|
+
Rake task or the command line.
|
|
39
45
|
|
|
40
46
|
How this compares with Pagefind, kensaku, lunr.js, rroonga, tantiny and others:
|
|
41
47
|
[docs/comparison.md](docs/comparison.md).
|
|
@@ -46,17 +52,18 @@ Safari: [bench/browser/](bench/browser/).
|
|
|
46
52
|
|
|
47
53
|
When to use it, and when not to:
|
|
48
54
|
|
|
49
|
-
- **Good fit:** catalogs, collection records
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
memory
|
|
59
|
-
|
|
55
|
+
- **Good fit:** catalogs, collection records, blog posts and full texts on
|
|
56
|
+
static sites, command-line tools, scripts and small apps; anywhere you want
|
|
57
|
+
nothing to install outside Ruby, or the same results in Ruby and the
|
|
58
|
+
browser. In one file, the 16,951-record Aozora Bunko catalog is 12.9 MB
|
|
59
|
+
gzipped; as a [split index](#large-collections-split-indexes), the browser
|
|
60
|
+
loads a 72 KB manifest and fetches about 40 KB per query, and 1,000 full
|
|
61
|
+
texts (33 MB gzipped in one file) need about the same.
|
|
62
|
+
- **Not a good fit:** frequent updates to a large index, or search served
|
|
63
|
+
continuously by a server. An update rewrites the whole index, and the index
|
|
64
|
+
is held in memory: building 3,000 full texts (35.6 million characters) takes
|
|
65
|
+
37 s and 0.56 GB. A native engine (rroonga, tantiny) or a database feature
|
|
66
|
+
(pg_bigm) is the better choice there.
|
|
60
67
|
|
|
61
68
|
## Ruby
|
|
62
69
|
|
|
@@ -147,9 +154,9 @@ gets the old index or the new one, never a partly written file. A reader
|
|
|
147
154
|
keeps the index it loaded until the file changes; `interval:` limits how
|
|
148
155
|
often it checks. Put several changes in one block to write once.
|
|
149
156
|
|
|
150
|
-
On the Aozora Bunko catalog (16,951 records
|
|
151
|
-
|
|
152
|
-
|
|
157
|
+
On the Aozora Bunko catalog (16,951 records), a check of an unchanged file
|
|
158
|
+
takes 0.09 ms, and an update about 0.5 s (about 2 s when another process
|
|
159
|
+
wrote last, as the file is read again).
|
|
153
160
|
[bench/index_file.rb](bench/index_file.rb). The lock is `flock`: use a local
|
|
154
161
|
disk, not NFS.
|
|
155
162
|
|
|
@@ -163,22 +170,37 @@ for 1,000 records, 0.24 s for 5,000, 0.7 s for 16,951. A record edited now
|
|
|
163
170
|
and then needs nothing special; put a few changes in one block; for an
|
|
164
171
|
import, build the index again and `write` it (11 s for 16,951 records).
|
|
165
172
|
|
|
166
|
-
|
|
173
|
+
## Large collections: split indexes
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
|
|
175
|
+
Indexes are written in format `cjk_index/4`: each posting list is a compact
|
|
176
|
+
string, about a third smaller gzipped than format 3 and three times smaller
|
|
177
|
+
before compression. Ruby and the browser script still read formats 2 and 3.
|
|
170
178
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
For full text or tens of thousands of records, write a split index: a small
|
|
180
|
+
manifest (refs, lengths, filters) and shards of about 32 KB that the browser
|
|
181
|
+
fetches only when a query needs them.
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
builder.write_split("assets/search") # index.json and the shards
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
const index = await CJKIndex.load("/assets/search/index.json");
|
|
189
|
+
const results = await index.searchAsync("銀河鉄道", { filter: { type: "小説" } });
|
|
190
|
+
// or: await index.prepare(query); index.search(query, options)
|
|
180
191
|
```
|
|
181
192
|
|
|
193
|
+
`searchAsync` also works on an index in one file, so a page can use it for
|
|
194
|
+
both. A blank query with a filter, `facets`, `highlight` and `excerpt` need
|
|
195
|
+
no shard. On 1,000 Aozora Bunko full texts (33 MB gzipped as one file), the
|
|
196
|
+
manifest is 28 KB and a query fetches 43 KB (median).
|
|
197
|
+
|
|
198
|
+
In Ruby, `CJKIndex::Searcher.load("assets/search")` reads shards as queries
|
|
199
|
+
need them, and `CJKIndex::Builder.read("assets/search")` loads a split index
|
|
200
|
+
to change it. Shard names are digests of their content, so they can be cached
|
|
201
|
+
for long; `write_split` removes the shards the new manifest no longer lists.
|
|
202
|
+
`IndexFile` always writes one file. Measurements: [bench/README.md](bench/README.md).
|
|
203
|
+
|
|
182
204
|
## Browser
|
|
183
205
|
|
|
184
206
|
```html
|
|
@@ -192,6 +214,7 @@ agri_6d032fb5 東京[帝國大學]農學部建物位置圖
|
|
|
192
214
|
var results = index.search("鳥瞰図", { filter: { type: "地図", date: { min: 1890, max: 1910 } } });
|
|
193
215
|
index.facets("type", results); // => [{ value: "地図", count: 12 }, ...]
|
|
194
216
|
});
|
|
217
|
+
// a split index: await index.searchAsync(query, options), see above
|
|
195
218
|
</script>
|
|
196
219
|
```
|
|
197
220
|
|
|
@@ -222,9 +245,14 @@ cjk_index:
|
|
|
222
245
|
type: value
|
|
223
246
|
subject: { kind: value, separator: ";" }
|
|
224
247
|
date: year
|
|
248
|
+
- name: texts
|
|
249
|
+
collection: texts
|
|
250
|
+
fields: [title, content]
|
|
251
|
+
split: true # -> assets/cjk-index/texts/index.json and shards
|
|
225
252
|
```
|
|
226
253
|
|
|
227
|
-
The runtime is written to `assets/cjk-index/cjk-index.js`.
|
|
254
|
+
The runtime is written to `assets/cjk-index/cjk-index.js`. Moving a site from
|
|
255
|
+
lunr.js: [docs/migrating-from-lunr.md](docs/migrating-from-lunr.md).
|
|
228
256
|
|
|
229
257
|
### CollectionBuilder
|
|
230
258
|
|
|
@@ -243,25 +271,120 @@ The preset follows CollectionBuilder's own search settings: fields with
|
|
|
243
271
|
column; set `filters:` to change them. A working example:
|
|
244
272
|
https://github.com/nakamura196/cb-ja-demo
|
|
245
273
|
|
|
274
|
+
## Bridgetown
|
|
275
|
+
|
|
276
|
+
Tested with Bridgetown 2.2.2. Node is not needed.
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
# config/initializers.rb
|
|
280
|
+
require "cjk_index/bridgetown"
|
|
281
|
+
|
|
282
|
+
Bridgetown.configure do |config|
|
|
283
|
+
init :cjk_index, indexes: [
|
|
284
|
+
{ name: "posts", collection: "posts", fields: %w[title content], boosts: { title: 3 },
|
|
285
|
+
filters: { category: "value", date: "year" } }
|
|
286
|
+
]
|
|
287
|
+
end
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
This writes `output/cjk-index/posts.json` and `output/cjk-index/cjk-index.js`.
|
|
291
|
+
Use `data:` and `ref:` instead of `collection:` for rows of
|
|
292
|
+
`src/_data/*.csv`. See [examples/bridgetown](examples/bridgetown).
|
|
293
|
+
|
|
294
|
+
## Command line and Rake
|
|
295
|
+
|
|
296
|
+
```console
|
|
297
|
+
$ cjk_index build items.csv --ref id --fields title,creator --boost title=3 --filter type --filter date=year -o index.json --runtime cjk-index.js
|
|
298
|
+
$ cjk_index search index.json 鳥瞰図 --filter type=地図 --filter date=1890..1910
|
|
299
|
+
$ cjk_index runtime --variants ja,zh-safe -o cjk-index.js
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
`build` reads CSV, a JSON array or JSON Lines, from a file or from standard
|
|
303
|
+
input (`-`). `--filter subject=value:";"` splits values on `;`. Add `--json`
|
|
304
|
+
to `search` for machine-readable results. CSV needs the `csv` gem, which is
|
|
305
|
+
no longer a default gem from Ruby 3.4.
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# Rakefile
|
|
309
|
+
require "cjk_index/rake_task"
|
|
310
|
+
|
|
311
|
+
CJKIndex::RakeTask.new(:search_index) do |t|
|
|
312
|
+
t.source = "data/items.csv" # or t.records = -> { Item.all.map(&:to_search) }
|
|
313
|
+
t.output = "public/search/items.json"
|
|
314
|
+
t.runtime = "public/search/cjk-index.js"
|
|
315
|
+
t.fields = %w[title creator]
|
|
316
|
+
t.boosts = { "title" => 3 }
|
|
317
|
+
t.filters = { "type" => "value", "date" => "year" }
|
|
318
|
+
end
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### A script with no dependencies
|
|
322
|
+
|
|
323
|
+
[examples/search_csv.rb](examples/search_csv.rb) searches a CSV catalog from
|
|
324
|
+
the command line, in about 40 lines of plain Ruby:
|
|
325
|
+
|
|
326
|
+
```console
|
|
327
|
+
$ ruby examples/search_csv.rb items.csv 实录 --ref objectid --variants ja,zh
|
|
328
|
+
12 results for 实录
|
|
329
|
+
jitsu_51ed985b 宣祖[実録] 第1帙 第1冊 巻2戊辰元年(1568)
|
|
330
|
+
...
|
|
331
|
+
$ ruby examples/search_csv.rb items.csv 帝国大学 --ref objectid
|
|
332
|
+
3 results for 帝国大学
|
|
333
|
+
agri_6d032fb5 東京[帝國大學]農學部建物位置圖
|
|
334
|
+
...
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Rails
|
|
338
|
+
|
|
339
|
+
[examples/rails](examples/rails) (Rails 8.1.4, tested with Puma and four
|
|
340
|
+
workers) keeps one index for all worker processes with `IndexFile`: an
|
|
341
|
+
initializer, a model concern that updates the index after each commit, a
|
|
342
|
+
search action with filters, and a Rake task that rebuilds the index.
|
|
343
|
+
Notes on all the adapters: [docs/notes/adapters.md](docs/notes/adapters.md).
|
|
344
|
+
|
|
246
345
|
## Variant tables
|
|
247
346
|
|
|
248
347
|
| name | folds | source |
|
|
249
348
|
|---|---|---|
|
|
250
|
-
| `ja` (default) |
|
|
251
|
-
| `zh` |
|
|
349
|
+
| `ja` (default) | 409 Japanese old forms and glyph variants → one form (圖→図, 證→証, 禱/祷, 剝/剥) | Jōyō Kanji Table (2010), Jinmeiyō kanji list and kZVariant, via Unihan 18.0 (Unicode License v3) |
|
|
350
|
+
| `zh-safe` | 2,767 Traditional → Simplified pairs that are one-to-one both ways | OpenCC (Apache-2.0) |
|
|
351
|
+
| `zh` | 3,202 Traditional → Simplified (as in 0.1) | OpenCC `TSCharacters.txt` (Apache-2.0); ambiguous entries dropped |
|
|
352
|
+
| `ko` | 5,660 old Hangul characters in the Hanyang Private Use Area → standard jamo | hypua table (Unlicense), from the KTUG Hanyang PUA Table Project |
|
|
252
353
|
|
|
253
354
|
With several tables, characters linked by any of them fold to one form,
|
|
254
|
-
preferring the table listed first (`[ja, zh]`: 圖, 図, 图 → 図).
|
|
255
|
-
|
|
256
|
-
|
|
355
|
+
preferring the table listed first (`[ja, zh-safe]`: 圖, 図, 图 → 図).
|
|
356
|
+
|
|
357
|
+
`zh` also merges characters that are distinct in Japanese and in
|
|
358
|
+
Traditional Chinese: 後 and 后, 發 and 髮 (both 发), 機 and 机. Combined with
|
|
359
|
+
`ja`, it merges 45 such groups of Jōyō and Jinmeiyō kanji. `zh-safe` leaves
|
|
360
|
+
those pairs out, so a Simplified query 发展 does not find 發展. Use `zh-safe`
|
|
361
|
+
for Japanese sites that should also match Simplified queries, and `zh` for
|
|
362
|
+
Chinese sites.
|
|
363
|
+
|
|
364
|
+
Hangul needs no table: precomposed syllables and conjoining jamo are folded
|
|
365
|
+
by Unicode normalization. `ko` is for old Hangul stored in the Private Use
|
|
366
|
+
Area by HWP and the Hanyang fonts; a query typed in standard jamo then finds
|
|
367
|
+
and highlights it.
|
|
368
|
+
|
|
369
|
+
Browser script size, gzipped: no table 6.3 KB, `ja` 9.0 KB, `ja, zh-safe`
|
|
370
|
+
24.1 KB, `ja, zh` 25.9 KB, `ja, ko` 36.1 KB.
|
|
371
|
+
|
|
372
|
+
The tables are UTF-8 TSV files in `data/` ("variant<TAB>folded", an optional
|
|
373
|
+
comment column, `#` comments); `script/variant_tables.rb` generates them from
|
|
374
|
+
their sources. Sources, rules and counts:
|
|
375
|
+
[docs/notes/variant-tables.md](docs/notes/variant-tables.md). An index
|
|
376
|
+
records a digest of what its tables fold, and Ruby and the browser script
|
|
377
|
+
refuse an index built with other table contents: rebuild the index after
|
|
378
|
+
changing tables or upgrading from 0.x.
|
|
257
379
|
|
|
258
380
|
## Status
|
|
259
381
|
|
|
260
|
-
0.
|
|
261
|
-
(https://rubygems.org/gems/cjk_index).
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
382
|
+
1.0. On RubyGems: `gem install cjk_index`
|
|
383
|
+
(https://rubygems.org/gems/cjk_index). Changes: [CHANGELOG.md](CHANGELOG.md).
|
|
384
|
+
Development is supported by the Ruby Association Grant 2026.
|
|
385
|
+
|
|
386
|
+
Not yet checked by a native reader: the `ko` table and the Korean examples
|
|
387
|
+
([docs/review/](docs/review/)). Reports are welcome.
|
|
265
388
|
|
|
266
389
|
## Development
|
|
267
390
|
|