mapshaper 0.7.2 → 0.7.3

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 (80) hide show
  1. package/LICENSE +1 -1
  2. package/mapshaper.js +1 -1
  3. package/package.json +4 -2
  4. package/www/mapshaper.js +1 -1
  5. package/www/docs/_assets/cmd-search.js +0 -213
  6. package/www/docs/_assets/docs.css +0 -722
  7. package/www/docs/_assets/docs.js +0 -75
  8. package/www/docs/_assets/highlight.css +0 -10
  9. package/www/docs/essentials/command-line.html +0 -127
  10. package/www/docs/essentials/command-line.html.md +0 -112
  11. package/www/docs/essentials/web-app.html +0 -138
  12. package/www/docs/essentials/web-app.html.md +0 -106
  13. package/www/docs/examples/basics.html +0 -275
  14. package/www/docs/examples/basics.html.md +0 -370
  15. package/www/docs/examples/data/Makefile +0 -31
  16. package/www/docs/examples/data/globe.msx +0 -0
  17. package/www/docs/examples/data/globe.svg +0 -616
  18. package/www/docs/examples/data/globe.txt +0 -21
  19. package/www/docs/examples/data/globe.zip +0 -0
  20. package/www/docs/examples/data/ne_50m_admin_0_countries.geojson +0 -1
  21. package/www/docs/examples/data/ne_50m_admin_1_states_provinces_lakes.geojson +0 -1
  22. package/www/docs/examples/data/us-states.msx +0 -0
  23. package/www/docs/examples/data/us-states.svg +0 -56
  24. package/www/docs/examples/data/us-states.txt +0 -6
  25. package/www/docs/examples/data/us-states.zip +0 -0
  26. package/www/docs/examples/globe.html +0 -108
  27. package/www/docs/examples/globe.html.md +0 -64
  28. package/www/docs/examples/us-states.html +0 -88
  29. package/www/docs/examples/us-states.html.md +0 -44
  30. package/www/docs/formats/csv.html +0 -127
  31. package/www/docs/formats/csv.html.md +0 -97
  32. package/www/docs/formats/dbf.html +0 -87
  33. package/www/docs/formats/dbf.html.md +0 -39
  34. package/www/docs/formats/flatgeobuf.html +0 -85
  35. package/www/docs/formats/flatgeobuf.html.md +0 -41
  36. package/www/docs/formats/geojson.html +0 -107
  37. package/www/docs/formats/geojson.html.md +0 -65
  38. package/www/docs/formats/geopackage.html +0 -87
  39. package/www/docs/formats/geopackage.html.md +0 -42
  40. package/www/docs/formats/json.html +0 -83
  41. package/www/docs/formats/json.html.md +0 -35
  42. package/www/docs/formats/kml.html +0 -82
  43. package/www/docs/formats/kml.html.md +0 -39
  44. package/www/docs/formats/overview.html +0 -191
  45. package/www/docs/formats/overview.html.md +0 -34
  46. package/www/docs/formats/shapefile.html +0 -123
  47. package/www/docs/formats/shapefile.html.md +0 -84
  48. package/www/docs/formats/snapshot.html +0 -87
  49. package/www/docs/formats/snapshot.html.md +0 -39
  50. package/www/docs/formats/svg.html +0 -99
  51. package/www/docs/formats/svg.html.md +0 -51
  52. package/www/docs/formats/topojson.html +0 -102
  53. package/www/docs/formats/topojson.html.md +0 -54
  54. package/www/docs/gallery/index.html +0 -80
  55. package/www/docs/gallery/index.html.md +0 -29
  56. package/www/docs/guides/combining-layers.html +0 -109
  57. package/www/docs/guides/combining-layers.html.md +0 -89
  58. package/www/docs/guides/expressions.html +0 -600
  59. package/www/docs/guides/expressions.html.md +0 -376
  60. package/www/docs/guides/programmatic.html +0 -117
  61. package/www/docs/guides/programmatic.html.md +0 -91
  62. package/www/docs/guides/projections.html +0 -158
  63. package/www/docs/guides/projections.html.md +0 -118
  64. package/www/docs/guides/simplification.html +0 -110
  65. package/www/docs/guides/simplification.html.md +0 -96
  66. package/www/docs/guides/topology.html +0 -90
  67. package/www/docs/guides/topology.html.md +0 -63
  68. package/www/docs/images/cal-counties.png +0 -0
  69. package/www/docs/images/simplification-detail.png +0 -0
  70. package/www/docs/images/simplification-dp.png +0 -0
  71. package/www/docs/images/simplification-mod2.png +0 -0
  72. package/www/docs/images/tiger-counties.png +0 -0
  73. package/www/docs/index.html +0 -101
  74. package/www/docs/index.html.md +0 -59
  75. package/www/docs/reference.html +0 -1302
  76. package/www/docs/reference.html.md +0 -1817
  77. package/www/docs/whats-new.html +0 -77
  78. package/www/docs/whats-new.html.md +0 -59
  79. package/www/llms-full.txt +0 -4053
  80. package/www/llms.txt +0 -55
@@ -1,376 +0,0 @@
1
- ---
2
- title: JavaScript expressions
3
- description: Reference for the JS expressions used in -each, -filter, -calc, -where, -sort, -if, -run and other Mapshaper commands.
4
- ---
5
-
6
- # JavaScript expressions
7
-
8
- Many Mapshaper commands take a **JS expression** as an argument or option. Expressions let you read and write per-feature attributes, derive new fields, filter records, sort, generate templated commands, and inspect layer-level metadata. The same expression syntax and execution context are reused across commands, so once you've learned the shape of a `-each` expression you can use it almost everywhere.
9
-
10
- ```bash
11
- mapshaper counties.shp \
12
- -each 'STATE_FIPS = COUNTY_FIPS.substr(0, 2),
13
- AREA_KM2 = this.area / 1e6' \
14
- -o out.shp
15
- ```
16
-
17
- Expressions are plain JavaScript. They can use any built-in language feature (arithmetic, string methods, conditionals, regex, etc.). Some commands also expect the expression to return a particular kind of value — `-filter` and `-inspect` expect `true` or `false`, `-sort` expects a sort key, `-split` expects a group identifier, and so on.
18
-
19
- ## Where expressions appear
20
-
21
- | Command | Expression role | Type |
22
- | --- | --- | --- |
23
- | [`-each`](/docs/reference.html.md#-each) | Run side-effects per feature, including assignments to data fields | feature |
24
- | [`-filter`](/docs/reference.html.md#-filter) | Boolean test, kept if `true` | feature, returns boolean |
25
- | [`-sort`](/docs/reference.html.md#-sort) | Returns the sort key for each feature | feature |
26
- | [`-inspect`](/docs/reference.html.md#-inspect) | Boolean test, prints matching feature(s) | feature, returns boolean |
27
- | [`-split`](/docs/reference.html.md#-split) | Returns the value used to group features into output layers | feature |
28
- | [`-subdivide`](/docs/reference.html.md#-subdivide) | Boolean test driving recursive partitioning, can call group functions like `sum()` | feature, returns boolean |
29
- | [`-calc` and `calc=` options](/docs/reference.html.md#-calc) | Aggregations across a group of features (`sum`, `count`, `median`, etc.) | calc |
30
- | `where=` (on `-filter`, `-each`, `-affine`, `-dashlines`, `-dissolve`, `-innerlines`, `-join`, `-style`, `-symbols`, `-calc`) | Sub-filter applied before the main operation | feature, returns boolean |
31
- | `weight=` on `-dissolve`/`-points` | Weighting expression for centroid calculation | feature |
32
- | Attribute options on [`-style`](/docs/reference.html.md#-style) and [`-symbols`](/docs/reference.html.md#-symbols) | Most values (`fill=`, `stroke=`, `stroke-width=`, `opacity=`, `r=`, `label-text=`, `dx=`, `dy=`, `font-size=`, etc.) accept either a literal or a JS expression evaluated per feature | feature |
33
- | [`-lines where=` and `each=`](/docs/reference.html.md#-lines) | Operates on **pairs** of features either side of a path, exposed as `A` and `B` | pair |
34
- | [`-if` / `-elif`](/docs/reference.html.md#-if) | Boolean test on layer-level metadata | layer |
35
- | [`-define`](/docs/reference.html.md#-define) | Stores variables and helper functions in a global namespace shared by later expressions | layer |
36
- | [`-run`](/docs/reference.html.md#-run) | Generates command strings, with embedded `{...}` template substitutions | template |
37
-
38
- <!-- | `bbox=` on `-rectangles` | Returns a `[xmin, ymin, xmax, ymax]` per feature | feature | -->
39
- These five flavors &mdash; **feature**, **calc**, **pair**, **layer** and **template** &mdash; share most of their context but differ in which variables are available and which functions are in scope.
40
-
41
- ## The execution context
42
-
43
- Inside any feature-level expression you have access to:
44
-
45
- - **Field names as bare variables.** Reading a field name returns its value. Assigning to a field name updates the current feature's record (and creates the field on first use). If a field name is not a valid JavaScript identifier (e.g. it contains spaces or starts with a digit), use `d["field name"]` to reference it.
46
- - **`this`**, the feature proxy. Provides geometry-derived properties (`this.area`, `this.bbox`, etc.) and read/write access to the feature's `properties`, `geojson` and `coordinates`.
47
- - **`d`**, a reference to the data record (the same object as `this.properties`).
48
- - **`global`**, an object that persists across commands. Variables created by `-define`, by assignment in a `-calc` expression, or by writing to `global.foo = ...` inside `-each` end up here. Values set by [`-vars`](/docs/reference.html.md#-vars) and [`-defaults`](/docs/reference.html.md#-defaults) live in a separate *templating* scope (read by `{{X}}` substitution) and are **not** visible by bare name in expressions; use `-define` if you want a value reachable from both `{{X}}` and JS expressions.
49
- - **`console.log()`** for printing values to stderr while debugging.
50
- - **Built-in helpers** (see [Helper functions](#helper-functions) below).
51
- - **User helpers** loaded by [`-define`](/docs/reference.html.md#-define), [`-include`](/docs/reference.html.md#-include) or [`-require`](/docs/reference.html.md#-require).
52
-
53
- If a name is referenced but not present in any of the above, JavaScript treats it as `undefined`, *not* an error. This is convenient when chaining expressions across heterogeneous datasets but can mask typos &mdash; double-check field names with `mapshaper -info` if a `-filter` returns a suspiciously empty result.
54
-
55
- ### Field assignment
56
-
57
- Assigning to a bare name creates or updates a data field on the current feature:
58
-
59
- ```bash
60
- mapshaper counties.shp -each 'POP_DENSITY = POPULATION / (this.area / 1e6)' -o
61
- ```
62
-
63
- Bare assignments like `POP_DENSITY = ...` will create the data table if the layer doesn't already have one. Assignments routed through `this.properties.X = ...` or `d.X = ...` only update an existing data table &mdash; prefer a bare assignment if you're not sure the layer has one yet.
64
-
65
- To delete a field, use the JS `delete` operator:
66
-
67
- ```bash
68
- mapshaper states.shp -each 'delete STATE_NAME, delete GEOID' -o
69
- ```
70
-
71
- To replace the entire record, assign to `this.properties`:
72
-
73
- ```bash
74
- mapshaper states.shp -each 'this.properties = {FID: this.id, NAME: NAME}' -o
75
- ```
76
-
77
- ### Multiple statements
78
-
79
- Use commas to evaluate multiple sub-expressions. The value of the whole expression is the value of the last sub-expression (relevant for `-filter`, `-sort`, `-split`):
80
-
81
- ```bash
82
- mapshaper data.csv -each 'A = parseInt(A), B = A * 2, C = A + B'
83
- ```
84
-
85
- Inside command files, you can also break a long expression across lines with `\`:
86
-
87
- ```
88
- -each '
89
- STATE_FIPS = COUNTY_FIPS.substr(0, 2), \
90
- AREA_KM2 = this.area / 1e6, \
91
- CENTROID_X = this.centroidX, \
92
- CENTROID_Y = this.centroidY
93
- '
94
- ```
95
-
96
- ## Feature properties (`this`)
97
-
98
- `this` is a proxy for the current feature. It gives you geometry-derived properties and a few editing affordances. The properties below are read-only unless the description says otherwise.
99
-
100
- ### All layer types
101
-
102
- | Name | Description |
103
- | --- | --- |
104
- | `this.id` | 0-based numerical id of the feature |
105
- | `this.layer_name` | Name of the layer (or empty string) |
106
- | `this.properties` | Data record. Read/write &mdash; assign a new object to replace all attributes. |
107
- | `this.layer` | Layer proxy &mdash; see [Layer-level properties](#layer-level-properties-thislayer) |
108
- | `this.geojson` | GeoJSON Feature (geometry + properties). Read/write &mdash; assign a new Feature to replace this one. |
109
- | `this.geometry` | Just the GeoJSON geometry. Read/write. |
110
-
111
- ### Polygon, polyline and point layers (with geometry)
112
-
113
- | Name | Description |
114
- | --- | --- |
115
- | `this.partCount` | 1 for single-part features, >1 for multi-part, 0 for null |
116
- | `this.isNull` | `true` if `partCount === 0` |
117
- | `this.bbox` | `[xmin, ymin, xmax, ymax]` |
118
- | `this.width`, `this.height` | Bounding-box width and height |
119
- | `this.bboxContainsPoint(x, y)` | `true` if the bbox covers the point |
120
- | `this.bboxIntersectsRectangle(a, b, c, d)` | `true` if the bbox overlaps the rectangle |
121
- | `this.bboxContainsRectangle(a, b, c, d)` | `true` if the bbox fully contains the rectangle |
122
- | `this.bboxContainedByRectangle(a, b, c, d)` | `true` if the bbox is fully inside the rectangle |
123
-
124
- ### Polygon-only
125
-
126
- | Name | Description |
127
- | --- | --- |
128
- | `this.area` | Area in source units (square meters for unprojected lat/long, computed on a sphere) |
129
- | `this.planarArea` | Treats lat/long as planar &mdash; useful inside expressions that already account for projection |
130
- | `this.originalArea` | Area before any `-simplify` was applied |
131
- | `this.perimeter` | Perimeter length (meters for unprojected lat/long) |
132
- | `this.compactness` | Polsby-Popper compactness ratio (0&ndash;1) |
133
- | `this.innerPct` | Fraction of the perimeter that is shared with neighboring polygons |
134
- | `this.centroidX`, `this.centroidY` | Centroid coordinates (computed from the largest ring; ignores holes) |
135
- | `this.innerX`, `this.innerY` | An interior point useful for placing a label or symbol |
136
-
137
- ### Polyline-only
138
-
139
- | Name | Description |
140
- | --- | --- |
141
- | `this.length` | Total length (meters for unprojected lat/long) |
142
-
143
- ### Point-only
144
-
145
- | Name | Description |
146
- | --- | --- |
147
- | `this.coordinates` | The full nested coordinate array, or `null`. Read/write &mdash; assign `null` to drop the geometry. |
148
- | `this.x`, `this.y` | Coordinates of the first point of the (possibly multi-) feature. Read/write. |
149
-
150
- > **Why it matters for unprojected data:** `this.area` and `this.length` use *spherical* (not planar or ellipsoidal) geometry on lat/long datasets. Results are in square meters / meters and accurate to within ~0.5% for most use cases. If you need ellipsoidal accuracy, project first with `-proj`.
151
-
152
- ## Layer-level properties (`this.layer`)
153
-
154
- `this.layer` exposes information about the layer the feature belongs to. Useful in expressions that need to know about other features:
155
-
156
- | Name | Description |
157
- | --- | --- |
158
- | `this.layer.name` | Layer name |
159
- | `this.layer.type` | `'polygon'`, `'polyline'`, `'point'` or `null` |
160
- | `this.layer.size` | Feature count |
161
- | `this.layer.empty` | `true` if `size === 0` |
162
- | `this.layer.bbox` | `[xmin, ymin, xmax, ymax]`, with extra `cx`, `cy`, `width`, `height`, `left`, `right`, `top`, `bottom` properties |
163
- | `this.layer.data` | The full array of data records (use sparingly inside per-feature loops) |
164
- | `this.layer.field_exists(name)` | Returns `true` if a field exists |
165
- | `this.layer.field_type(name)` | Returns `'string'`, `'number'`, `'object'` etc., or `null` |
166
- | `this.layer.field_includes(name, value)` | Returns `true` if any record's `name` field equals `value` |
167
-
168
- ## Helper functions
169
-
170
- These are always in scope inside feature expressions:
171
-
172
- - `round(num [, decimals])` &mdash; Round to N decimal places (default 0). Faster and easier than `Math.round`.
173
- - `sprintf(fmt, ...)` &mdash; printf-style formatter (uses [printj](https://github.com/SheetJS/printj) syntax).
174
- - `format_dms(coord [, fmt])` &mdash; Format a number as a degrees/minutes/seconds string. Common formats: `'DD° MM′ SS.SSSSS″ [NS]'`, `'DdMmSs [EW]'`, `'[+-]DDDMM.MMMMM'`, `'[-]DD.DDDDD°'`.
175
- - `parse_dms(string [, fmt])` &mdash; Parse a DMS string back to a number.
176
- - `blend(c1, c2, ...)` &mdash; Mix CSS color strings together (returns a hex string).
177
- - `console.log(...)` &mdash; Write to stderr.
178
-
179
- JavaScript's built-in `Math`, `JSON`, `Number`, `String`, `Array`, `Date`, `Object` etc. are all available. Node-specific globals like `process`, `require` and `setTimeout` are not.
180
-
181
- ## Calc expressions
182
-
183
- `-calc` and any command's `calc=` option use the same context as `-each` plus a set of *aggregate* functions that operate over the entire group of features (or the entire layer for `-calc`). Each aggregate function takes a per-feature expression and reduces it to a single value across the group.
184
-
185
- | Function | Description |
186
- | --- | --- |
187
- | `count()` | Number of records in the collection |
188
- | `sum(<expr>)` | Sum of the per-feature expression |
189
- | `mean(<expr>)`, `average(<expr>)` | Arithmetic mean |
190
- | `median(<expr>)` | Median value |
191
- | `mode(<expr>)` | Most common value (first one wins ties) |
192
- | `min(<expr>)`, `max(<expr>)` | Extremes |
193
- | `quartile1(<expr>)`, `quartile2(<expr>)`, `quartile3(<expr>)` | Quartiles |
194
- | `iqr(<expr>)` | Interquartile range |
195
- | `quantile(<expr>, <pct>)` | Arbitrary percentile (0&ndash;1) |
196
- | `collect(<expr>)` | Array of all values (preserves order) |
197
- | `collectIds()` | Array of feature ids |
198
- | `first(<expr>)`, `last(<expr>)` | First / last value seen |
199
- | `every(<expr>)`, `some(<expr>)` | Boolean reductions |
200
-
201
- Argument expressions use the same syntax as `-each`, so per-feature properties and helpers are available:
202
-
203
- ```bash
204
- mapshaper counties.shp \
205
- -calc 'TOTAL_POP = sum(POP),
206
- MEAN_AREA_KM2 = sum(this.area / 1e6) / count(),
207
- TOP_DENSITY = max(POP / this.area)'
208
- ```
209
-
210
- Calc expressions can also use assignments to expose values to subsequent commands via the `global` namespace (see [Sharing state across commands](#sharing-state-across-commands) below).
211
-
212
- ## Pair expressions (`A` and `B`)
213
-
214
- The `-lines where=` and `each=` options operate on path segments shared between two adjacent features. Inside these expressions:
215
-
216
- - `A` is the feature on one side of the path
217
- - `B` is the feature on the other side, or `null` for outer boundaries
218
-
219
- Both `A` and `B` give you the full set of feature properties (`A.properties`, `A.area`, `A.id`, etc.).
220
-
221
- ```bash
222
- # Keep only inner boundaries between two different states
223
- mapshaper counties.shp \
224
- -lines where='B && A.STATE != B.STATE' \
225
- -o state-borders.shp
226
- ```
227
-
228
- ## Layer-level expressions (`-if`, `-define`)
229
-
230
- The `-if` family and `-define` evaluate against the *current command's target layer(s)*, not per feature. The context exposes:
231
-
232
- - `target` &mdash; the proxy for the single target layer (only set when there's exactly one target)
233
- - `targets` &mdash; an array-like of layer proxies, also indexable by name (`targets.states`)
234
- - `layer_name`, `data`, `type`, `size`, `empty`, `bbox`
235
- - `field_exists(name)`, `field_type(name)`, `field_includes(name, value)`
236
- - `layer_exists(name [, geometry_type])`
237
- - `file_exists(path)`
238
- - `global` &mdash; the shared variable namespace
239
-
240
- ```bash
241
- mapshaper data.csv \
242
- -calc 'N = count()' \
243
- -if 'global.N < 5' -print 'LOW SAMPLE SIZE, STOPPING' -stop -endif
244
- ```
245
-
246
- Each entry in `targets` exposes useful summary stats from `-info`: `layer_name`, `feature_count`, `null_shape_count`, `null_data_count`, `bbox`, `proj4`. Reading `targets[0].geojson` returns the layer as a GeoJSON FeatureCollection; assigning to it replaces the layer with the FeatureCollection you provide.
247
-
248
- ## Template expressions (`-run`)
249
-
250
- `-run` accepts either a path to a [command file](/docs/reference.html.md#command-files) or a string containing one or more curly-brace template expressions. Each `{...}` is evaluated as a JS expression and substituted into the resulting command string before Mapshaper parses it.
251
-
252
- ```bash
253
- # Project to a transverse Mercator centred on the layer
254
- mapshaper -i country.shp -require projection.js \
255
- -run '-proj {tmerc(target.bbox)}' -o
256
- ```
257
-
258
- Inside the curly braces you have:
259
-
260
- - `target` and `targets` (same as `-if`)
261
- - `io.ifile(filename, data)` &mdash; spill data to a temp file and yield its path, useful for piping computed JSON back into `-i`
262
- - Anything loaded by `-require` or `-define`
263
-
264
- Bare function calls outside curly braces are also evaluated directly, so `-run 'tmerc(target.bbox)'` works the same as `-run '{tmerc(target.bbox)}'` when the function name was loaded via `-require`.
265
-
266
- ## Loading helpers
267
-
268
- Three commands extend the expression context with your own variables and helpers:
269
-
270
- - [`-define`](/docs/reference.html.md#-define) takes an inline JS expression and stores any assignments on the global namespace. Good for one-liners.
271
- - [`-include`](/docs/reference.html.md#-include) loads a `.js` file containing a single object literal; each property of that object becomes a variable in subsequent expressions.
272
- - [`-require`](/docs/reference.html.md#-require) loads an installed npm module or a local module file. With `alias=foo` the module is bound to that name; without an alias, the module's exported names are added directly to the context.
273
-
274
- ```bash
275
- mapshaper data.json \
276
- -require ./helpers.mjs \
277
- -each 'displayname = formatName(d)' \
278
- -o data.json
279
- ```
280
-
281
- ```bash
282
- mapshaper -define 'KM_PER_MILE = 1.609344' \
283
- routes.geojson \
284
- -each 'KM = MILES * global.KM_PER_MILE' \
285
- -o
286
- ```
287
-
288
- ## Sharing state across commands
289
-
290
- Mapshaper has two scopes for values that persist between commands. They share a name lookup for `{{X}}` substitution but are otherwise independent.
291
-
292
- - **Expression scope (`global`)** &mdash; written by `-define`, `-include`, `-require`, `-colorizer`, and `-calc` assignments (e.g. `N = count()`) or any `global.foo = ...` inside `-each`. Values can be any JavaScript value (numbers, strings, functions, objects). Read by JS expressions as bare names, and as `global.X` everywhere. `{{X}}` substitution falls back to this scope, so `-define base = "out"` &rarr; `-o {{base}}.geojson` and `-calc 'N = count()'` &rarr; `-if '{{N}} > 100'` work as you'd expect.
293
- - **Templating scope** &mdash; written by [`-vars`](/docs/reference.html.md#-vars) and [`-defaults`](/docs/reference.html.md#-defaults). Values must be primitives (string / number / boolean / null) and are validated at write time. Read by `{{X}}` substitution; `{{X}}` checks the templating scope first, then falls back to the expression scope. **Not** visible by bare name in JS expressions &mdash; that's deliberate, so a string set by `-vars N=5` can't silently coerce into arithmetic.
294
-
295
- If you want one value usable in both contexts, set it once with `-define`. If you only need it in command strings, use `-vars` (or `-defaults` for command-file overridable defaults).
296
-
297
- ```bash
298
- mapshaper counties.shp \
299
- -calc 'BIG = count("POP > 1000000")' \
300
- -if 'global.BIG > 0' \
301
- -filter 'POP > 1000000' \
302
- -o big-counties.shp \
303
- -endif
304
- ```
305
-
306
- ## Common pitfalls
307
-
308
- - **Quoting.** In bash/zsh, wrap expressions in single quotes so the shell doesn't expand `!`, `$` or backticks. In Windows `cmd.exe`, use double quotes and escape inner quotes with backslashes. In PowerShell, prefer single quotes, or escape `$` with a backtick.
309
- - **Type coercion from CSVs.** Numeric-looking strings in CSVs are parsed as numbers by default; identifier-like strings (FIPS, ZIP) need `string-fields=` on `-i` to preserve leading zeros. See [CSV practical notes](/docs/formats/csv.html.md#practical-notes).
310
- - **Field name collisions.** A field called `area`, `length`, `id` etc. shadows the built-in property of the same name. Mapshaper prints a warning. Either rename the field with `-rename-fields`, or read the property via `this.area` rather than the bare name.
311
- - **Lat/long area surprises.** `this.area` on an unprojected polygon returns *square meters on a sphere*, not square degrees. To get square kilometres, divide by `1e6`. To get planar square degrees (e.g. for sanity checks), use `this.planarArea`.
312
- - **Centroids ignore holes.** `this.centroidX/Y` is the centroid of the largest ring. For a labelling point that's guaranteed inside the polygon, use `innerX`/`innerY`.
313
- - **`-each` doesn't return values.** Its expression is evaluated for side-effects only. Use `-filter`, `-sort` or `-calc` if you want the return value to drive behavior.
314
- - **Reserved names.** `this`, `d`, `_`, `global`, `console`, `target`, `targets` and the helper function names listed above are not safe to use as field names.
315
- - **Auto-vivification of fields.** Assigning to a name that isn't a known field creates a new field on every record. If you only want to set a field on *some* records, wrap it in a conditional and assign explicit `null` for the others, otherwise downstream readers may see `undefined` instead of a real null.
316
-
317
- ## Examples
318
-
319
- ```bash
320
- # Add two derived fields
321
- mapshaper counties.shp \
322
- -each 'STATE_FIPS = COUNTY_FIPS.substr(0, 2),
323
- AREA_KM2 = round(this.area / 1e6, 2)' \
324
- -o out.shp
325
-
326
- # Drop features outside a date window
327
- mapshaper events.csv \
328
- -filter 'new Date(DATE) >= new Date("2020-01-01")' \
329
- -o recent.csv
330
-
331
- # Sort polygons largest-first
332
- mapshaper countries.geojson \
333
- -sort '-this.area' \
334
- -o sorted.geojson
335
-
336
- # Look up one feature
337
- mapshaper states.geojson -inspect 'NAME == "Delaware"'
338
-
339
- # Aggregate stats during a dissolve
340
- mapshaper counties.shp \
341
- -dissolve STATE calc='N = count(),
342
- POP = sum(POP),
343
- MEDIAN_INC = median(MEDIAN_INC)' \
344
- -o states.shp
345
-
346
- # Conditional pipeline based on a calc result
347
- mapshaper data.csv \
348
- -calc 'N = count()' \
349
- -if 'global.N == 0' -stop -endif \
350
- -o data.csv
351
-
352
- # Filter shared boundaries
353
- mapshaper counties.shp \
354
- -lines where='B && A.STATE != B.STATE' \
355
- -o state-borders.shp
356
-
357
- # Per-feature styling: circle radius from POP, fill from an expression
358
- mapshaper cities.geojson \
359
- -style r='Math.sqrt(POP) / 40' \
360
- fill='POP > 1e6 ? "#c33" : "#39c"' \
361
- opacity=0.7 \
362
- -o cities.svg
363
-
364
- # Project to a layer-specific CRS
365
- mapshaper -i country.shp -require ./projection.js \
366
- -run '-proj {tmerc(target.bbox)}' -o
367
- ```
368
-
369
- ## See also
370
-
371
- - [`-each`](/docs/reference.html.md#-each) &mdash; the canonical feature-expression command
372
- - [`-filter`](/docs/reference.html.md#-filter)
373
- - [`-calc`](/docs/reference.html.md#-calc)
374
- - [`-define`](/docs/reference.html.md#-define), [`-include`](/docs/reference.html.md#-include), [`-require`](/docs/reference.html.md#-require)
375
- - [`-run`](/docs/reference.html.md#-run)
376
- - [Basics](/docs/examples/basics.html.md) &mdash; recipes that put expressions to work
@@ -1,117 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Using Mapshaper from Node.js &middot; mapshaper docs</title>
7
- <meta name="description" content="Integrating Mapshaper into JavaScript builds and applications via its Node.js API.">
8
- <link rel="icon" type="image/png" href="/images/icon.png">
9
- <link rel="stylesheet" href="/docs/_assets/highlight.css">
10
- <link rel="stylesheet" href="/docs/_assets/docs.css">
11
- </head>
12
- <body class="">
13
-
14
- <header class="page-header">
15
- <a href="/" class="mapshaper-logo">map<span class="logo-highlight">shaper</span></a>
16
- <span class="header-section-label">Docs</span>
17
- <nav class="header-nav">
18
- <a href="/">Web app</a>
19
- <a href="https://github.com/mbloch/mapshaper">GitHub</a>
20
- <a href="/sponsor.html" class="sponsor-link"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg> Become a sponsor</a>
21
- </nav>
22
- </header>
23
-
24
- <div class="docs-layout">
25
-
26
- <aside class="docs-sidebar">
27
- <div class="sidebar-inner">
28
- <nav class="docs-nav"><ul class="top-links"><li><a href="/docs/">Home</a></li><li><a href="/docs/whats-new.html">What&#39;s new</a></li><li><a href="/docs/reference.html">Command reference</a></li><li><a href="/docs/gallery/">Gallery</a></li></ul><h2>Getting started</h2><ul><li><a href="/docs/essentials/command-line.html">The command-line tool</a></li><li><a href="/docs/essentials/web-app.html">The web app</a></li></ul><h2>Guides</h2><ul><li><a href="/docs/guides/simplification.html">Simplification</a></li><li><a href="/docs/guides/expressions.html">JavaScript expressions</a></li><li><a href="/docs/guides/projections.html">Projections</a></li><li><a href="/docs/guides/topology.html">Topology and cleaning</a></li><li><a href="/docs/guides/combining-layers.html">Combining two layers</a></li><li><a href="/docs/guides/programmatic.html" class="is-active">Using Mapshaper from Node.js</a></li></ul><h2>Formats</h2><ul><li><a href="/docs/formats/overview.html">Overview</a></li><li><a href="/docs/formats/shapefile.html">Shapefile</a></li><li><a href="/docs/formats/geojson.html">GeoJSON</a></li><li><a href="/docs/formats/topojson.html">TopoJSON</a></li><li><a href="/docs/formats/geopackage.html">GeoPackage</a></li><li><a href="/docs/formats/flatgeobuf.html">FlatGeobuf</a></li><li><a href="/docs/formats/kml.html">KML / KMZ</a></li><li><a href="/docs/formats/csv.html">CSV / TSV</a></li><li><a href="/docs/formats/dbf.html">DBF</a></li><li><a href="/docs/formats/json.html">JSON records</a></li><li><a href="/docs/formats/svg.html">SVG</a></li><li><a href="/docs/formats/snapshot.html">Mapshaper snapshot</a></li></ul><h2>Examples</h2><ul><li><a href="/docs/examples/basics.html">Basics</a></li><li><a href="/docs/examples/globe.html">Globe</a></li><li><a href="/docs/examples/us-states.html">U.S. state map</a></li></ul></nav>
29
- </div>
30
- </aside>
31
-
32
- <main class="docs-main">
33
- <article class="docs-article">
34
- <div class="docs-breadcrumbs"><a href="/docs/">Docs</a> &rsaquo; Guides &rsaquo; Using Mapshaper from Node.js</div>
35
- <h1 id="using-mapshaper-from-nodejs">Using Mapshaper from Node.js</h1>
36
- <p>This page is for developers who want to use Mapshaper&#39;s geoprocessing functions inside their own programs &mdash; either by shelling out to the CLI from a build tool, or by calling Mapshaper&#39;s API from Node.js code directly.</p>
37
- <h2 id="calling-the-cli-from-a-build-tool">Calling the CLI from a build tool</h2>
38
- <p>The simplest way to script Mapshaper is to invoke the <code>mapshaper</code> (or <code>mapshaper-xl</code>) command from <code>make</code> or a shell script.</p>
39
- <p>Example <code>Makefile</code> target:</p>
40
- <pre><code class="hljs language-make"><span class="hljs-section">europe.topojson: shp/world_countries.shp</span>
41
- mapshaper <span class="hljs-variable">{{CONTENT}}lt;</span> \
42
- -filter <span class="hljs-string">&quot;CONTINENT == &#x27;Europe&#x27;&quot;</span> \
43
- -simplify interval=100m keep-shapes \
44
- -o <span class="hljs-variable">$@</span>
45
- </code></pre>
46
- <p>An alternative to embedding a long series of Mapshaper commands on the command line is to put them in a <code>.txt</code> file and pass the file to <code>mapshaper</code>. See <a href="/docs/reference.html#command-files">command files</a> and <a href="/docs/reference.html#variable-interpolation">variable interpolation</a> in the reference.</p>
47
- <h2 id="the-nodejs-api">The Node.js API</h2>
48
- <p>Mapshaper exposes three top-level functions for running editing commands programmatically. All three accept the same command-line string format as the <code>mapshaper</code> CLI.</p>
49
- <h3 id="runcommandscommands-input-callback"><code>runCommands(commands[, input][, callback])</code></h3>
50
- <p>Runs a command line against files on disk (or in-memory). The <code>-o</code> command(s) write their output to disk.</p>
51
- <ul>
52
- <li><code>commands</code> &mdash; a command-line string.</li>
53
- <li><code>input</code> (optional) &mdash; an object whose keys are filenames and whose values are file contents. Files referenced by <code>-i</code> are looked up here first, then on the filesystem.</li>
54
- <li><code>callback</code> (optional) &mdash; a Node-style <code>function(err)</code>. Without a callback, <code>runCommands</code> returns a Promise.</li>
55
- </ul>
56
- <pre><code class="hljs language-javascript"><span class="hljs-keyword">import</span> mapshaper <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;mapshaper&#x27;</span>;
57
-
58
- <span class="hljs-keyword">await</span> mapshaper.<span class="hljs-title function_">runCommands</span>(<span class="hljs-string">&#x27;-i shapefiles/*.shp -o geojson/ format=geojson&#x27;</span>);
59
- </code></pre>
60
- <h3 id="applycommandscommands-input-callback"><code>applyCommands(commands[, input][, callback])</code></h3>
61
- <p>Same signature as <code>runCommands</code>, but instead of writing files to disk, the contents produced by <code>-o</code> are returned to the caller as a <code>{ filename: Buffer }</code> object. Useful for processing data without touching the filesystem.</p>
62
- <pre><code class="hljs language-javascript"><span class="hljs-keyword">import</span> mapshaper <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;mapshaper&#x27;</span>;
63
-
64
- <span class="hljs-keyword">const</span> input = { <span class="hljs-string">&#x27;input.csv&#x27;</span>: <span class="hljs-string">&#x27;lat,lng,value\n40.3,-72.3,1000&#x27;</span> };
65
- <span class="hljs-keyword">const</span> cmd = <span class="hljs-string">&#x27;-i input.csv -points x=lng y=lat -o output.geojson&#x27;</span>;
66
-
67
- <span class="hljs-keyword">const</span> output = <span class="hljs-keyword">await</span> mapshaper.<span class="hljs-title function_">applyCommands</span>(cmd, input);
68
- <span class="hljs-comment">// output[&#x27;output.geojson&#x27;] is a Buffer containing GeoJSON</span>
69
- </code></pre>
70
- <h3 id="runcommandsxlcommands-options-callback"><code>runCommandsXL(commands[, options][, callback])</code></h3>
71
- <p>Like <code>runCommands</code>, but the work runs in a child Node process configured with a larger maximum heap (8 GB by default). Equivalent to running <code>mapshaper-xl</code> from the command line. Override the heap size with the <code>xl</code> option:</p>
72
- <pre><code class="hljs language-javascript"><span class="hljs-keyword">await</span> mapshaper.<span class="hljs-title function_">runCommandsXL</span>(commands, { <span class="hljs-attr">xl</span>: <span class="hljs-string">&#x27;16gb&#x27;</span> });
73
- </code></pre>
74
- <p>This function reads input only from the filesystem &mdash; there&#39;s no <code>input</code> argument as on <code>runCommands</code>/<code>applyCommands</code>.</p>
75
- <h2 id="working-with-shapefiles-in-applycommands">Working with Shapefiles in <code>applyCommands</code></h2>
76
- <p>Shapefiles are really a set of component files. To import one through <code>applyCommands</code>, pass the contents of all the parts you care about:</p>
77
- <ul>
78
- <li><code>.shp</code> &mdash; geometry (Buffer or ArrayBuffer)</li>
79
- <li><code>.dbf</code> &mdash; attribute table (Buffer or ArrayBuffer)</li>
80
- <li><code>.prj</code> &mdash; coordinate system (string)</li>
81
- </ul>
82
- <p>Without <code>.dbf</code> you&#39;ll get geometry but no attributes; without <code>.prj</code>, projection-dependent commands won&#39;t have a coordinate system to work from.</p>
83
- <pre><code class="hljs language-javascript"><span class="hljs-keyword">const</span> input = {
84
- <span class="hljs-string">&#x27;world.shp&#x27;</span>: shpBuffer,
85
- <span class="hljs-string">&#x27;world.dbf&#x27;</span>: dbfBuffer,
86
- <span class="hljs-string">&#x27;world.prj&#x27;</span>: prjString
87
- };
88
- <span class="hljs-keyword">const</span> output = <span class="hljs-keyword">await</span> mapshaper.<span class="hljs-title function_">applyCommands</span>(
89
- <span class="hljs-string">&#x27;-i world.shp -simplify 10% -o world.geojson&#x27;</span>, input
90
- );
91
- </code></pre>
92
- <h2 id="versioning">Versioning</h2>
93
- <p>The Node API is stable across minor Mapshaper releases, but new options and commands appear regularly. The full set of accepted command-line options is the same as the CLI&#39;s, so the <a href="/docs/reference.html">command reference</a> is the authoritative list of what you can put into the <code>commands</code> string.</p>
94
-
95
- <div class="edit-link">
96
- <a href="https://github.com/mbloch/mapshaper/edit/master/docs/guides/programmatic.md">Edit this page on GitHub</a>
97
- </div>
98
- </article>
99
- </main>
100
-
101
- <aside class="docs-toc">
102
- <div class="docs-toc-title">On this page</div><ul><li class="lvl-2"><a href="#calling-the-cli-from-a-build-tool">Calling the CLI from a build tool</a></li><li class="lvl-2"><a href="#the-nodejs-api">The Node.js API</a></li><li class="lvl-3"><a href="#runcommandscommands-input-callback">runCommands(commands[, input][, callback])</a></li><li class="lvl-3"><a href="#applycommandscommands-input-callback">applyCommands(commands[, input][, callback])</a></li><li class="lvl-3"><a href="#runcommandsxlcommands-options-callback">runCommandsXL(commands[, options][, callback])</a></li><li class="lvl-2"><a href="#working-with-shapefiles-in-applycommands">Working with Shapefiles in applyCommands</a></li><li class="lvl-2"><a href="#versioning">Versioning</a></li></ul>
103
- </aside>
104
-
105
- </div>
106
-
107
- <script src="/docs/_assets/docs.js" defer></script>
108
-
109
- <footer class="docs-footer">
110
- <div class="docs-footer-inner">
111
- <span>mapshaper is free software, licensed under <a href="https://www.mozilla.org/MPL/2.0/">MPL 2.0</a>.</span>
112
- <span><a href="/privacy.html">Privacy</a> &middot; <a href="/terms.html">Terms</a> &middot; <a href="/sponsor.html">Support mapshaper</a></span>
113
- </div>
114
- </footer>
115
-
116
- </body>
117
- </html>
@@ -1,91 +0,0 @@
1
- ---
2
- title: Using Mapshaper from Node.js
3
- description: Integrating Mapshaper into JavaScript builds and applications via its Node.js API.
4
- ---
5
-
6
- # Using Mapshaper from Node.js
7
-
8
- This page is for developers who want to use Mapshaper's geoprocessing functions inside their own programs &mdash; either by shelling out to the CLI from a build tool, or by calling Mapshaper's API from Node.js code directly.
9
-
10
- ## Calling the CLI from a build tool
11
-
12
- The simplest way to script Mapshaper is to invoke the `mapshaper` (or `mapshaper-xl`) command from `make` or a shell script.
13
-
14
- Example `Makefile` target:
15
-
16
- ```make
17
- europe.topojson: shp/world_countries.shp
18
- mapshaper $< \
19
- -filter "CONTINENT == 'Europe'" \
20
- -simplify interval=100m keep-shapes \
21
- -o $@
22
- ```
23
-
24
- An alternative to embedding a long series of Mapshaper commands on the command line is to put them in a `.txt` file and pass the file to `mapshaper`. See [command files](/docs/reference.html.md#command-files) and [variable interpolation](/docs/reference.html.md#variable-interpolation) in the reference.
25
-
26
- ## The Node.js API
27
-
28
- Mapshaper exposes three top-level functions for running editing commands programmatically. All three accept the same command-line string format as the `mapshaper` CLI.
29
-
30
- ### `runCommands(commands[, input][, callback])`
31
-
32
- Runs a command line against files on disk (or in-memory). The `-o` command(s) write their output to disk.
33
-
34
- - `commands` &mdash; a command-line string.
35
- - `input` (optional) &mdash; an object whose keys are filenames and whose values are file contents. Files referenced by `-i` are looked up here first, then on the filesystem.
36
- - `callback` (optional) &mdash; a Node-style `function(err)`. Without a callback, `runCommands` returns a Promise.
37
-
38
- ```javascript
39
- import mapshaper from 'mapshaper';
40
-
41
- await mapshaper.runCommands('-i shapefiles/*.shp -o geojson/ format=geojson');
42
- ```
43
-
44
- ### `applyCommands(commands[, input][, callback])`
45
-
46
- Same signature as `runCommands`, but instead of writing files to disk, the contents produced by `-o` are returned to the caller as a `{ filename: Buffer }` object. Useful for processing data without touching the filesystem.
47
-
48
- ```javascript
49
- import mapshaper from 'mapshaper';
50
-
51
- const input = { 'input.csv': 'lat,lng,value\n40.3,-72.3,1000' };
52
- const cmd = '-i input.csv -points x=lng y=lat -o output.geojson';
53
-
54
- const output = await mapshaper.applyCommands(cmd, input);
55
- // output['output.geojson'] is a Buffer containing GeoJSON
56
- ```
57
-
58
- ### `runCommandsXL(commands[, options][, callback])`
59
-
60
- Like `runCommands`, but the work runs in a child Node process configured with a larger maximum heap (8 GB by default). Equivalent to running `mapshaper-xl` from the command line. Override the heap size with the `xl` option:
61
-
62
- ```javascript
63
- await mapshaper.runCommandsXL(commands, { xl: '16gb' });
64
- ```
65
-
66
- This function reads input only from the filesystem &mdash; there's no `input` argument as on `runCommands`/`applyCommands`.
67
-
68
- ## Working with Shapefiles in `applyCommands`
69
-
70
- Shapefiles are really a set of component files. To import one through `applyCommands`, pass the contents of all the parts you care about:
71
-
72
- - `.shp` &mdash; geometry (Buffer or ArrayBuffer)
73
- - `.dbf` &mdash; attribute table (Buffer or ArrayBuffer)
74
- - `.prj` &mdash; coordinate system (string)
75
-
76
- Without `.dbf` you'll get geometry but no attributes; without `.prj`, projection-dependent commands won't have a coordinate system to work from.
77
-
78
- ```javascript
79
- const input = {
80
- 'world.shp': shpBuffer,
81
- 'world.dbf': dbfBuffer,
82
- 'world.prj': prjString
83
- };
84
- const output = await mapshaper.applyCommands(
85
- '-i world.shp -simplify 10% -o world.geojson', input
86
- );
87
- ```
88
-
89
- ## Versioning
90
-
91
- The Node API is stable across minor Mapshaper releases, but new options and commands appear regularly. The full set of accepted command-line options is the same as the CLI's, so the [command reference](/docs/reference.html.md) is the authoritative list of what you can put into the `commands` string.