japanese_address_parser 3.1.0 → 3.1.1

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.
@@ -9,21 +9,51 @@ import {
9
9
  getCityRegexPatterns,
10
10
  getTownRegexPatterns,
11
11
  getSameNamedPrefectureCityRegexPatterns,
12
+ // interface version 1
12
13
  getResidentials,
13
14
  getGaikuList,
15
+ // interface version 2
16
+ getAddrs,
17
+ PrefectureList,
18
+ TownList,
19
+ AddrList,
14
20
  } from './lib/cacheRegexes'
15
21
  import unfetch from 'isomorphic-unfetch'
16
22
 
23
+ type TransformRequestResponse = null | PrefectureList | TownList | AddrList
24
+
25
+ export type TransformRequestQuery = {
26
+ level: number // level = -1 は旧 API。 transformRequestFunction を設定しても無視する
27
+ pref?: string
28
+ city?: string
29
+ town?: string
30
+ }
31
+
32
+ export type TransformRequestFunction = (
33
+ url: URL,
34
+ query: TransformRequestQuery,
35
+ ) => TransformRequestResponse | Promise<TransformRequestResponse>
36
+
17
37
  /**
18
38
  * normalize {@link Normalizer} の動作オプション。
19
39
  */
20
40
  export interface Config {
41
+ /**
42
+ * レスポンス型のバージョン。デフォルト 1
43
+ * 1 の場合は jyukyo: string, gaiku: string
44
+ * 2 の場合は addr: string, other: string
45
+ */
46
+ interfaceVersion: number
47
+
21
48
  /** 住所データを URL 形式で指定。 file:// 形式で指定するとローカルファイルを参照できます。 */
22
49
  japaneseAddressesApi: string
23
50
 
24
51
  /** 町丁目のデータを何件までキャッシュするか。デフォルト 1,000 */
25
52
  townCacheSize: number
26
53
 
54
+ /** 住所データへのリクエストを変形するオプション。 interfaceVersion === 2 で有効 */
55
+ transformRequest?: TransformRequestFunction
56
+
27
57
  geoloniaApiKey?: string
28
58
  }
29
59
  export const config: Config = currentConfig
@@ -31,7 +61,7 @@ export const config: Config = currentConfig
31
61
  /**
32
62
  * 住所の正規化結果として戻されるオブジェクト
33
63
  */
34
- export interface NormalizeResult {
64
+ interface NormalizeResult_v1 {
35
65
  /** 都道府県 */
36
66
  pref: string
37
67
  /** 市区町村 */
@@ -60,6 +90,34 @@ export interface NormalizeResult {
60
90
  level: number
61
91
  }
62
92
 
93
+ type NormalizeResult_v2 = {
94
+ /** 都道府県 */
95
+ pref: string
96
+ /** 市区町村 */
97
+ city: string
98
+ /** 町丁目 */
99
+ town: string
100
+ /** 住居表示または地番 */
101
+ addr: string
102
+ /** 正規化後の住所文字列 */
103
+ other?: string
104
+ /** 緯度。データが存在しない場合は null */
105
+ lat: number | null
106
+ /** 経度。データが存在しない場合は null */
107
+ lng: number | null
108
+ /**
109
+ * 住所文字列をどこまで判別できたかを表す正規化レベル
110
+ * - 0 - 都道府県も判別できなかった。
111
+ * - 1 - 都道府県まで判別できた。
112
+ * - 2 - 市区町村まで判別できた。
113
+ * - 3 - 町丁目まで判別できた。
114
+ * - 8 - 住居表示住所の街区符号・住居番号までの判別または地番住所の判別ができた。
115
+ */
116
+ level: number
117
+ }
118
+
119
+ export type NormalizeResult = NormalizeResult_v1 | NormalizeResult_v2
120
+
63
121
  /**
64
122
  * 正規化関数の {@link normalize} のオプション
65
123
  */
@@ -92,6 +150,7 @@ export type Normalizer = (
92
150
 
93
151
  export type FetchLike = (
94
152
  input: string,
153
+ requestQuery?: TransformRequestQuery,
95
154
  ) => Promise<Response | { json: () => Promise<unknown> }>
96
155
 
97
156
  const defaultOption = {
@@ -143,7 +202,13 @@ const normalizeResidentialPart = async (
143
202
  pref: string,
144
203
  city: string,
145
204
  town: string,
146
- ) => {
205
+ ): Promise<{
206
+ gaiku: string
207
+ jyukyo?: string
208
+ addr: string
209
+ lat: string
210
+ lng: string
211
+ } | null> => {
147
212
  const [gaikuListItem, residentials] = await Promise.all([
148
213
  getGaikuList(pref, city, town),
149
214
  getResidentials(pref, city, town),
@@ -183,6 +248,27 @@ const normalizeResidentialPart = async (
183
248
  return null
184
249
  }
185
250
 
251
+ const normalizeAddrPart = async (
252
+ addr: string,
253
+ pref: string,
254
+ city: string,
255
+ town: string,
256
+ ) => {
257
+ const addrListItem = await getAddrs(pref, city, town)
258
+
259
+ // 住居表示住所、および地番住所が見つからなかった
260
+ if (addrListItem.length === 0) {
261
+ return null
262
+ }
263
+
264
+ const addrItem = addrListItem.find((item) => addr.startsWith(item.addr))
265
+ if (addrItem) {
266
+ const other = addr.replace(addrItem.addr, '').trim()
267
+ return { addr: addrItem.addr, other, lat: addrItem.lat, lng: addrItem.lng }
268
+ }
269
+ return null
270
+ }
271
+
186
272
  export const normalize: Normalizer = async (
187
273
  address,
188
274
  _option = defaultOption,
@@ -378,7 +464,7 @@ export const normalize: Normalizer = async (
378
464
  // `-1` のようなケース
379
465
  return kan2num(s)
380
466
  })
381
- .replace(/-[^0-9]+([0-9〇一二三四五六七八九十百千]+)/, (s) => {
467
+ .replace(/-[^0-9]([0-9〇一二三四五六七八九十百千]+)/, (s) => {
382
468
  // `-あ1` のようなケース
383
469
  return kan2num(zen2han(s))
384
470
  })
@@ -392,43 +478,85 @@ export const normalize: Normalizer = async (
392
478
 
393
479
  addr = patchAddr(pref, city, town, addr)
394
480
 
395
- // 住居表示住所リストを使い番地号までの正規化を行う
396
- if (option.level > 3 && normalized && town) {
397
- normalized = await normalizeResidentialPart(addr, pref, city, town)
398
- }
399
- if (normalized) {
400
- lat = parseFloat(normalized.lat)
401
- lng = parseFloat(normalized.lng)
402
- }
403
-
404
- if (Number.isNaN(lat) || Number.isNaN(lng)) {
405
- lat = null
406
- lng = null
407
- }
408
-
409
481
  if (pref) level = level + 1
410
482
  if (city) level = level + 1
411
483
  if (town) level = level + 1
412
484
 
413
- const result: NormalizeResult = {
414
- pref,
415
- city,
416
- town,
417
- addr,
418
- lat,
419
- lng,
420
- level,
485
+ if (option.level <= 3 || level < 3) {
486
+ return { pref, city, town, addr, level, lat, lng }
421
487
  }
422
488
 
423
- if (normalized && 'gaiku' in normalized) {
424
- result.addr = normalized.addr
425
- result.gaiku = normalized.gaiku
426
- result.level = 7
427
- }
428
- if (normalized && 'jyukyo' in normalized) {
429
- result.jyukyo = normalized.jyukyo
430
- result.level = 8
431
- }
489
+ // ======================== Advanced section ========================
490
+ // これ以下は地番住所または住居表示住所までの正規化・ジオコーディングを行う処理
491
+ // 現状、インターフェース v1 と v2 が存在する
492
+ // japanese-addresses のフォーマット、および normalize 関数の戻り値が異なる
493
+ // 将来的に v2 に統一することを検討中
494
+ // ==================================================================
495
+
496
+ // v2 のインターフェース
497
+ if (currentConfig.interfaceVersion === 2) {
498
+ const normalizedAddrPart = await normalizeAddrPart(addr, pref, city, town)
499
+ let other = undefined
500
+ if (normalizedAddrPart) {
501
+ addr = normalizedAddrPart.addr
502
+ if (normalizedAddrPart.other) {
503
+ other = normalizedAddrPart.other
504
+ }
505
+ if (normalizedAddrPart.lat !== null)
506
+ lat = parseFloat(normalizedAddrPart.lat)
507
+ if (normalizedAddrPart.lng !== null)
508
+ lng = parseFloat(normalizedAddrPart.lng)
509
+ level = 8
510
+ }
511
+ const result: NormalizeResult_v2 = {
512
+ pref,
513
+ city,
514
+ town,
515
+ addr,
516
+ level,
517
+ lat,
518
+ lng,
519
+ }
520
+ if (other) {
521
+ result.other = other
522
+ }
523
+ return result
524
+ } else if (currentConfig.interfaceVersion === 1) {
525
+ // 住居表示住所リストを使い番地号までの正規化を行う
526
+ if (option.level > 3 && normalized && town) {
527
+ normalized = await normalizeResidentialPart(addr, pref, city, town)
528
+ }
529
+ if (normalized) {
530
+ lat = parseFloat(normalized.lat)
531
+ lng = parseFloat(normalized.lng)
532
+ }
533
+
534
+ if (Number.isNaN(lat) || Number.isNaN(lng)) {
535
+ lat = null
536
+ lng = null
537
+ }
538
+
539
+ const result: NormalizeResult_v1 = {
540
+ pref,
541
+ city,
542
+ town,
543
+ addr,
544
+ lat,
545
+ lng,
546
+ level,
547
+ }
548
+ if (normalized && 'gaiku' in normalized) {
549
+ result.addr = normalized.addr
550
+ result.gaiku = normalized.gaiku
551
+ result.level = 7
552
+ }
553
+ if (normalized && 'jyukyo' in normalized) {
554
+ result.jyukyo = normalized.jyukyo
555
+ result.level = 8
556
+ }
432
557
 
433
- return result
558
+ return result
559
+ } else {
560
+ throw new Error('invalid interfaceVersion')
561
+ }
434
562
  }
data/js/package-lock.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "": {
7
7
  "name": "japanese_address_parser",
8
8
  "dependencies": {
9
- "@geolonia/normalize-japanese-addresses": "^2.8.0"
9
+ "@geolonia/normalize-japanese-addresses": "^2.9.2"
10
10
  },
11
11
  "devDependencies": {}
12
12
  },
@@ -16,9 +16,9 @@
16
16
  "integrity": "sha512-xzSsIHhyyjqNpW8qSh5bFMu3FJvyJGBbNZ/t8clPHkigjUdZ7Ck8wkzCkcwlVd00RkoHwGDLnvXx5W0WiGK0TQ=="
17
17
  },
18
18
  "node_modules/@geolonia/normalize-japanese-addresses": {
19
- "version": "2.8.0",
20
- "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.8.0.tgz",
21
- "integrity": "sha512-BNKTl+38nq+ZKABa9nmwixLyDTXDPYDWSG3DluTjvhog3LEVWcTOHy0taIWXpumlvoz67ingq2qxdjtvW8ktzQ==",
19
+ "version": "2.9.2",
20
+ "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.9.2.tgz",
21
+ "integrity": "sha512-sbeV/seJ/ue6pn2sLo+Ccunl6eB3yNhrUIzNpT2IiR9Fw6fW5f1lLdApODqhTmz++xr1dyPwZOzTXCGEaXejDA==",
22
22
  "dependencies": {
23
23
  "@geolonia/japanese-numeral": "^0.1.16",
24
24
  "isomorphic-unfetch": "^3.1.0",
@@ -101,9 +101,9 @@
101
101
  "integrity": "sha512-xzSsIHhyyjqNpW8qSh5bFMu3FJvyJGBbNZ/t8clPHkigjUdZ7Ck8wkzCkcwlVd00RkoHwGDLnvXx5W0WiGK0TQ=="
102
102
  },
103
103
  "@geolonia/normalize-japanese-addresses": {
104
- "version": "2.8.0",
105
- "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.8.0.tgz",
106
- "integrity": "sha512-BNKTl+38nq+ZKABa9nmwixLyDTXDPYDWSG3DluTjvhog3LEVWcTOHy0taIWXpumlvoz67ingq2qxdjtvW8ktzQ==",
104
+ "version": "2.9.2",
105
+ "resolved": "https://registry.npmjs.org/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-2.9.2.tgz",
106
+ "integrity": "sha512-sbeV/seJ/ue6pn2sLo+Ccunl6eB3yNhrUIzNpT2IiR9Fw6fW5f1lLdApODqhTmz++xr1dyPwZOzTXCGEaXejDA==",
107
107
  "requires": {
108
108
  "@geolonia/japanese-numeral": "^0.1.16",
109
109
  "isomorphic-unfetch": "^3.1.0",
data/js/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": true,
4
4
  "description": "JapaneseAddressParserは日本の住所をパースすることができるRuby gemです。",
5
5
  "dependencies": {
6
- "@geolonia/normalize-japanese-addresses": "^2.8.0"
6
+ "@geolonia/normalize-japanese-addresses": "^2.9.2"
7
7
  },
8
8
  "devDependencies": {}
9
9
  }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JapaneseAddressParser
4
- VERSION = '3.1.0'
4
+ VERSION = '3.1.1'
5
5
  public_constant :VERSION
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: japanese_address_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yamaguchi Takuya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-24 00:00:00.000000000 Z
11
+ date: 2023-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: schmooze
@@ -4160,7 +4160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
4160
4160
  - !ruby/object:Gem::Version
4161
4161
  version: '0'
4162
4162
  requirements: []
4163
- rubygems_version: 3.4.1
4163
+ rubygems_version: 3.4.18
4164
4164
  signing_key:
4165
4165
  specification_version: 4
4166
4166
  summary: Japanese address parser written in Ruby.