ansuko 1.3.2 → 1.3.4
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 +13 -0
- package/README.md +13 -0
- package/README.zh.md +103 -94
- package/dist/plugins/geo.d.ts +2 -0
- package/dist/plugins/geo.js +104 -0
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -167,6 +167,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
|
|
|
167
167
|
|
|
168
168
|
// 複数のポリゴンを結合
|
|
169
169
|
const unified = extended.unionPolygon([polygon1, polygon2])
|
|
170
|
+
|
|
171
|
+
// MapBoxユーティリティ
|
|
172
|
+
extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
|
|
173
|
+
// => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
|
|
174
|
+
|
|
175
|
+
extended.mProps({
|
|
176
|
+
fillColor: "#ff0000",
|
|
177
|
+
sourceLayer: "buildings",
|
|
178
|
+
visibility: true
|
|
179
|
+
})
|
|
180
|
+
// => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
|
|
170
181
|
```
|
|
171
182
|
|
|
172
183
|
#### Prototypeプラグイン
|
|
@@ -254,6 +265,8 @@ extended.toPointGeoJson([139.7, 35.6])
|
|
|
254
265
|
- **`toMultiLineStringGeoJson`** - 複数の線をMultiLineStringに変換
|
|
255
266
|
- **`unionPolygon`** - 複数のPolygon/MultiPolygonを単一のジオメトリに結合
|
|
256
267
|
- **`parseToTerraDraw`** - GeoJSONをTerra Draw互換のフィーチャーに変換
|
|
268
|
+
- **`mZoomInterpolate`** - ズームオブジェクトをMapBox補間式に変換
|
|
269
|
+
- **`mProps`** - camelCaseプロパティをMapBox互換形式に変換(minzoom、visibilityなどの特殊ケースに対応)
|
|
257
270
|
|
|
258
271
|
### Prototype拡張(プラグイン: `ansuko/plugins/prototype`)
|
|
259
272
|
|
package/README.md
CHANGED
|
@@ -143,6 +143,8 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
|
|
|
143
143
|
- **`toMultiLineStringGeoJson`** - Convert multiple lines to MultiLineString
|
|
144
144
|
- **`unionPolygon`** - Union multiple Polygon/MultiPolygon into single geometry
|
|
145
145
|
- **`parseToTerraDraw`** - Convert GeoJSON to Terra Draw compatible features
|
|
146
|
+
- **`mZoomInterpolate`** - Convert zoom object to MapBox interpolation expression
|
|
147
|
+
- **`mProps`** - Convert camelCase properties to MapBox-compatible format (handles special cases like minzoom, visibility)
|
|
146
148
|
|
|
147
149
|
### Prototype Extensions (plugin: `ansuko/plugins/prototype`)
|
|
148
150
|
|
|
@@ -244,6 +246,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
|
|
|
244
246
|
|
|
245
247
|
// Union multiple polygons
|
|
246
248
|
const unified = extended.unionPolygon([polygon1, polygon2])
|
|
249
|
+
|
|
250
|
+
// MapBox utilities
|
|
251
|
+
extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
|
|
252
|
+
// => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
|
|
253
|
+
|
|
254
|
+
extended.mProps({
|
|
255
|
+
fillColor: "#ff0000",
|
|
256
|
+
sourceLayer: "buildings",
|
|
257
|
+
visibility: true
|
|
258
|
+
})
|
|
259
|
+
// => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
|
|
247
260
|
```
|
|
248
261
|
|
|
249
262
|
#### Prototype Plugin
|
package/README.zh.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ansuko
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在lodash基础上扩展、提供实用且直观易懂的现代JavaScript/TypeScript工具库。
|
|
4
4
|
|
|
5
5
|
[English](./README.md) | [日本語](./README.ja.md) | [简体中文](./README.zh.md)
|
|
6
6
|
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
- **ansuko = underscore → low dash → lodash** - 延续这个系列
|
|
13
13
|
- **スコ (suko)** - 日文俚语,意为"喜欢"或"最爱"
|
|
14
14
|
|
|
15
|
-
这个库修复了 lodash 的不直观行为,并添加了强大的工具来消除常见的 JavaScript 困扰。
|
|
16
|
-
|
|
17
15
|
## 安装
|
|
18
16
|
|
|
19
17
|
```bash
|
|
@@ -32,40 +30,40 @@ npm install ansuko
|
|
|
32
30
|
|
|
33
31
|
## 核心理念
|
|
34
32
|
|
|
35
|
-
ansuko
|
|
33
|
+
ansuko以直观的语法,解决了JavaScript中常见的痛点。
|
|
36
34
|
|
|
37
|
-
###
|
|
35
|
+
### 修正 lodash 的非常规行为
|
|
38
36
|
|
|
39
37
|
```typescript
|
|
40
38
|
// ❌ lodash(不直观)
|
|
41
|
-
_.isEmpty(0) // true - 0
|
|
42
|
-
_.isEmpty(true) // true - true
|
|
43
|
-
_.castArray(null) // [null] -
|
|
39
|
+
_.isEmpty(0) // true - 0真的为「空」吗?
|
|
40
|
+
_.isEmpty(true) // true - true算「空」吗?
|
|
41
|
+
_.castArray(null) // [null] - 为何保留null?
|
|
44
42
|
|
|
45
43
|
// ✅ ansuko(直观)
|
|
46
|
-
_.isEmpty(0) // false -
|
|
44
|
+
_.isEmpty(0) // false - 数值不为空
|
|
47
45
|
_.isEmpty(true) // false - 布尔值不为空
|
|
48
|
-
_.castArray(null) // [] -
|
|
46
|
+
_.castArray(null) // [] - 得到空数组
|
|
49
47
|
```
|
|
50
48
|
|
|
51
49
|
### 安全的 JSON 处理
|
|
52
50
|
|
|
53
51
|
```typescript
|
|
54
|
-
// ❌ 标准 JSON
|
|
55
|
-
JSON.stringify('hello') // '"hello"' -
|
|
56
|
-
JSON.parse(badJson) //
|
|
57
|
-
|
|
58
|
-
// ✅ ansuko
|
|
59
|
-
_.jsonStringify('hello') // null -
|
|
60
|
-
_.jsonStringify({ a: 1 }) // '{"a":1}' -
|
|
61
|
-
_.parseJSON(badJson) // null -
|
|
62
|
-
_.parseJSON('{ a: 1, }') // {a:1} - 支持
|
|
52
|
+
// ❌ 标准 JSON(繁琐)
|
|
53
|
+
JSON.stringify('hello') // '"hello"' - 多余的引号
|
|
54
|
+
JSON.parse(badJson) // throws - 必须用try-catch
|
|
55
|
+
|
|
56
|
+
// ✅ ansuko(简洁直观)
|
|
57
|
+
_.jsonStringify('hello') // null - 非对象不序列化
|
|
58
|
+
_.jsonStringify({ a: 1 }) // '{"a":1}' - 结构简洁
|
|
59
|
+
_.parseJSON(badJson) // null - 不抛异常
|
|
60
|
+
_.parseJSON('{ a: 1, }') // {a:1} - 支持JSON5!
|
|
63
61
|
```
|
|
64
62
|
|
|
65
|
-
### Promise
|
|
63
|
+
### 支持Promise的回滚
|
|
66
64
|
|
|
67
65
|
```typescript
|
|
68
|
-
// ❌
|
|
66
|
+
// ❌ 冗长写法
|
|
69
67
|
const data = await fetchData()
|
|
70
68
|
const result = data ? data : await fetchBackup()
|
|
71
69
|
|
|
@@ -79,7 +77,7 @@ const result = await _.valueOr(
|
|
|
79
77
|
### 智能比较
|
|
80
78
|
|
|
81
79
|
```typescript
|
|
82
|
-
// ❌
|
|
80
|
+
// ❌ 三元运算符地狱
|
|
83
81
|
const value = a === b ? a : (a == null && b == null ? a : defaultValue)
|
|
84
82
|
|
|
85
83
|
// ✅ ansuko(可读)
|
|
@@ -88,40 +86,40 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
|
|
|
88
86
|
|
|
89
87
|
## 主要特性
|
|
90
88
|
|
|
91
|
-
###
|
|
89
|
+
### 增强型lodash函数
|
|
92
90
|
|
|
93
|
-
- **`isEmpty`** -
|
|
94
|
-
- **`castArray`** -
|
|
95
|
-
-
|
|
91
|
+
- **`isEmpty`** - 检查是否为空(数字和布尔值不视为空)
|
|
92
|
+
- **`castArray`** - 转换为数组,若为null/undefined 则返回 `[]`
|
|
93
|
+
- 支持所有lodash函数:`size`、`isNil`、`debounce`、`isEqual`、`keys`、`values`、`has` 等
|
|
96
94
|
|
|
97
|
-
###
|
|
95
|
+
### 数值处理与流控制
|
|
98
96
|
|
|
99
|
-
- **`valueOr`** -
|
|
100
|
-
- **`emptyOr`** -
|
|
101
|
-
- **`hasOr`** -
|
|
102
|
-
- **`equalsOr`** -
|
|
103
|
-
- **`changes`** -
|
|
104
|
-
- **`swallow`** -
|
|
105
|
-
- **`swallowMap`** -
|
|
97
|
+
- **`valueOr`** - 支持Promise和函数,获取目标值或默认值
|
|
98
|
+
- **`emptyOr`** - 若为空则返回null,否则应用回调或返回值
|
|
99
|
+
- **`hasOr`** - 检查路径是否存在,不存在则返回默认值(支持深层路径及 Promise)
|
|
100
|
+
- **`equalsOr`** - 支持Promise的比较与回退,具备直观的Nil处理机制
|
|
101
|
+
- **`changes`** - 用于数据库更新的对象差分追踪(支持 profile.tags[1]等深层路径及排除模式)`和排除模式)
|
|
102
|
+
- **`swallow`** - 执行函数并在报错时返回undefined(支持同步/异步)
|
|
103
|
+
- **`swallowMap`** - 将错误处理为undefined的数组map(支持compact模式排除错误项)
|
|
106
104
|
|
|
107
105
|
### 类型转换与验证
|
|
108
106
|
|
|
109
|
-
- **`toNumber`** -
|
|
110
|
-
- **`toBool`** -
|
|
111
|
-
- **`boolIf`** -
|
|
107
|
+
- **`toNumber`** - 解析包含逗号、全角字符的数字,无效时返回null
|
|
108
|
+
- **`toBool`** - 智能布尔值转换(支持 "yes"/"no"/"true"/"false"/数字),可配置未检测到时的行为检测处理
|
|
109
|
+
- **`boolIf`** - 带有回退机制的安全布尔值转换
|
|
112
110
|
- **`isValidStr`** - 非空字符串验证
|
|
113
111
|
|
|
114
112
|
### JSON 处理
|
|
115
113
|
|
|
116
|
-
- **`parseJSON`** - 无需
|
|
117
|
-
- **`jsonStringify`** -
|
|
114
|
+
- **`parseJSON`** - 无需try-catch的安全JSON/JSON5解析(支持注释及末尾逗号)
|
|
115
|
+
- **`jsonStringify`** - 仅字符串化有效对象,防止字符串被重复包裹
|
|
118
116
|
|
|
119
117
|
### 数组工具
|
|
120
118
|
|
|
121
119
|
- **`arrayDepth`** - 返回数组的嵌套深度(非数组:0,空数组:1)
|
|
122
120
|
- **`castArray`** - 转换为数组,nil 变为 `[]`(而非 `[null]`)
|
|
123
121
|
|
|
124
|
-
###
|
|
122
|
+
### 日语文本处理(插件:`ansuko/plugins/ja`)
|
|
125
123
|
|
|
126
124
|
- **`kanaToFull`** - 半角片假名 → 全角(例如 `ガギ` → `ガギ`)
|
|
127
125
|
- **`kanaToHalf`** - 全角 → 半角片假名(浊音拆分:`ガギ` → `ガギ`)
|
|
@@ -129,51 +127,51 @@ const value = _.equalsOr(a, b, defaultValue) // null == undefined
|
|
|
129
127
|
- **`hiraToKana`** - 平假名 → 片假名
|
|
130
128
|
- **`toHalfWidth`** - 全角 → 半角,可选连字符标准化
|
|
131
129
|
- **`toFullWidth`** - 半角 → 全角,可选连字符标准化
|
|
132
|
-
- **`haifun`** -
|
|
130
|
+
- **`haifun`** - 将各种形式的连字符统一正规化
|
|
133
131
|
|
|
134
|
-
###
|
|
132
|
+
### Geo地理空间工具(插件:`ansuko/plugins/geo`)
|
|
135
133
|
|
|
136
|
-
- **`toGeoJson`** -
|
|
137
|
-
- **`toPointGeoJson`** -
|
|
138
|
-
- **`toPolygonGeoJson`** - 将外环转换为
|
|
139
|
-
- **`toLineStringGeoJson`** - 将坐标转换为
|
|
140
|
-
- **`toMultiPointGeoJson`** - 将多个点转换为
|
|
141
|
-
- **`toMultiPolygonGeoJson`** - 将多个多边形转换为
|
|
142
|
-
- **`toMultiLineStringGeoJson`** - 将多条线转换为
|
|
143
|
-
- **`unionPolygon`** - 将多个
|
|
144
|
-
- **`parseToTerraDraw`** - 将
|
|
134
|
+
- **`toGeoJson`** - 具备自动检测功能的通用GeoJSON转换器(按高维到低维顺序尝试)
|
|
135
|
+
- **`toPointGeoJson`** - 将坐标或对象转换为Point GeoJSON
|
|
136
|
+
- **`toPolygonGeoJson`** - 将外环转换为Polygon(验证闭合环)
|
|
137
|
+
- **`toLineStringGeoJson`** - 将坐标转换为LineString(检查自相交)
|
|
138
|
+
- **`toMultiPointGeoJson`** - 将多个点转换为MultiPoint
|
|
139
|
+
- **`toMultiPolygonGeoJson`** - 将多个多边形转换为MultiPolygon
|
|
140
|
+
- **`toMultiLineStringGeoJson`** - 将多条线转换为MultiLineString
|
|
141
|
+
- **`unionPolygon`** - 将多个Polygon/MultiPolygon合并为单一几何体
|
|
142
|
+
- **`parseToTerraDraw`** - 将GeoJSON转换为兼容Terra Draw的Feature
|
|
143
|
+
- **`mZoomInterpolate`** - 将缩放对象转换为MapBox插值表达式
|
|
144
|
+
- **`mProps`** - 将(camelCase)属性转换为MapBox兼容格式(处理minzoom、visibility等特殊情况)
|
|
145
145
|
|
|
146
|
-
### 原型扩展(插件:`ansuko/plugins/prototype`)
|
|
146
|
+
### Prototype原型扩展(插件:`ansuko/plugins/prototype`)
|
|
147
147
|
|
|
148
|
-
- **`Array.prototype.notMap`** -
|
|
149
|
-
- **`Array.prototype.notFilter`** -
|
|
148
|
+
- **`Array.prototype.notMap`** - 使用谓词取反进行map,返回布尔数组
|
|
149
|
+
- **`Array.prototype.notFilter`** - 使用谓词取反进行filter(筛选不匹配的项)
|
|
150
150
|
|
|
151
151
|
### 时间工具
|
|
152
152
|
|
|
153
|
-
- **`waited`** -
|
|
153
|
+
- **`waited`** - 延迟N个动画帧后执行(在 React/DOM 環境下比`setTimeout`更优)
|
|
154
154
|
|
|
155
155
|
## 插件架构
|
|
156
156
|
|
|
157
|
-
ansuko
|
|
158
|
-
|
|
159
|
-
- **核心**(~20KB):改进 lodash 的基本工具
|
|
160
|
-
- **日文插件**(~5KB):仅在需要日文文本处理时加载
|
|
161
|
-
- **地理插件**(~100KB 含 @turf/turf):仅为 GIS 应用加载
|
|
162
|
-
- **原型插件**(~1KB):仅在需要数组原型扩展时加载
|
|
157
|
+
ansuko使用最小核心 + 插件架构来保持你的包大小小:
|
|
163
158
|
|
|
164
|
-
|
|
159
|
+
- **核心**(约 20KB):在 lodash 上增强的必备工具
|
|
160
|
+
- **日文插件**(约 5KB):仅在需要日文文本处理时引入
|
|
161
|
+
- **Geo 插件**(约 100KB,含 @turf/turf):面向 GIS 应用
|
|
162
|
+
- **Prototype 插件**(约 1KB):仅在需要扩展 Array.prototype 时引入
|
|
165
163
|
|
|
166
164
|
```typescript
|
|
167
|
-
//
|
|
165
|
+
// 最小打包:仅核心
|
|
168
166
|
import _ from 'ansuko' // ~20KB
|
|
169
167
|
|
|
170
|
-
//
|
|
168
|
+
// 按需加入日文支持
|
|
171
169
|
import jaPlugin from 'ansuko/plugins/ja'
|
|
172
|
-
_.extend(jaPlugin) // +5KB
|
|
170
|
+
const extended = _.extend(jaPlugin) // +5KB
|
|
173
171
|
|
|
174
|
-
//
|
|
172
|
+
// 地图类应用再挂载 GIS
|
|
175
173
|
import geoPlugin from 'ansuko/plugins/geo'
|
|
176
|
-
|
|
174
|
+
const full = extended.extend(geoPlugin) // +100KB
|
|
177
175
|
```
|
|
178
176
|
|
|
179
177
|
## 快速开始
|
|
@@ -243,6 +241,17 @@ extended.toPointGeoJson({ lat: 35.6895, lng: 139.6917 })
|
|
|
243
241
|
|
|
244
242
|
// 合并多个多边形
|
|
245
243
|
const unified = extended.unionPolygon([polygon1, polygon2])
|
|
244
|
+
|
|
245
|
+
// MapBox 工具
|
|
246
|
+
extended.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
|
|
247
|
+
// => ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
|
|
248
|
+
|
|
249
|
+
extended.mProps({
|
|
250
|
+
fillColor: "#ff0000",
|
|
251
|
+
sourceLayer: "buildings",
|
|
252
|
+
visibility: true
|
|
253
|
+
})
|
|
254
|
+
// => { "fill-color": "#ff0000", "source-layer": "buildings", "visibility": "visible" }
|
|
246
255
|
```
|
|
247
256
|
|
|
248
257
|
#### 原型插件
|
|
@@ -276,37 +285,37 @@ extended.toPointGeoJson([139.7, 35.6])
|
|
|
276
285
|
|
|
277
286
|
## 文档
|
|
278
287
|
|
|
279
|
-
|
|
288
|
+
更多详细信息,请参阅:
|
|
280
289
|
|
|
281
|
-
- **[API 参考](./docs/API.zh.md)** -
|
|
282
|
-
- **[使用指南](./docs/Guide.zh.md)** -
|
|
290
|
+
- **[API 参考](./docs/API.zh.md)** - 包含示例的完整API文档
|
|
291
|
+
- **[使用指南](./docs/Guide.zh.md)** - 实际使用案例与设计模式
|
|
283
292
|
|
|
284
|
-
## TypeScript
|
|
293
|
+
## 支持TypeScript
|
|
285
294
|
|
|
286
|
-
|
|
295
|
+
完美支持TypeScript,包含完整的类型定义。所有函数均支持泛型,并经过严格的类型标注。
|
|
287
296
|
|
|
288
|
-
##
|
|
297
|
+
## 为什么仅有lodash还不够?
|
|
289
298
|
|
|
290
|
-
lodash
|
|
299
|
+
lodash很优秀,但存在一些[被社区广为诟病](https://github.com/lodash/lodash/issues)的怪癖:
|
|
291
300
|
|
|
292
|
-
###
|
|
301
|
+
### 已修正的部分
|
|
293
302
|
|
|
294
|
-
1. **`_.isEmpty(true)` 返回 `true`** -
|
|
295
|
-
2. **`_.isEmpty(1)` 返回 `true`** - 数字
|
|
296
|
-
3. **`_.castArray(null)` 返回 `[null]`** -
|
|
303
|
+
1. **`_.isEmpty(true)` 返回 `true`** - 布尔值真的为"空"吗?
|
|
304
|
+
2. **`_.isEmpty(1)` 返回 `true`** - 数字1怎么能为"空"呢?
|
|
305
|
+
3. **`_.castArray(null)` 返回 `[null]`** - 为什么要把null包含在数组里?
|
|
297
306
|
|
|
298
|
-
### lodash
|
|
307
|
+
### lodash中没有的工具函数
|
|
299
308
|
|
|
300
|
-
4. **无安全的 JSON 解析** -
|
|
301
|
-
5. **无内置的比较与后备** -
|
|
302
|
-
6. **无 Promise 感知的值解析** -
|
|
303
|
-
7. **无对象差异跟踪** -
|
|
304
|
-
8. **`JSON.stringify("hello")`
|
|
309
|
+
4. **无安全的 JSON 解析** - 总是需要写重复的try-catch代码块
|
|
310
|
+
5. **无内置的比较与后备** - 代码中到处充斥着冗余的三元运算符
|
|
311
|
+
6. **无 Promise 感知的值解析** - 手动处理Promise逻辑非常繁琐
|
|
312
|
+
7. **无对象差异跟踪** - 进行数据库更新操作时往往需要引入额外库
|
|
313
|
+
8. **`JSON.stringify("hello")` 会添加多余引号 —— 生成 `'"hello"'`这种带引号的繁琐字符串
|
|
305
314
|
|
|
306
|
-
###
|
|
315
|
+
### 实际使用案例
|
|
307
316
|
|
|
308
317
|
```typescript
|
|
309
|
-
// lodash
|
|
318
|
+
// lodash的常见写法(冗长且易错)
|
|
310
319
|
let data
|
|
311
320
|
try {
|
|
312
321
|
const cached = cache.get(id)
|
|
@@ -320,7 +329,7 @@ try {
|
|
|
320
329
|
data = defaultValue
|
|
321
330
|
}
|
|
322
331
|
|
|
323
|
-
// ansuko
|
|
332
|
+
// ansuko的实现逻辑(简洁且安全)
|
|
324
333
|
const data = await _.valueOr(
|
|
325
334
|
() => cache.get(id),
|
|
326
335
|
() => api.fetch(id),
|
|
@@ -328,13 +337,13 @@ const data = await _.valueOr(
|
|
|
328
337
|
)
|
|
329
338
|
```
|
|
330
339
|
|
|
331
|
-
ansuko
|
|
340
|
+
ansuko在修正上述问题的同时,为现代JavaScript开发增添了强大的工具函数,并保持了与Lodash的100%兼容性。
|
|
332
341
|
|
|
333
342
|
## 依赖项
|
|
334
343
|
|
|
335
344
|
- **`lodash`** - 核心工具函数
|
|
336
|
-
- **`json5`** -
|
|
337
|
-
- **`@turf/turf`** -
|
|
345
|
+
- **`json5`** - 支持注释和末尾逗号的扩展JSON解析
|
|
346
|
+
- **`@turf/turf`** - 地理空间分析(用于geo插件)
|
|
338
347
|
|
|
339
348
|
## 从源代码构建
|
|
340
349
|
|
|
@@ -343,10 +352,10 @@ npm install
|
|
|
343
352
|
npm run build
|
|
344
353
|
```
|
|
345
354
|
|
|
346
|
-
|
|
355
|
+
执行后将在`dist`目录下生成编译后的JavaScript文件和类型定义。
|
|
347
356
|
|
|
348
|
-
##
|
|
349
|
-
|
|
357
|
+
## 开发相关
|
|
358
|
+
因为不太擅长写测试和文档,所以一直在使用Claude进行头脑风暴并辅助编写文档。
|
|
350
359
|
|
|
351
360
|
## 许可证
|
|
352
361
|
|
|
@@ -358,4 +367,4 @@ Naoto Sera
|
|
|
358
367
|
|
|
359
368
|
---
|
|
360
369
|
|
|
361
|
-
|
|
370
|
+
技术无国界,开源即和平。无论世界如何变迁,愿代码始终纯粹。
|
package/dist/plugins/geo.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface AnsukoGeoPluginExtension {
|
|
|
21
21
|
toMultiPolygonGeoJson: (geo: any, digit?: number) => GeoJSON.MultiPolygon | null;
|
|
22
22
|
toMultiLineStringGeoJson: (geo: any, digit?: number) => GeoJSON.MultiLineString | null;
|
|
23
23
|
unionPolygon: (geo: any, digit?: number) => GeoJSON.Polygon | GeoJSON.MultiPolygon | null;
|
|
24
|
+
mZoomInterpolate: (zoomValues: Record<number, number>, type?: string) => any;
|
|
25
|
+
mProps: (properties: Record<string, any>, excludeKeys?: string[]) => Record<string, any>;
|
|
24
26
|
}
|
|
25
27
|
declare const ansukoGeoPlugin: <T extends AnsukoType>(ansuko: T) => T & AnsukoGeoPluginExtension;
|
|
26
28
|
export default ansukoGeoPlugin;
|
package/dist/plugins/geo.js
CHANGED
|
@@ -551,6 +551,108 @@ const ansukoGeoPlugin = (ansuko) => {
|
|
|
551
551
|
}
|
|
552
552
|
return features;
|
|
553
553
|
};
|
|
554
|
+
/**
|
|
555
|
+
* Creates a MapBox zoom interpolation expression from a simple object mapping.
|
|
556
|
+
* Converts `{10: 1, 15: 5, 20: 10}` into MapBox's interpolation array format.
|
|
557
|
+
*
|
|
558
|
+
* @param zoomValues - Object mapping zoom levels to values
|
|
559
|
+
* @param type - Interpolation type: "linear", "exponential", or "cubic-bezier" (default: "linear")
|
|
560
|
+
* @returns MapBox interpolation expression array
|
|
561
|
+
* @example
|
|
562
|
+
* _.mZoomInterpolate({ 10: 1, 15: 5, 20: 10 })
|
|
563
|
+
* // Returns: ["interpolate", ["linear"], ["zoom"], 10, 1, 15, 5, 20, 10]
|
|
564
|
+
* @example
|
|
565
|
+
* _.mZoomInterpolate({ 12: 0.5, 18: 2 }, "exponential")
|
|
566
|
+
* @category Geo Utilities
|
|
567
|
+
*/
|
|
568
|
+
const mZoomInterpolate = (zoomValues, type = "linear") => {
|
|
569
|
+
let vals = [];
|
|
570
|
+
Object.entries(zoomValues).sort((v1, v2) => {
|
|
571
|
+
return parseFloat(v1[0]) - parseFloat(v2[0]);
|
|
572
|
+
}).map(([zoom, val]) => {
|
|
573
|
+
vals.push(parseFloat(zoom));
|
|
574
|
+
vals.push(val);
|
|
575
|
+
});
|
|
576
|
+
return [
|
|
577
|
+
"interpolate",
|
|
578
|
+
[type],
|
|
579
|
+
["zoom"],
|
|
580
|
+
...vals,
|
|
581
|
+
];
|
|
582
|
+
};
|
|
583
|
+
/**
|
|
584
|
+
* Converts camelCase properties to MapBox-compatible format.
|
|
585
|
+
* Handles special cases like minzoom, maxzoom, tileSize, cluster properties, and converts
|
|
586
|
+
* visibility boolean to "visible"/"none". Recursively processes nested objects and arrays.
|
|
587
|
+
*
|
|
588
|
+
* @param properties - Object with camelCase properties
|
|
589
|
+
* @param excludeKeys - Keys to exclude from conversion (keeps original key and value)
|
|
590
|
+
* @returns Converted properties object compatible with MapBox
|
|
591
|
+
* @example
|
|
592
|
+
* _.mProps({
|
|
593
|
+
* fillColor: "#ff0000",
|
|
594
|
+
* fillOpacity: 0.5,
|
|
595
|
+
* sourceLayer: "buildings"
|
|
596
|
+
* })
|
|
597
|
+
* // Returns: { "fill-color": "#ff0000", "fill-opacity": 0.5, "source-layer": "buildings" }
|
|
598
|
+
* @example
|
|
599
|
+
* _.mProps({ visibility: true }) // Returns: { visibility: "visible" }
|
|
600
|
+
* @example
|
|
601
|
+
* _.mProps({ minZoom: 10, maxZoom: 20 }) // Returns: { minzoom: 10, maxzoom: 20 }
|
|
602
|
+
* @category Geo Utilities
|
|
603
|
+
*/
|
|
604
|
+
const mProps = (properties, excludeKeys = []) => {
|
|
605
|
+
if (_.isEmpty(properties)) {
|
|
606
|
+
return properties;
|
|
607
|
+
}
|
|
608
|
+
if (Array.isArray(properties)) {
|
|
609
|
+
return properties.map(p => mProps(p, excludeKeys));
|
|
610
|
+
}
|
|
611
|
+
if (typeof properties === "object") {
|
|
612
|
+
return Object.fromEntries(Object.entries(properties).map(([key, value]) => {
|
|
613
|
+
let newKey = key;
|
|
614
|
+
const lKey = key.toLowerCase();
|
|
615
|
+
if (lKey === "minzoom") {
|
|
616
|
+
newKey = "minzoom";
|
|
617
|
+
}
|
|
618
|
+
else if (lKey === "maxzoom") {
|
|
619
|
+
newKey = "maxzoom";
|
|
620
|
+
}
|
|
621
|
+
else if (lKey === "tilesize") {
|
|
622
|
+
newKey = "tileSize";
|
|
623
|
+
}
|
|
624
|
+
else if (lKey === "clusterradius") {
|
|
625
|
+
newKey = "clusterRadius";
|
|
626
|
+
}
|
|
627
|
+
else if (lKey === "clustermaxzoom") {
|
|
628
|
+
newKey = "clusterMaxZoom";
|
|
629
|
+
}
|
|
630
|
+
else if (lKey === "clusterminpoints") {
|
|
631
|
+
newKey = "clusterMinPoints";
|
|
632
|
+
}
|
|
633
|
+
else if (lKey === "clusterproperties") {
|
|
634
|
+
newKey = "clusterProperties";
|
|
635
|
+
}
|
|
636
|
+
else if (lKey === "linemetrics") {
|
|
637
|
+
newKey = "lineMetrics";
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
newKey = _.kebabCase(newKey).toLowerCase();
|
|
641
|
+
}
|
|
642
|
+
if (key === "visibility" && _.isBoolean(value)) {
|
|
643
|
+
return ["visibility", value ? "visible" : "none"];
|
|
644
|
+
}
|
|
645
|
+
if (excludeKeys.includes(key) || excludeKeys.includes(newKey)) {
|
|
646
|
+
return [key, value];
|
|
647
|
+
}
|
|
648
|
+
if (Array.isArray(value) || typeof value === "object") {
|
|
649
|
+
value = mProps(value, excludeKeys);
|
|
650
|
+
}
|
|
651
|
+
return [newKey, value];
|
|
652
|
+
}));
|
|
653
|
+
}
|
|
654
|
+
return properties;
|
|
655
|
+
};
|
|
554
656
|
const a = ansuko;
|
|
555
657
|
a.toLngLatArray = toLngLatArray;
|
|
556
658
|
a.toGeoJson = toGeoJson;
|
|
@@ -562,6 +664,8 @@ const ansukoGeoPlugin = (ansuko) => {
|
|
|
562
664
|
a.toMultiPolygonGeoJson = toMultiPolygonGeoJson;
|
|
563
665
|
a.unionPolygon = unionPolygon;
|
|
564
666
|
a.parseToTerraDraw = parseToTerraDraw;
|
|
667
|
+
a.mZoomInterpolate = mZoomInterpolate;
|
|
668
|
+
a.mProps = mProps;
|
|
565
669
|
return ansuko;
|
|
566
670
|
};
|
|
567
671
|
export default ansukoGeoPlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ansuko",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors. Fixes lodash quirks, adds Promise support, Japanese text processing, and GeoJSON utilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lodash",
|