ja-compromise 0.0.1 → 0.1.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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +367 -6
  3. package/builds/ja-compromise.cjs +4389 -2286
  4. package/builds/ja-compromise.min.js +1 -1
  5. package/builds/ja-compromise.mjs +1 -1
  6. package/package.json +36 -23
  7. package/src/01-one/conjugate/conjugate-adj.js +53 -0
  8. package/src/01-one/conjugate/conjugate-verb.js +145 -0
  9. package/src/01-one/conjugate/deconjugate.js +178 -0
  10. package/src/01-one/conjugate/index.js +13 -0
  11. package/src/01-one/conjugate/kana.js +38 -0
  12. package/src/01-one/conjugate/tags.js +85 -0
  13. package/src/01-one/conjugate/verb-class.js +105 -0
  14. package/src/01-one/lexicon/_data.js +30 -0
  15. package/src/01-one/lexicon/api.js +61 -0
  16. package/src/01-one/lexicon/lexicon.js +163 -0
  17. package/src/01-one/lexicon/misc.js +115 -0
  18. package/src/01-one/lexicon/plugin.js +20 -0
  19. package/src/01-one/numbers/api.js +202 -0
  20. package/src/01-one/numbers/kanji-number.js +69 -0
  21. package/src/01-one/numbers/to-kanji.js +66 -0
  22. package/src/01-one/output/compute/dict.js +13 -0
  23. package/src/01-one/output/compute/english.js +13 -0
  24. package/src/01-one/output/compute/root.js +30 -0
  25. package/src/01-one/output/debug/_color.js +16 -0
  26. package/src/01-one/output/debug/index.js +24 -0
  27. package/src/01-one/output/debug/tags.js +56 -0
  28. package/src/01-one/output/plugin.js +13 -0
  29. package/src/01-one/romanji/api.js +16 -0
  30. package/src/01-one/romanji/compute/index.js +36 -0
  31. package/src/01-one/romanji/compute/kanji-reading/index.js +91 -0
  32. package/src/01-one/romanji/compute/kanji-reading/readings.js +861 -0
  33. package/src/01-one/romanji/compute/kanji-reading/words.js +31 -0
  34. package/src/01-one/romanji/compute/toRomanji/hiragana-map.js +175 -0
  35. package/src/01-one/romanji/compute/toRomanji/index.js +84 -0
  36. package/src/01-one/romanji/compute/toRomanji/katakana-map.js +128 -0
  37. package/src/01-one/romanji/plugin.js +7 -0
  38. package/src/01-one/tokenizer/methods/join-numbers.js +32 -0
  39. package/src/01-one/tokenizer/methods/join-up.js +66 -0
  40. package/src/01-one/tokenizer/methods/lib.js +66 -0
  41. package/src/01-one/tokenizer/methods/naiive-split.js +88 -0
  42. package/src/01-one/tokenizer/methods/okurigana.js +58 -0
  43. package/src/01-one/tokenizer/methods/terms.js +143 -0
  44. package/src/01-one/tokenizer/methods/trie/build.js +13 -0
  45. package/src/01-one/tokenizer/methods/trie/split-up.js +29 -0
  46. package/src/01-one/tokenizer/methods/whitespace.js +44 -0
  47. package/src/01-one/tokenizer/plugin.js +13 -0
  48. package/src/02-two/preTagger/compute/01-script.js +44 -0
  49. package/src/02-two/preTagger/compute/02-particles.js +82 -0
  50. package/src/02-two/preTagger/compute/03-verbs.js +111 -0
  51. package/src/02-two/preTagger/compute/04-adjectives.js +43 -0
  52. package/src/02-two/preTagger/compute/05-people.js +22 -0
  53. package/src/02-two/preTagger/compute/06-numbers.js +80 -0
  54. package/src/02-two/preTagger/compute/07-dates.js +105 -0
  55. package/src/02-two/preTagger/compute/index.js +52 -0
  56. package/src/02-two/preTagger/plugin.js +9 -0
  57. package/src/02-two/tagset/plugin.js +12 -0
  58. package/src/02-two/tagset/tags/dates.js +58 -0
  59. package/src/02-two/tagset/tags/misc.js +91 -0
  60. package/src/02-two/tagset/tags/nouns.js +131 -0
  61. package/src/02-two/tagset/tags/particles.js +50 -0
  62. package/src/02-two/tagset/tags/values.js +68 -0
  63. package/src/02-two/tagset/tags/verbs.js +93 -0
  64. package/src/_lib.js +2 -0
  65. package/src/_version.js +1 -0
  66. package/src/index.js +82 -0
  67. package/types/index.d.ts +268 -0
  68. package/types/japanese.d.ts +159 -0
  69. package/types/misc.d.ts +92 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Spencer Kelly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -51,9 +51,12 @@ The goal of this project is to provide a small, basic, rule-based POS-tagger.
51
51
  ```js
52
52
  import nlp from 'ja-compromise'
53
53
 
54
- let doc = ldv('小さな子供は食料品店に歩いた')
54
+ let doc = nlp('小さな子供は食料品店に歩いた')
55
55
  doc.match('#Noun').out('array')
56
- // [ '', '食料品店']
56
+ // [ '子供', '食料品店' ]
57
+
58
+ doc.match('#Verb').json()[0].terms[0].tags
59
+ // [ 'Verb', 'PastTense' ]
57
60
  ```
58
61
 
59
62
 
@@ -62,18 +65,368 @@ doc.match('#Noun').out('array')
62
65
 
63
66
  またはブラウザで
64
67
  ```html
65
- <script src="https://unpkg.com/de-compromise"></script>
68
+ <script src="https://unpkg.com/ja-compromise"></script>
66
69
  <script>
67
- let txt = '小さな子供が食料品を買いました。 彼はとても怖がっていた'
70
+ let txt = '小さな子供が食料品を買いました。'
68
71
  let doc = jaCompromise(txt)
69
- console.log(doc.sentences(1).json())
70
- // { text:'小さな子供が食...', terms:[ ... ] }
72
+
73
+ console.log(doc.nouns().out('array'))
74
+ // [ '子供', '食料品' ]
75
+
76
+ console.log(doc.verbs().out('array'))
77
+ // [ '買いました。' ]
78
+
79
+ console.log(doc.compute('root').text('root'))
80
+ // '小さな子供が食料品を買う。'
71
81
  </script>
72
82
  ```
73
83
 
74
84
 
75
85
  see [en-compromise/api](https://github.com/spencermountain/compromise#api) for full API documentation.
76
86
 
87
+
88
+ <!-- spacer -->
89
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
90
+
91
+ ## 助詞 - particles
92
+ 日本語には前置詞がなく、助詞があります。
93
+
94
+ Japanese has no prepositions - it has 助詞, which follow the word they mark.
95
+ Which kind of particle it is tells you most of what you need to know about the
96
+ words around it, so each kind gets its own tag:
97
+
98
+ | tag | 種類 | examples |
99
+ |---|---|---|
100
+ | `#CaseParticle` | 格助詞 | が を に へ で と から より まで |
101
+ | `#TopicParticle` | 係助詞 | は も こそ さえ しか |
102
+ | `#AdverbialParticle` | 副助詞 | だけ ばかり ほど くらい など |
103
+ | `#ConjunctiveParticle` | 接続助詞 | て ば たら ながら ので のに けれど |
104
+ | `#SentenceParticle` | 終助詞 | か ね よ わ ぞ ぜ |
105
+ | `#AdnominalParticle` | 連体助詞 | の |
106
+ | `#QuotativeParticle` | 引用の と | と |
107
+
108
+ They all inherit `#Particle`, and the case-marking ones also answer to
109
+ `#Preposition`, so older matches keep working.
110
+
111
+ ```js
112
+ nlp('私は本を読む').match('#TopicParticle').text() // 'は'
113
+ nlp('私は本を読む').match('#Topic').text() // '私'
114
+ nlp('私は本を読む').match('#Object').text() // '本'
115
+ ```
116
+
117
+
118
+ <!-- spacer -->
119
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
120
+
121
+ ## 活用 - conjugation
122
+ Verb conjugation is rule-based - the verb's class (五段/一段/irregular) decides
123
+ everything else.
124
+
125
+ ```js
126
+ nlp.verbClass('書く') // 'godan'
127
+ nlp.verbClass('食べる') // 'ichidan'
128
+
129
+ nlp.conjugate('書く')
130
+ // {
131
+ // Infinitive: '書く', Stem: '書き', PastTense: '書いた',
132
+ // Negative: '書かない', Gerund: '書いて', Polite: '書きます',
133
+ // PolitePast: '書きました', Imperative: '書け', Volitional: '書こう',
134
+ // Potential: '書ける', Passive: '書かれる', Causative: '書かせる',
135
+ // Conditional: '書いたら', Provisional: '書けば', Desire: '書きたい', ..
136
+ // }
137
+
138
+ nlp.deconjugate('書きました')
139
+ // { root: '書く', tags: [ 'Verb', 'PastTense', 'Polite' ] }
140
+ ```
141
+
142
+ い-adjectives conjugate too - they carry tense themselves, without the copula:
143
+
144
+ ```js
145
+ nlp('この本は高かった').match('#Adjective').json()[0].terms[0].tags
146
+ // [ 'Adjective', 'IAdjective', 'PastTense' ]
147
+ ```
148
+
149
+ `.compute('root')` puts every word back in its dictionary-form:
150
+
151
+ ```js
152
+ nlp('映画を見ました。').compute('root').text('root')
153
+ // '映画を見る。'
154
+ ```
155
+
156
+
157
+ <!-- spacer -->
158
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
159
+
160
+ ## 数 - numbers
161
+ The same methods as english compromise, and the same split between reading a
162
+ number and rewriting one:
163
+
164
+ ```js
165
+ let doc = nlp('本を二十三冊買った。')
166
+
167
+ doc.numbers().get() // [ 23 ] - read it
168
+ doc.numbers().units().text() // '冊' - its counter
169
+
170
+ doc.numbers().toNumber()
171
+ doc.text() // '本を23冊買った。' - rewrite in digits
172
+
173
+ nlp('本を23冊買った。').numbers().toText().all().text()
174
+ // '本を二十三冊買った。' - rewrite in kanji
175
+ ```
176
+
177
+ Japanese numerals are fully compositional - 23 is 二十三, literally
178
+ "two-ten-three" - so both directions are exact. Every number from 0 to 20,000
179
+ round-trips through both.
180
+
181
+ ```js
182
+ nlp.toNumber('三百二十一') // 321
183
+ nlp.toKanji(1995) // '千九百九十五'
184
+ nlp.toKanji(500000) // '五十万' (japanese groups by 10,000, not 1,000)
185
+ ```
186
+
187
+ Arithmetic keeps whichever script it found:
188
+
189
+ ```js
190
+ nlp('本を五冊買った').numbers().add(10).all().text() // '本を十五冊買った'
191
+ nlp('23人').numbers().subtract(2).all().text() // '21人'
192
+ ```
193
+
194
+ `.values()` is an alias for `.numbers()`, and `.money()`, `.percentages()`,
195
+ `.isOrdinal()`, `.isCardinal()`, `.greaterThan()`, `.lessThan()`, `.between()`,
196
+ `.set()`, `.increment()` and `.toLocaleString()` all work as they do in english.
197
+
198
+
199
+ <!-- spacer -->
200
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
201
+
202
+ ## 助数詞 - counters
203
+ Japanese can't count a noun directly - it's 本を三冊, never 三本. The counter
204
+ says what *kind* of thing is being counted, so it's the nearest thing to a unit:
205
+
206
+ | counter | for |
207
+ |---|---|
208
+ | 本 | long thin things - pens, bottles |
209
+ | 枚 | flat things - paper, plates |
210
+ | 冊 | bound things - books |
211
+ | 匹 | small animals |
212
+ | 人 | people |
213
+
214
+ A counter is only a counter when a number is in front of it - 本 is a book far
215
+ more often than it's the counter for long thin things:
216
+
217
+ ```js
218
+ nlp('本を五冊買った').counters().text() // '冊' (not 本)
219
+ ```
220
+
221
+ <!-- spacer -->
222
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
223
+
224
+ ## 日付 - dates
225
+ Dates are built out of number + counter, so `年`, `月` and `日` need context -
226
+ they're the same word whether they mean a date or a span of time:
227
+
228
+ ```js
229
+ nlp('1995年3月10日の午後3時').dates().out('array')
230
+ // [ '1995年3月10日', '午後3時' ]
231
+
232
+ nlp('3月').match('#Month').found // true - march
233
+ nlp('三ヶ月').match('#Duration').found // true - three months
234
+ nlp('五十年').match('#Year').found // false - fifty years, not the year 50
235
+ ```
236
+
237
+ `#Date` covers `#Year`, `#Month`, `#Day`, `#WeekDay`, `#Time`, `#Season`,
238
+ `#Duration` and `#Era` (令和5年).
239
+
240
+
241
+ <!-- spacer -->
242
+ <img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
243
+
244
+ ## 分かち書き - tokenizing
245
+ Japanese isn't written with spaces, so the tokenizer segments by longest-match
246
+ against the lexicon, then repairs what that gets wrong:
247
+
248
+ ```js
249
+ nlp('本を読んでいる人').terms().out('array')
250
+ // [ '本', 'を', '読んでいる', '人' ]
251
+
252
+ // an unknown verb is still one word - 含む isn't in the lexicon
253
+ nlp('含まれている').terms().out('array')
254
+ // [ '含まれている' ]
255
+ ```
256
+
257
+ Run `npm run score` to check segmentation and tagging against
258
+ [learn/test/gold.js](./learn/test/gold.js).
259
+
260
+
261
+ ## API
262
+ ja-compromise には、`compromise/one` のすべてのメソッドが含まれます:
263
+
264
+ ##### 日本語のメソッド / japanese-specific
265
+
266
+ | | |
267
+ |---|---|
268
+ | `.verbs()` | every 動詞 in the document |
269
+ | `.nouns()` | every 名詞 |
270
+ | `.adjectives()` | every 形容詞 and 形容動詞 |
271
+ | `.particles()` | every 助詞 |
272
+ | `.romanji()` | the document sounded-out in the latin alphabet |
273
+ | `.toInfinitive()` | the dictionary-form of each match |
274
+ | `.compute('root')` | set each term's dictionary-form |
275
+ | `nlp.conjugate(verb)` | the full paradigm of a dictionary-form verb |
276
+ | `nlp.deconjugate(word)` | walk a conjugated verb back to its dictionary-form |
277
+ | `nlp.conjugateAdjective(word)` | the paradigm of an い- or な-adjective |
278
+ | `nlp.verbClass(verb)` | `'godan'`, `'ichidan'`, `'suru'`, .. |
279
+ | `.numbers()` / `.values()` | every number |
280
+ | `.numbers().get()` | 「二十三」 → `23` |
281
+ | `.numbers().toNumber()` | rewrite 二十三 as `23` |
282
+ | `.numbers().toText()` | rewrite `23` as 二十三 |
283
+ | `.numbers().units()` | the 助数詞 for each number |
284
+ | `.counters()` | every 助数詞 |
285
+ | `.dates()` | every date, time and duration |
286
+ | `nlp.toNumber(numeral)` | 「二十三」 → `23` |
287
+ | `nlp.toKanji(num)` | `23` → 「二十三」 |
288
+
289
+ TypeScript declarations ship with the package - see [types/](./types).
290
+
291
+
292
+ <details>
293
+ <summary><h3>クリックして API メソッドを表示</h3></summary>
294
+
295
+ ##### Output
296
+
297
+ - **[.text()](https://observablehq.com/@spencermountain/compromise-text)** - return the document as text
298
+ - **[.json()](https://observablehq.com/@spencermountain/compromise-json)** - return the document as data
299
+ - **[.debug()](https://observablehq.com/@spencermountain/compromise-output)** - pretty-print the interpreted document
300
+ - **[.out()](https://observablehq.com/@spencermountain/compromise-output)** - a named or custom output
301
+ - **[.html({})](https://observablehq.com/@spencermountain/compromise-html)** - output custom html tags for matches
302
+ - **[.wrap({})](https://observablehq.com/@spencermountain/compromise-output)** - produce custom output for document matches
303
+
304
+ ##### Utils
305
+
306
+ - **[.found](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - is this document empty?
307
+ - **[.docs](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ get term objects as json
308
+ - **[.length](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - count the # of characters in the document (string length)
309
+ - **[.isView](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - identify a compromise object
310
+ - **[.compute()](https://observablehq.com/@spencermountain/compromise-compute)** - run a named analysis on the document
311
+ - **[.clone()](https://observablehq.com/@spencermountain/compromise-utils)** - deep-copy the document, so that no references remain
312
+ - **[.termList()](https://observablehq.com/@spencermountain/compromise-accessors)** - return a flat list of all Term objects in match
313
+ - **[.cache({})](https://observablehq.com/@spencermountain/compromise-cache)** - freeze the current state of the document, for speed-purposes
314
+ - **[.uncache()](https://observablehq.com/@spencermountain/compromise-cache)** - un-freezes the current state of the document, so it may be transformed
315
+
316
+ ##### Accessors
317
+
318
+ - **[.all()](https://observablehq.com/@spencermountain/compromise-utils)** - return the whole original document ('zoom out')
319
+ - **[.terms()](https://observablehq.com/@spencermountain/compromise-selections)** - split-up results by each individual term
320
+ - **[.first(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the first result(s)
321
+ - **[.last(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the last result(s)
322
+ - **[.slice(n,n)](https://observablehq.com/@spencermountain/compromise-accessors)** - grab a subset of the results
323
+ - **[.eq(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - use only the nth result
324
+ - **[.firstTerms()](https://observablehq.com/@spencermountain/compromise-accessors)** - get the first word in each match
325
+ - **[.lastTerms()](https://observablehq.com/@spencermountain/compromise-accessors)** - get the end word in each match
326
+ - **[.fullSentences()](https://observablehq.com/@spencermountain/compromise-accessors)** - get the whole sentence for each match
327
+ - **[.groups()](https://observablehq.com/@spencermountain/compromise-accessors)** - grab any named capture-groups from a match
328
+ - **[.wordCount()](https://observablehq.com/@spencermountain/compromise-utils)** - count the # of terms in the document
329
+
330
+ ##### Match
331
+
332
+ _(match methods use the [match-syntax](https://docs.compromise.cool/compromise-match-syntax).)_
333
+
334
+ - **[.match('')](https://observablehq.com/@spencermountain/compromise-match)** - return a new Doc, with this one as a parent
335
+ - **[.not('')](https://observablehq.com/@spencermountain/compromise-match)** - return all results except for this
336
+ - **[.matchOne('')](https://observablehq.com/@spencermountain/compromise-match)** - return only the first match
337
+ - **[.if('')](https://observablehq.com/@spencermountain/compromise-match)** - return each current phrase, only if it contains this match ('only')
338
+ - **[.ifNo('')](https://observablehq.com/@spencermountain/compromise-match)** - Filter-out any current phrases that have this match ('notIf')
339
+ - **[.has('')](https://observablehq.com/@spencermountain/compromise-match)** - Return a boolean if this match exists
340
+ - **[.before('')](https://observablehq.com/@spencermountain/compromise-match)** - return all terms before a match, in each phrase
341
+ - **[.after('')](https://observablehq.com/@spencermountain/compromise-match)** - return all terms after a match, in each phrase
342
+ - **[.union()](https://observablehq.com/@spencermountain/compromise-pointers)** - return combined matches without duplicates
343
+ - **[.intersection()](https://observablehq.com/@spencermountain/compromise-pointers)** - return only duplicate matches
344
+ - **[.complement()](https://observablehq.com/@spencermountain/compromise-pointers)** - get everything not in another match
345
+ - **[.settle()](https://observablehq.com/@spencermountain/compromise-pointers)** - remove overlaps from matches
346
+ - **[.growRight('')](https://observablehq.com/@spencermountain/compromise-match)** - add any matching terms immediately after each match
347
+ - **[.growLeft('')](https://observablehq.com/@spencermountain/compromise-match)** - add any matching terms immediately before each match
348
+ - **[.grow('')](https://observablehq.com/@spencermountain/compromise-match)** - add any matching terms before or after each match
349
+ - **[.sweep(net)](https://observablehq.com/@spencermountain/compromise-sweep)** - apply a series of match objects to the document
350
+ - **[.splitOn('')](https://observablehq.com/@spencermountain/compromise-split)** - return a Document with three parts for every match ('splitOn')
351
+ - **[.splitBefore('')](https://observablehq.com/@spencermountain/compromise-split)** - partition a phrase before each matching segment
352
+ - **[.splitAfter('')](https://observablehq.com/@spencermountain/compromise-split)** - partition a phrase after each matching segment
353
+ - **[.lookup([])](https://observablehq.com/@spencermountain/compromise-match)** - quick find for an array of string matches
354
+ - **[.autoFill()](https://observablehq.com/@spencermountain/compromise-typeahead)** - create type-ahead assumptions on the document
355
+
356
+ ##### Tag
357
+
358
+ - **[.tag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Give all terms the given tag
359
+ - **[.tagSafe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Only apply tag to terms if it is consistent with current tags
360
+ - **[.unTag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - Remove this term from the given terms
361
+ - **[.canBe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - return only the terms that can be this tag
362
+
363
+ ##### Case
364
+
365
+ - **[.toLowerCase()](https://observablehq.com/@spencermountain/compromise-case)** - turn every letter of every term to lower-cse
366
+ - **[.toUpperCase()](https://observablehq.com/@spencermountain/compromise-case)** - turn every letter of every term to upper case
367
+ - **[.toTitleCase()](https://observablehq.com/@spencermountain/compromise-case)** - upper-case the first letter of each term
368
+ - **[.toCamelCase()](https://observablehq.com/@spencermountain/compromise-case)** - remove whitespace and title-case each term
369
+
370
+ ##### Whitespace
371
+
372
+ - **[.pre('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - add this punctuation or whitespace before each match
373
+ - **[.post('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - add this punctuation or whitespace after each match
374
+ - **[.trim()](https://observablehq.com/@spencermountain/compromise-whitespace)** - remove start and end whitespace
375
+ - **[.hyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - connect words with hyphen, and remove whitespace
376
+ - **[.dehyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - remove hyphens between words, and set whitespace
377
+ - **[.toQuotations()](https://observablehq.com/@spencermountain/compromise-whitespace)** - add quotation marks around these matches
378
+ - **[.toParentheses()](https://observablehq.com/@spencermountain/compromise-whitespace)** - add brackets around these matches
379
+
380
+ ##### Loops
381
+
382
+ - **[.map(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - run each phrase through a function, and create a new document
383
+ - **[.forEach(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - run a function on each phrase, as an individual document
384
+ - **[.filter(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return only the phrases that return true
385
+ - **[.find(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return a document with only the first phrase that matches
386
+ - **[.some(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - return true or false if there is one matching phrase
387
+ - **[.random(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - sample a subset of the results
388
+
389
+ ##### Insert
390
+
391
+ - **[.replace(match, replace)](https://observablehq.com/@spencermountain/compromise-insert)** - search and replace match with new content
392
+ - **[.replaceWith(replace)](https://observablehq.com/@spencermountain/compromise-insert)** - substitute-in new text
393
+ - **[.remove()](https://observablehq.com/@spencermountain/compromise-insert)** - fully remove these terms from the document
394
+ - **[.insertBefore(str)](https://observablehq.com/@spencermountain/compromise-insert)** - add these new terms to the front of each match (prepend)
395
+ - **[.insertAfter(str)](https://observablehq.com/@spencermountain/compromise-insert)** - add these new terms to the end of each match (append)
396
+ - **[.concat()](https://observablehq.com/@spencermountain/compromise-insert)** - add these new things to the end
397
+
398
+ ##### Transform
399
+
400
+ - **[.sort('method')](https://observablehq.com/@spencermountain/compromise-sorting)** - re-arrange the order of the matches (in place)
401
+ - **[.reverse()](https://observablehq.com/@spencermountain/compromise-sorting)** - reverse the order of the matches, but not the words
402
+ - **[.unique()](https://observablehq.com/@spencermountain/compromise-sorting)** - remove any duplicate matches
403
+
404
+
405
+ ##### Lib
406
+
407
+ _(these methods are on the main `nlp` object)_
408
+
409
+ - **[nlp.tokenize(str)](https://observablehq.com/@spencermountain/compromise-tokenization)** - parse text without running POS-tagging
410
+ - **[nlp.lazy(str, match)](https://observablehq.com/@spencermountain/compromise-performance)** - scan through a text with minimal analysis
411
+ - **[nlp.plugin({})](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - mix in a compromise-plugin
412
+ - **[nlp.parseMatch(str)](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - pre-parse any match statements into json
413
+ - **[nlp.world()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - grab or change library internals
414
+ - **[nlp.model()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - grab all current linguistic data
415
+ - **[nlp.methods()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - grab or change internal methods
416
+ - **[nlp.hooks()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - see which compute methods run automatically
417
+ - **[nlp.verbose(mode)](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - log our decision-making for debugging
418
+ - **[nlp.version](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - current semver version of the library
419
+
420
+ - **[nlp.addWords(obj)](https://observablehq.com/@spencermountain/compromise-plugin)** - add new words to the lexicon
421
+ - **[nlp.addTags(obj)](https://observablehq.com/@spencermountain/compromise-plugin)** - add new tags to the tagSet
422
+ - **[nlp.typeahead(arr)](https://observablehq.com/@spencermountain/compromise-typeahead)** - add words to the auto-fill dictionary
423
+ - **[nlp.buildTrie(arr)](https://observablehq.com/@spencermountain/compromise-lookup)** - compile a list of words into a fast lookup form
424
+ - **[nlp.buildNet(arr)](https://observablehq.com/@spencermountain/compromise-sweep)** - compile a list of matches into a fast match form
425
+
426
+ <!-- spacer -->
427
+ <img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
428
+ </details>
429
+
77
430
  参加して助けてください! - please join to help!
78
431
 
79
432
  ### 指示: / Contributing
@@ -85,6 +438,14 @@ npm test
85
438
  npm watch
86
439
  ```
87
440
 
441
+ ### 制限 / Known gaps
442
+ * kanji readings are per-character with a small override table, so romanization
443
+ of unfamiliar compounds is often wrong
444
+ * segmentation is greedy longest-match, with no way to weigh one reading of an
445
+ ambiguous kana string against another
446
+ * compound verbs (吐き出す) split at the first stem unless they're in the lexicon
447
+ * personal names are found from an honorific suffix, not from a name-list
448
+
88
449
  ### See also
89
450
  * [spacy/japanese](https://spacy.io/models/ja) - python tagger/tokenizer, by [explosionAI](https://explosion.ai/)
90
451
  * [meCab](https://taku910.github.io/mecab/) - C/C++ tokenizer/tagger, by Taku Kudo