ansuko 1.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.
package/README.ja.md ADDED
@@ -0,0 +1,343 @@
1
+ # ansuko
2
+
3
+ [![CI](https://img.shields.io/github/actions/workflow/status/sera4am/ansuko/ci.yml?branch=main)](https://github.com/sera4am/ansuko/actions/workflows/ci.yml)
4
+
5
+ lodashを拡張した、実用的で直感的な動作を提供するモダンなJavaScript/TypeScriptユーティリティライブラリ。
6
+
7
+ [English](./README.md) | [日本語](./README.ja.md)
8
+
9
+ ## インストール
10
+
11
+ ```bash
12
+ npm install ansuko
13
+ ```
14
+
15
+ または `package.json` に追加:
16
+
17
+ ```json
18
+ {
19
+ "dependencies": {
20
+ "ansuko"
21
+ }
22
+ }
23
+ ```
24
+
25
+ ## 基本思想
26
+
27
+ ansukoは直感的な動作でJavaScriptのよくある不満を解消します:
28
+
29
+ ### lodashの癖を修正
30
+
31
+ ```typescript
32
+ // ❌ lodash(直感的でない)
33
+ _.isEmpty(0) // true - 0は本当に「空」?
34
+ _.isEmpty(true) // true - trueは「空」?
35
+ _.castArray(null) // [null] - なぜnullを残す?
36
+
37
+ // ✅ ansuko(直感的)
38
+ _.isEmpty(0) // false - 数値は空ではない
39
+ _.isEmpty(true) // false - 真偽値は空ではない
40
+ _.castArray(null) // [] - クリーンな空配列
41
+ ```
42
+
43
+ ### 安全なJSON処理
44
+
45
+ ```typescript
46
+ // ❌ 標準JSON(面倒)
47
+ JSON.stringify('hello') // '"hello"' - 余計な引用符!
48
+ JSON.parse(badJson) // throws - try-catchが必要
49
+
50
+ // ✅ ansuko(スムーズ)
51
+ _.jsonStringify('hello') // null - オブジェクトではない
52
+ _.jsonStringify({ a: 1 }) // '{"a":1}' - クリーン
53
+ _.parseJSON(badJson) // null - 例外なし
54
+ _.parseJSON('{ a: 1, }') // {a:1} - JSON5対応!
55
+ ```
56
+
57
+ ### Promise対応のフォールバック
58
+
59
+ ```typescript
60
+ // ❌ 冗長なパターン
61
+ const data = await fetchData()
62
+ const result = data ? data : await fetchBackup()
63
+
64
+ // ✅ ansuko(簡潔)
65
+ const result = await _.valueOr(
66
+ () => fetchData(),
67
+ () => fetchBackup()
68
+ )
69
+ ```
70
+
71
+ ### スマートな比較
72
+
73
+ ```typescript
74
+ // ❌ 冗長な三項演算子地獄
75
+ const value = a === b ? a : (a == null && b == null ? a : defaultValue)
76
+
77
+ // ✅ ansuko(読みやすい)
78
+ const value = _.equalsOr(a, b, defaultValue) // null == undefined
79
+ ```
80
+
81
+ ## プラグインアーキテクチャ
82
+
83
+ ansukoは最小限のコア + プラグインアーキテクチャを採用し、バンドルサイズを小さく保ちます:
84
+
85
+ - **コア** (~20KB): lodashを改善する必須ユーティリティ
86
+ - **日本語プラグイン** (~5KB): 日本語テキスト処理が必要な場合のみ読み込み
87
+ - **Geoプラグイン** (~100KB、@turf/turf含む): GISアプリケーション用
88
+ - **Prototypeプラグイン** (~1KB): Array prototypeの拡張が必要な場合のみ
89
+
90
+
91
+ ```typescript
92
+ // 最小バンドル - コアのみ
93
+ import _ from 'ansuko' // ~20KB
94
+
95
+ // 必要に応じて日本語サポートを追加
96
+ import jaPlugin from 'ansuko/plugins/ja'
97
+ const extended = _.extend(jaPlugin) // +5KB
98
+
99
+ // マッピングアプリ用にGIS機能を追加
100
+ import geoPlugin from 'ansuko/plugins/geo'
101
+ const full = extended.extend(geoPlugin) // +100KB
102
+ ```
103
+
104
+ ## クイックスタート
105
+
106
+ ### 基本的な使い方
107
+
108
+ ```typescript
109
+ import _ from 'ansuko'
110
+
111
+ // 拡張されたlodash関数
112
+ _.isEmpty(0) // false(lodashのようにtrueではない!)
113
+ _.isEmpty([]) // true
114
+ _.castArray(null) // []([null]ではない!)
115
+ _.toNumber('1,234.5') // 1234.5
116
+
117
+ // Promise対応の値処理
118
+ const value = await _.valueOr(
119
+ () => cache.get(id),
120
+ () => api.fetch(id)
121
+ )
122
+
123
+ // 安全なJSONパース
124
+ const data = _.parseJSON('{ "a": 1, /* comment */ }') // JSON5対応!
125
+
126
+ // データベース更新用のオブジェクト変更追跡
127
+ const diff = _.changes(
128
+ original,
129
+ updated,
130
+ ['name', 'email', 'profile.bio']
131
+ )
132
+ ```
133
+
134
+ ### プラグインの使用
135
+
136
+ #### 日本語テキストプラグイン
137
+
138
+ ```typescript
139
+ import _ from 'ansuko'
140
+ import jaPlugin from 'ansuko/plugins/ja'
141
+
142
+ const extended = _.extend(jaPlugin)
143
+
144
+ extended.kanaToFull('ガギ') // 'ガギ'
145
+ extended.kanaToHira('アイウ') // 'あいう'
146
+ extended.toHalfWidth('ABCー123', '-') // 'ABC-123'
147
+ extended.haifun('test‐data', '-') // 'test-data'
148
+ ```
149
+
150
+ #### Geoプラグイン
151
+
152
+ ```typescript
153
+ import _ from 'ansuko'
154
+ import geoPlugin from 'ansuko/plugins/geo'
155
+
156
+ const extended = _.extend(geoPlugin)
157
+
158
+ // 様々な形式をGeoJSONに変換
159
+ extended.toPointGeoJson([139.7671, 35.6812])
160
+ // => { type: 'Point', coordinates: [139.7671, 35.6812] }
161
+
162
+ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
163
+ // => { type: 'Point', coordinates: [139.6917, 35.6895] }
164
+
165
+ // 複数のポリゴンを結合
166
+ const unified = extended.unionPolygon([polygon1, polygon2])
167
+ ```
168
+
169
+ #### Prototypeプラグイン
170
+
171
+ ```typescript
172
+ import _ from 'ansuko'
173
+ import prototypePlugin from 'ansuko/plugins/prototype'
174
+
175
+ _.extend(prototypePlugin)
176
+
177
+ // Array.prototypeが拡張される
178
+ [1, 2, 3].notMap(n => n > 1) // [true, false, false]
179
+ [1, 2, 3].notFilter(n => n % 2) // [2](偶数)
180
+ ```
181
+
182
+ ### プラグインのチェーン
183
+
184
+ ```typescript
185
+ import _ from 'ansuko'
186
+ import jaPlugin from 'ansuko/plugins/ja'
187
+ import geoPlugin from 'ansuko/plugins/geo'
188
+
189
+ const extended = _
190
+ .extend(jaPlugin)
191
+ .extend(geoPlugin)
192
+
193
+ // 日本語とGeoユーティリティの両方が使える!
194
+ extended.kanaToHira('アイウ')
195
+ extended.toPointGeoJson([139.7, 35.6])
196
+ ```
197
+
198
+ ## 主な機能
199
+
200
+ ### 拡張されたlodash関数
201
+
202
+ - **`isEmpty`** - 空かどうかチェック(数値と真偽値は空ではない)
203
+ - **`castArray`** - 配列に変換、null/undefinedは `[]` を返す
204
+ - すべてのlodash関数が利用可能: `size`, `isNil`, `debounce`, `isEqual`, `keys`, `values`, `has` など
205
+
206
+ ### 値処理とフロー制御
207
+
208
+ - **`valueOr`** - Promise/関数対応で値またはデフォルトを取得
209
+ - **`emptyOr`** - 空ならnullを返し、それ以外はコールバックを適用または値を返す
210
+ - **`hasOr`** - パスの存在確認、なければデフォルトを返す(深いパス & Promise対応)
211
+ - **`equalsOr`** - Promise対応の比較とフォールバック、直感的なnil処理
212
+ - **`changes`** - DB更新用のオブジェクト差分追跡(`profile.tags[1]` のような深いパス & 除外モード対応)
213
+
214
+ ### 型変換と検証
215
+
216
+ - **`toNumber`** - カンマ・全角対応の数値パース、無効時は `null`
217
+ - **`toBool`** - スマートな真偽値変換("yes"/"no"/"true"/"false"/数値)、未検出時の動作を設定可能
218
+ - **`boolIf`** - フォールバック付き安全な真偽値変換
219
+ - **`isValidStr`** - 非空文字列検証
220
+
221
+ ### JSON処理
222
+
223
+ - **`parseJSON`** - try-catch不要の安全なJSON/JSON5パース(コメント & 末尾カンマ対応)
224
+ - **`jsonStringify`** - 有効なオブジェクトのみを文字列化、文字列のラップを防止
225
+
226
+ ### 配列ユーティリティ
227
+
228
+ - **`arrayDepth`** - 配列のネスト深さを返す(非配列: 0、空配列: 1)
229
+ - **`castArray`** - 配列に変換、nilは `[]` になる(`[null]` にならない)
230
+
231
+ ### 日本語テキスト(プラグイン: `ansuko/plugins/ja`)
232
+
233
+ - **`kanaToFull`** - 半角カナ → 全角カナ(例: `ガギ` → `ガギ`)
234
+ - **`kanaToHalf`** - 全角 → 半角カナ(濁点分割: `ガギ` → `ガギ`)
235
+ - **`kanaToHira`** - カナ → ひらがな(半角は自動的に全角化)
236
+ - **`hiraToKana`** - ひらがな → カナ
237
+ - **`toHalfWidth`** - 全角 → 半角、オプションでハイフン正規化
238
+ - **`toFullWidth`** - 半角 → 全角、オプションでハイフン正規化
239
+ - **`haifun`** - 様々なハイフンを単一文字に正規化
240
+
241
+ ### Geoユーティリティ(プラグイン: `ansuko/plugins/geo`)
242
+
243
+ - **`toGeoJson`** - 自動検出付きの汎用GeoJSONコンバーター(高次元から順に試行)
244
+ - **`toPointGeoJson`** - 座標/オブジェクトをPoint GeoJSONに変換
245
+ - **`toPolygonGeoJson`** - 外周リングをPolygonに変換(閉じたリングを検証)
246
+ - **`toLineStringGeoJson`** - 座標をLineStringに変換(自己交差をチェック)
247
+ - **`toMultiPointGeoJson`** - 複数の点をMultiPointに変換
248
+ - **`toMultiPolygonGeoJson`** - 複数のポリゴンをMultiPolygonに変換
249
+ - **`toMultiLineStringGeoJson`** - 複数の線をMultiLineStringに変換
250
+ - **`unionPolygon`** - 複数のPolygon/MultiPolygonを単一のジオメトリに結合
251
+ - **`parseToTerraDraw`** - GeoJSONをTerra Draw互換のフィーチャーに変換
252
+
253
+ ### Prototype拡張(プラグイン: `ansuko/plugins/prototype`)
254
+
255
+ - **`Array.prototype.notMap`** - 否定された述語でmap → boolean配列
256
+ - **`Array.prototype.notFilter`** - 否定された述語でfilter(一致しない項目)
257
+
258
+ ### タイミングユーティリティ
259
+
260
+ - **`waited`** - N個のアニメーションフレーム後に実行を遅延(React/DOMには `setTimeout` より良い)
261
+
262
+ ## ドキュメント
263
+
264
+ 詳細情報については、以下を参照してください:
265
+
266
+ - **[APIリファレンス](./API.ja.md)** - 例付きの完全なAPIドキュメント
267
+ - **[使用ガイド](./Guide.ja.md)** - 実際の使用例とパターン
268
+
269
+ ## TypeScriptサポート
270
+
271
+ 型定義を含む完全なTypeScriptサポート。すべての関数はジェネリック対応で完全に型付けされています。
272
+
273
+ ## なぜlodashだけでは不十分なのか?
274
+
275
+ lodashは優れていますが、[コミュニティで批判されている](https://github.com/lodash/lodash/issues)いくつかの癖があります:
276
+
277
+ ### 修正された動作
278
+
279
+ 1. **`_.isEmpty(true)` が `true` を返す** - 真偽値は本当に「空」?
280
+ 2. **`_.isEmpty(1)` が `true` を返す** - 数値1は「空」?
281
+ 3. **`_.castArray(null)` が `[null]` を返す** - なぜnullを配列に含める?
282
+
283
+ ### lodashにない追加ユーティリティ
284
+
285
+ 4. **安全なJSONパースがない** - 常にtry-catchブロックが必要
286
+ 5. **フォールバック付き組み込み比較がない** - 冗長な三項演算子パターンがいたるところに
287
+ 6. **Promise対応の値解決がない** - 手動のPromise処理が面倒
288
+ 7. **オブジェクト差分追跡がない** - DB更新に外部ライブラリが必要
289
+ 8. **`JSON.stringify("hello")` が引用符を追加** - `'"hello"'` という引用符が厄介
290
+
291
+ ### 実際の使用例
292
+
293
+ ```typescript
294
+ // lodashでの一般的なパターン(冗長でエラーが起きやすい)
295
+ let data
296
+ try {
297
+ const cached = cache.get(id)
298
+ if (cached && !_.isEmpty(cached)) {
299
+ data = cached
300
+ } else {
301
+ const fetched = await api.fetch(id)
302
+ data = fetched || defaultValue
303
+ }
304
+ } catch (e) {
305
+ data = defaultValue
306
+ }
307
+
308
+ // ansukoでの同じロジック(簡潔で安全)
309
+ const data = await _.valueOr(
310
+ () => cache.get(id),
311
+ () => api.fetch(id),
312
+ defaultValue
313
+ )
314
+ ```
315
+
316
+ ansukoは、これらの問題を修正しながら、モダンなJavaScript開発のための強力なユーティリティを追加し、lodashとの **100%互換性** を維持しています。
317
+
318
+ ## 依存関係
319
+
320
+ - **`lodash`** - コアユーティリティ関数
321
+ - **`json5`** - コメントと末尾カンマ対応の拡張JSONパース
322
+ - **`@turf/turf`** - 地理空間解析(geoプラグインで使用)
323
+
324
+ ## ソースからのビルド
325
+
326
+ ```bash
327
+ npm install
328
+ npm run build
329
+ ```
330
+
331
+ これにより、`dist` ディレクトリにコンパイルされたJavaScriptと型定義が生成されます。
332
+
333
+ ## 開発
334
+
335
+ Seraによって開発され、ドキュメント、コードレビュー、技術的な議論でClaude(Anthropic)の支援を受けました。
336
+
337
+ ## ライセンス
338
+
339
+ MIT
340
+
341
+ ## 作者
342
+
343
+ 世来 直人
package/README.md ADDED
@@ -0,0 +1,353 @@
1
+ # ansuko
2
+
3
+ [![CI](https://img.shields.io/github/actions/workflow/status/sera4am/ansuko/ci.yml?branch=main)](https://github.com/sera4am/ansuko/actions/workflows/ci.yml)
4
+
5
+ A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors.
6
+
7
+ [English](./README.md) | [日本語](./README.ja.md)
8
+
9
+ ## Why ansuko?
10
+
11
+ The name "ansuko" comes from multiple meanings:
12
+
13
+ - **アンスコ (ansuko)** - Japanese abbreviation for "underscore" (アンダースコア)
14
+ - **ansuko = underscore → low dash → lodash** - Continuing the lineage
15
+ - **スコ (suko)** - Japanese slang meaning "like" or "favorite"
16
+
17
+ This library fixes lodash's unintuitive behaviors and adds powerful utilities that eliminate common JavaScript frustrations.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install ansuko
23
+ ```
24
+
25
+ Or add to your `package.json`:
26
+
27
+ ```json
28
+ {
29
+ "dependencies": {
30
+ "ansuko"
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## Core Philosophy
36
+
37
+ ansuko eliminates common JavaScript frustrations with intuitive behaviors:
38
+
39
+ ### Fixed lodash Quirks
40
+
41
+ ```typescript
42
+ // ❌ lodash (unintuitive)
43
+ _.isEmpty(0) // true - Is 0 really "empty"?
44
+ _.isEmpty(true) // true - Is true "empty"?
45
+ _.castArray(null) // [null] - Why keep null?
46
+
47
+ // ✅ ansuko (intuitive)
48
+ _.isEmpty(0) // false - Numbers are not empty
49
+ _.isEmpty(true) // false - Booleans are not empty
50
+ _.castArray(null) // [] - Clean empty array
51
+ ```
52
+
53
+ ### Safe JSON Handling
54
+
55
+ ```typescript
56
+ // ❌ Standard JSON (annoying)
57
+ JSON.stringify('hello') // '"hello"' - Extra quotes!
58
+ JSON.parse(badJson) // throws - Need try-catch
59
+
60
+ // ✅ ansuko (smooth)
61
+ _.jsonStringify('hello') // null - Not an object
62
+ _.jsonStringify({ a: 1 }) // '{"a":1}' - Clean
63
+ _.parseJSON(badJson) // null - No exceptions
64
+ _.parseJSON('{ a: 1, }') // {a:1} - JSON5 support!
65
+ ```
66
+
67
+ ### Promise-Aware Fallbacks
68
+
69
+ ```typescript
70
+ // ❌ Verbose pattern
71
+ const data = await fetchData()
72
+ const result = data ? data : await fetchBackup()
73
+
74
+ // ✅ ansuko (concise)
75
+ const result = await _.valueOr(
76
+ () => fetchData(),
77
+ () => fetchBackup()
78
+ )
79
+ ```
80
+
81
+ ### Smart Comparisons
82
+
83
+ ```typescript
84
+ // ❌ Verbose ternary hell
85
+ const value = a === b ? a : (a == null && b == null ? a : defaultValue)
86
+
87
+ // ✅ ansuko (readable)
88
+ const value = _.equalsOr(a, b, defaultValue) // null == undefined
89
+ ```
90
+
91
+ ## Key Features
92
+
93
+ ### Enhanced lodash Functions
94
+
95
+ - **`isEmpty`** - Check if empty (numbers and booleans are NOT empty)
96
+ - **`castArray`** - Convert to array, returns `[]` for null/undefined
97
+ - All lodash functions remain available: `size`, `isNil`, `debounce`, `isEqual`, `keys`, `values`, `has`, etc.
98
+
99
+ ### Value Handling & Control Flow
100
+
101
+ - **`valueOr`** - Get value or default with Promise/function support
102
+ - **`emptyOr`** - Return null if empty, otherwise apply callback or return value
103
+ - **`hasOr`** - Check if paths exist, return default if missing (supports deep paths & Promises)
104
+ - **`equalsOr`** - Compare and fallback with intuitive nil handling (Promises supported)
105
+ - **`changes`** - Track object differences for DB updates (supports deep paths like `profile.tags[1]` & excludes mode)
106
+
107
+ ### Type Conversion & Validation
108
+
109
+ - **`toNumber`** - Parse numbers with comma/full-width support, returns `null` for invalid
110
+ - **`toBool`** - Smart boolean conversion ("yes"/"no"/"true"/"false"/numbers) with configurable undetected handling
111
+ - **`boolIf`** - Safe boolean conversion with fallback
112
+ - **`isValidStr`** - Non-empty string validation
113
+
114
+ ### JSON Processing
115
+
116
+ - **`parseJSON`** - Safe JSON/JSON5 parsing without try-catch (supports comments & trailing commas)
117
+ - **`jsonStringify`** - Stringify only valid objects, prevents accidental string wrapping
118
+
119
+ ### Array Utilities
120
+
121
+ - **`arrayDepth`** - Returns nesting depth of arrays (non-array: 0, empty array: 1)
122
+ - **`castArray`** - Convert to array, nil becomes `[]` (not `[null]`)
123
+
124
+ ### Japanese Text (plugin: `ansuko/plugins/ja`)
125
+
126
+ - **`kanaToFull`** - Half-width katakana → Full-width (e.g., `ガギ` → `ガギ`)
127
+ - **`kanaToHalf`** - Full-width → Half-width katakana (dakuten splits: `ガギ` → `ガギ`)
128
+ - **`kanaToHira`** - Katakana → Hiragana (auto-converts half-width first)
129
+ - **`hiraToKana`** - Hiragana → Katakana
130
+ - **`toHalfWidth`** - Full-width → Half-width with optional hyphen normalization
131
+ - **`toFullWidth`** - Half-width → Full-width with optional hyphen normalization
132
+ - **`haifun`** - Normalize various hyphens to single character
133
+
134
+ ### Geo Utilities (plugin: `ansuko/plugins/geo`)
135
+
136
+ - **`toGeoJson`** - Universal GeoJSON converter with auto-detection (tries dimensions from high to low)
137
+ - **`toPointGeoJson`** - Convert coords/object to Point GeoJSON
138
+ - **`toPolygonGeoJson`** - Convert outer ring to Polygon (validates closed ring)
139
+ - **`toLineStringGeoJson`** - Convert coords to LineString (checks self-intersection)
140
+ - **`toMultiPointGeoJson`** - Convert multiple points to MultiPoint
141
+ - **`toMultiPolygonGeoJson`** - Convert multiple polygons to MultiPolygon
142
+ - **`toMultiLineStringGeoJson`** - Convert multiple lines to MultiLineString
143
+ - **`unionPolygon`** - Union multiple Polygon/MultiPolygon into single geometry
144
+ - **`parseToTerraDraw`** - Convert GeoJSON to Terra Draw compatible features
145
+
146
+ ### Prototype Extensions (plugin: `ansuko/plugins/prototype`)
147
+
148
+ - **`Array.prototype.notMap`** - Map with negated predicate → boolean array
149
+ - **`Array.prototype.notFilter`** - Filter by negated predicate (items that do NOT match)
150
+
151
+ ### Timing Utilities
152
+
153
+ - **`waited`** - Delay execution by N animation frames (better than `setTimeout` for React/DOM)
154
+
155
+ ## Plugin Architecture
156
+
157
+ ansuko uses a minimal core + plugin architecture to keep your bundle size small:
158
+
159
+ - **Core** (~20KB): Essential utilities that improve lodash
160
+ - **Japanese plugin** (~5KB): Only load if you need Japanese text processing
161
+ - **Geo plugin** (~100KB with @turf/turf): Only load for GIS applications
162
+ - **Prototype plugin** (~1KB): Only load if you want Array prototype extensions
163
+
164
+ This means you only pay for what you use!
165
+
166
+ ```typescript
167
+ // Minimal bundle - just core
168
+ import _ from 'ansuko' // ~20KB
169
+
170
+ // Add Japanese support when needed
171
+ import jaPlugin from 'ansuko/plugins/ja'
172
+ _.extend(jaPlugin) // +5KB
173
+
174
+ // Add GIS features for mapping apps
175
+ import geoPlugin from 'ansuko/plugins/geo'
176
+ _.extend(geoPlugin) // +100KB
177
+ ```
178
+
179
+ ## Quick Start
180
+
181
+ ### Basic Usage
182
+
183
+ ```typescript
184
+ import _ from 'ansuko'
185
+
186
+ // Enhanced lodash functions
187
+ _.isEmpty(0) // false (not true like lodash!)
188
+ _.isEmpty([]) // true
189
+ _.castArray(null) // [] (not [null]!)
190
+ _.toNumber('1,234.5') // 1234.5
191
+
192
+ // Value handling with Promise support
193
+ const value = await _.valueOr(
194
+ () => cache.get(id),
195
+ () => api.fetch(id)
196
+ )
197
+
198
+ // Safe JSON parsing
199
+ const data = _.parseJSON('{ "a": 1, /* comment */ }') // Works with JSON5!
200
+
201
+ // Track object changes for database updates
202
+ const diff = _.changes(
203
+ original,
204
+ updated,
205
+ ['name', 'email', 'profile.bio']
206
+ )
207
+ ```
208
+
209
+ ### Using Plugins
210
+
211
+ #### Japanese Text Plugin
212
+
213
+ ```typescript
214
+ import _ from 'ansuko'
215
+ import jaPlugin from 'ansuko/plugins/ja'
216
+
217
+ _.extend(jaPlugin)
218
+
219
+ _.kanaToFull('ガギ') // 'ガギ'
220
+ _.kanaToHira('アイウ') // 'あいう'
221
+ _.toHalfWidth('ABCー123', '-') // 'ABC-123'
222
+ _.haifun('test‐data', '-') // 'test-data'
223
+ ```
224
+
225
+ #### Geo Plugin
226
+
227
+ ```typescript
228
+ import _ from 'ansuko'
229
+ import geoPlugin from 'ansuko/plugins/geo'
230
+
231
+ const extended = _.extend(geoPlugin)
232
+
233
+ // Convert various formats to GeoJSON
234
+ extended.toPointGeoJson([139.7671, 35.6812])
235
+ // => { type: 'Point', coordinates: [139.7671, 35.6812] }
236
+
237
+ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
238
+ // => { type: 'Point', coordinates: [139.6917, 35.6895] }
239
+
240
+ // Union multiple polygons
241
+ const unified = extended.unionPolygon([polygon1, polygon2])
242
+ ```
243
+
244
+ #### Prototype Plugin
245
+
246
+ ```typescript
247
+ import _ from 'ansuko'
248
+ import prototypePlugin from 'ansuko/plugins/prototype'
249
+
250
+ _.extend(prototypePlugin)
251
+
252
+ // Now Array.prototype is extended
253
+ [1, 2, 3].notMap(n => n > 1) // [true, false, false]
254
+ [1, 2, 3].notFilter(n => n % 2) // [2] (even numbers)
255
+ ```
256
+
257
+ ### Chaining Plugins
258
+
259
+ ```typescript
260
+ import _ from 'ansuko'
261
+ import jaPlugin from 'ansuko/plugins/ja'
262
+ import geoPlugin from 'ansuko/plugins/geo'
263
+
264
+ const extended = _
265
+ .extend(jaPlugin)
266
+ .extend(geoPlugin)
267
+
268
+ // Now you have both Japanese and Geo utilities!
269
+ extended.kanaToHira('アイウ')
270
+ extended.toPointGeoJson([139.7, 35.6])
271
+ ```
272
+
273
+ ## Documentation
274
+
275
+ For detailed information, see:
276
+
277
+ - **[API Reference](./docs/API.md)** - Complete API documentation with examples
278
+ - **[Usage Guide](./docs/Guide.md)** - Real-world examples and patterns
279
+
280
+ ## TypeScript Support
281
+
282
+ Full TypeScript support with type definitions included. All functions are fully typed with generic support.
283
+
284
+ ## Why not just use lodash?
285
+
286
+ lodash is excellent, but has some quirks that have been [criticized by the community](https://github.com/lodash/lodash/issues):
287
+
288
+ ### Fixed Behaviors
289
+
290
+ 1. **`_.isEmpty(true)` returns `true`** - Is a boolean really "empty"?
291
+ 2. **`_.isEmpty(1)` returns `true`** - Is the number 1 "empty"?
292
+ 3. **`_.castArray(null)` returns `[null]`** - Why include null in the array?
293
+
294
+ ### Added Utilities Missing in lodash
295
+
296
+ 4. **No safe JSON parsing** - Always need try-catch blocks
297
+ 5. **No built-in comparison with fallback** - Verbose ternary patterns everywhere
298
+ 6. **No Promise-aware value resolution** - Manual Promise handling gets messy
299
+ 7. **No object diff tracking** - Need external libs for DB updates
300
+ 8. **`JSON.stringify("hello")` adds quotes** - Those `'"hello"'` quotes are annoying
301
+
302
+ ### Real-World Example
303
+
304
+ ```typescript
305
+ // Common pattern with lodash (verbose & error-prone)
306
+ let data
307
+ try {
308
+ const cached = cache.get(id)
309
+ if (cached && !_.isEmpty(cached)) {
310
+ data = cached
311
+ } else {
312
+ const fetched = await api.fetch(id)
313
+ data = fetched || defaultValue
314
+ }
315
+ } catch (e) {
316
+ data = defaultValue
317
+ }
318
+
319
+ // Same logic with ansuko (concise & safe)
320
+ const data = await _.valueOr(
321
+ () => cache.get(id),
322
+ () => api.fetch(id),
323
+ defaultValue
324
+ )
325
+ ```
326
+
327
+ ansuko maintains **100% compatibility** with lodash while fixing these issues and adding powerful utilities for modern JavaScript development.
328
+
329
+ ## Dependencies
330
+
331
+ - **`lodash`** - Core utility functions
332
+ - **`json5`** - Enhanced JSON parsing with comments and trailing commas support
333
+ - **`@turf/turf`** - Geospatial analysis (used by geo plugin)
334
+
335
+ ## Building from Source
336
+
337
+ ```bash
338
+ npm install
339
+ npm run build
340
+ ```
341
+
342
+ This will generate the compiled JavaScript and type definitions in the `dist` directory.
343
+
344
+ ## Development
345
+ Developed by Sera with assistance from Claude (Anthropic) for documentation, code review, and technical discussions.
346
+
347
+ ## License
348
+
349
+ MIT
350
+
351
+ ## Author
352
+
353
+ Naoto Sera