mapshaper 0.5.88 → 0.5.92

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/bin/mapshaper-gui CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  var defaultPort = 5555,
4
- program = require('commander')
4
+ commander = require('commander'),
5
+ program = new commander.Command()
5
6
  .name('mapshaper-gui')
6
7
  .usage('[options] [file ...]')
7
8
  .option('-p, --port <port>', 'http port of server on localhost', defaultPort)
@@ -9,10 +10,14 @@ var defaultPort = 5555,
9
10
  .option('-s, --direct-save', 'save files outside the browser\'s download folder')
10
11
  .option('-f, --force-save', 'allow overwriting input files with output files')
11
12
  .option('-a, --display-all', 'turn on visibility of all layers')
13
+ .option('-n, --name <name(s)>', 'rename input layer or layers')
14
+ .option('-c, --commands <string>', 'console commands to run initially')
12
15
  .option('-t, --target <name>', 'name of layer to select initially')
16
+ .addOption(new commander.Option('-b, --blurb <text>',
17
+ 'replace the default blurb on the import screen').hideHelp())
13
18
  .helpOption('-h, --help', 'show this help message')
14
19
  .version(require('../package.json').version)
15
- .parse(),
20
+ .parse(process.argv),
16
21
  opts = program.opts(),
17
22
  http = require("http"),
18
23
  path = require("path"),
@@ -25,11 +30,11 @@ var defaultPort = 5555,
25
30
  dataFiles = expandShapefiles(program.args),
26
31
  probeCount = 0,
27
32
  sessionId = null;
28
-
29
33
  validateFiles(dataFiles);
30
34
 
31
35
  process.on('uncaughtException', function(err) {
32
- if (err.errno === 'EADDRINUSE') {
36
+ // added 'code' for Node.js v16
37
+ if (err.errno === 'EADDRINUSE' || err.code === 'EADDRINUSE') {
33
38
  // probe for an open port, unless user has specified a non-default port
34
39
  if (port == defaultPort && probeCount < 10) {
35
40
  probeCount++;
@@ -202,11 +207,16 @@ function validateOutputFile(file) {
202
207
  }
203
208
 
204
209
  function getManifestJS(files, opts) {
205
- var o = {files: files};
206
- if (opts.target) o.target = opts.target;
207
- if (opts.directSave) o.allow_saving = true;
208
- if (opts.displayAll) o.display_all = true;
209
- if (opts.quickView) o.quick_view = true;
210
+ var o = {
211
+ files: files,
212
+ target: opts.target,
213
+ allow_saving: opts.directSave,
214
+ display_all: opts.displayAll,
215
+ quick_view: opts.quickView,
216
+ name: opts.name,
217
+ commands: opts.commands,
218
+ blurb: opts.blurb
219
+ };
210
220
  return "mapshaper.manifest = " + JSON.stringify(o) + ";\n";
211
221
  }
212
222
 
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.87";
3
+ var VERSION = "0.5.91";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -1240,7 +1240,8 @@
1240
1240
  // print a message to stdout
1241
1241
  function print() {
1242
1242
  STDOUT = true; // tell logArgs() to print to stdout, not stderr
1243
- message.apply(null, arguments);
1243
+ // calling message() adds the "[command name]" prefix
1244
+ _message(utils.toArray(arguments));
1244
1245
  STDOUT = false;
1245
1246
  }
1246
1247
 
@@ -2157,6 +2158,7 @@
2157
2158
  function getPointToPathInfo(px, py, ids, arcs) {
2158
2159
  var iter = arcs.getShapeIter(ids);
2159
2160
  var pPathSq = Infinity;
2161
+ var arcId;
2160
2162
  var ax, ay, bx, by, axmin, aymin, bxmin, bymin, pabSq;
2161
2163
  if (iter.hasNext()) {
2162
2164
  ax = axmin = bxmin = iter.x;
@@ -2168,6 +2170,7 @@
2168
2170
  pabSq = pointSegDistSq2(px, py, ax, ay, bx, by);
2169
2171
  if (pabSq < pPathSq) {
2170
2172
  pPathSq = pabSq;
2173
+ arcId = iter._ids[iter._i]; // kludge
2171
2174
  axmin = ax;
2172
2175
  aymin = ay;
2173
2176
  bxmin = bx;
@@ -2179,7 +2182,8 @@
2179
2182
  if (pPathSq == Infinity) return {distance: Infinity};
2180
2183
  return {
2181
2184
  segment: [[axmin, aymin], [bxmin, bymin]],
2182
- distance: Math.sqrt(pPathSq)
2185
+ distance: Math.sqrt(pPathSq),
2186
+ arcId: arcId
2183
2187
  };
2184
2188
  }
2185
2189
 
@@ -2187,11 +2191,20 @@
2187
2191
  // Return unsigned distance of a point to the nearest point on a polygon or polyline path
2188
2192
  //
2189
2193
  function getPointToShapeDistance(x, y, shp, arcs) {
2190
- var minDist = (shp || []).reduce(function(minDist, ids) {
2191
- var pathDist = getPointToPathDistance(x, y, ids, arcs);
2192
- return Math.min(minDist, pathDist);
2193
- }, Infinity);
2194
- return minDist;
2194
+ var info = getPointToShapeInfo(x, y, shp, arcs);
2195
+ return info ? info.distance : Infinity;
2196
+ }
2197
+
2198
+ function getPointToShapeInfo(x, y, shp, arcs) {
2199
+ return (shp || []).reduce(function(memo, ids) {
2200
+ var pathInfo = getPointToPathInfo(x, y, ids, arcs);
2201
+ if (!memo || pathInfo.distance < memo.distance) return pathInfo;
2202
+ return memo;
2203
+ }, null) || {
2204
+ distance: Infinity,
2205
+ arcId: -1,
2206
+ segment: null
2207
+ };
2195
2208
  }
2196
2209
 
2197
2210
  // @ids array of arc ids
@@ -2276,6 +2289,7 @@
2276
2289
  getPointToPathDistance: getPointToPathDistance,
2277
2290
  getPointToPathInfo: getPointToPathInfo,
2278
2291
  getPointToShapeDistance: getPointToShapeDistance,
2292
+ getPointToShapeInfo: getPointToShapeInfo,
2279
2293
  getAvgPathXY: getAvgPathXY,
2280
2294
  getMaxPath: getMaxPath,
2281
2295
  countVerticesInPath: countVerticesInPath,
@@ -5376,6 +5390,10 @@
5376
5390
  };
5377
5391
  };
5378
5392
 
5393
+ this.getVertex2 = function(i) {
5394
+ return [_xx[i], _yy[i]];
5395
+ };
5396
+
5379
5397
  // @nth: index of vertex. ~(idx) starts from the opposite endpoint
5380
5398
  this.indexOfVertex = function(arcId, nth) {
5381
5399
  var absId = arcId < 0 ? ~arcId : arcId,
@@ -9350,15 +9368,23 @@
9350
9368
  var getters = {
9351
9369
  name: lyr.name,
9352
9370
  data: records,
9353
- type: lyr.geometry_type
9371
+ type: lyr.geometry_type,
9372
+ size: getFeatureCount(lyr),
9373
+ empty: getFeatureCount(lyr) === 0
9354
9374
  };
9355
9375
  addGetters(obj, getters);
9356
9376
  addBBoxGetter(obj, lyr, arcs);
9357
- obj.empty = function() {
9358
- return getFeatureCount(lyr) === 0;
9377
+ obj.field_exists = function(name) {
9378
+ return lyr.data && lyr.data.fieldExists(name) ? true : false;
9359
9379
  };
9360
- obj.size = function() {
9361
- return getFeatureCount(lyr);
9380
+ obj.field_type = function(name) {
9381
+ return lyr.data && getColumnType(name, lyr.data.getRecords()) || null;
9382
+ };
9383
+ obj.field_includes = function(name, val) {
9384
+ if (!lyr.data) return false;
9385
+ return lyr.data.getRecords().some(function(rec) {
9386
+ return rec && (rec[name] === val);
9387
+ });
9362
9388
  };
9363
9389
  return obj;
9364
9390
  }
@@ -20116,33 +20142,22 @@ ${svg}
20116
20142
  .option('target', targetOpt);
20117
20143
 
20118
20144
  parser.command('symbols')
20119
- // .describe('symbolize points as polygons, circles, stars or arrows')
20145
+ .describe('symbolize points as arrows, circles, stars, polygons, etc.')
20120
20146
  .option('type', {
20121
- describe: 'symbol type (e.g. star, polygon, circle, arrow)'
20122
- })
20123
- .option('scale', {
20124
- describe: 'scale symbols by a factor',
20125
- type: 'number'
20147
+ describe: 'symbol type (e.g. arrow, circle, square, star, polygon, ring)'
20126
20148
  })
20127
- .option('pixel-scale', {
20128
- describe: 'symbol scale in meters-per-pixel (see polygons option)',
20129
- type: 'number',
20149
+ .option('stroke', {})
20150
+ .option('stroke-width', {})
20151
+ .option('fill', {
20152
+ describe: 'symbol fill color'
20130
20153
  })
20131
20154
  .option('polygons', {
20132
20155
  describe: 'generate symbols as polygons instead of SVG objects',
20133
20156
  type: 'flag'
20134
20157
  })
20135
- .option('radius', {
20136
- describe: 'distance from center to farthest point on the symbol',
20137
- type: 'distance'
20138
- })
20139
- .option('sides', {
20140
- describe: 'number of sides of a polygon symbol',
20141
- type: 'number'
20142
- })
20143
- .option('orientation', {
20144
- // TODO: removed (replaced by flipped and rotated)
20145
- // describe: 'use orientation=b for a rotated or flipped orientation'
20158
+ .option('pixel-scale', {
20159
+ describe: 'set symbol scale in meters-per-pixel (for polygons option)',
20160
+ type: 'number',
20146
20161
  })
20147
20162
  // .option('flipped', {
20148
20163
  // type: 'flag',
@@ -20150,11 +20165,23 @@ ${svg}
20150
20165
  // })
20151
20166
  .option('rotated', {
20152
20167
  type: 'flag',
20153
- describe: 'symbol is rotated to a different orientation'
20168
+ describe: 'symbol is rotated to an alternate orientation'
20154
20169
  })
20155
20170
  .option('rotation', {
20156
20171
  describe: 'rotation of symbol in degrees'
20157
20172
  })
20173
+ .option('scale', {
20174
+ describe: 'scale symbols by a multiplier',
20175
+ type: 'number'
20176
+ })
20177
+ .option('radius', {
20178
+ describe: 'distance from center to farthest point on the symbol',
20179
+ type: 'distance'
20180
+ })
20181
+ .option('sides', {
20182
+ describe: '(polygon) number of sides of a (regular) polygon symbol',
20183
+ type: 'number'
20184
+ })
20158
20185
  .option('points', {
20159
20186
  describe: '(star) number of points'
20160
20187
  })
@@ -20172,7 +20199,7 @@ ${svg}
20172
20199
  })
20173
20200
  .option('direction', {
20174
20201
  old_alias: 'arrow-direction',
20175
- describe: '(arrow) angle off vertical (-90 = left-pointing)'
20202
+ describe: '(arrow) angle off of vertical (-90 = left-pointing)'
20176
20203
  })
20177
20204
  .option('head-angle', {
20178
20205
  old_alias: 'arrow-head-angle',
@@ -20207,17 +20234,12 @@ ${svg}
20207
20234
  })
20208
20235
  .option('min-stem-ratio', {
20209
20236
  old_alias: 'arrow-min-stem',
20210
- describe: '(arrow) min ratio of stem to total length',
20237
+ describe: '(arrow) minimum ratio of stem to total length',
20211
20238
  type: 'number'
20212
20239
  })
20213
20240
  .option('anchor', {
20214
20241
  describe: '(arrow) takes one of: start, middle, end (default is start)'
20215
20242
  })
20216
- .option('stroke', {})
20217
- .option('stroke-width', {})
20218
- .option('fill', {
20219
- describe: 'symbol fill color'
20220
- })
20221
20243
  .option('effect', {})
20222
20244
  // .option('where', whereOpt)
20223
20245
  .option('name', nameOpt)
@@ -20606,6 +20628,10 @@ ${svg}
20606
20628
  .option('target', targetOpt)
20607
20629
  .validate(validateExpressionOpt);
20608
20630
 
20631
+ parser.command('print')
20632
+ .describe('print a message to stdout')
20633
+ .flag('multi_arg');
20634
+
20609
20635
  parser.command('projections')
20610
20636
  .describe('print list of supported projections');
20611
20637
 
@@ -27158,7 +27184,7 @@ ${svg}
27158
27184
  }
27159
27185
 
27160
27186
  function samePoint(a, b) {
27161
- return a[0] === b[0] && a[1] === b[1];
27187
+ return a && b && a[0] === b[0] && a[1] === b[1];
27162
27188
  }
27163
27189
 
27164
27190
  function isClosedPath(arr) {
@@ -27772,11 +27798,15 @@ ${svg}
27772
27798
  }
27773
27799
 
27774
27800
  function getCategoricalColorScheme(name, n) {
27801
+ var colors;
27775
27802
  initSchemes();
27776
- if (index.categorical.includes(name) === false) {
27777
- stop(name, 'is not a categorical color scheme');
27803
+ if (!isColorSchemeName(name)) {
27804
+ stop('Unknown color scheme name:', name);
27805
+ } else if (isCategoricalColorScheme(name)) {
27806
+ colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
27807
+ } else {
27808
+ colors = getColorRamp(name, n);
27778
27809
  }
27779
- var colors = ramps[name] || require('d3-scale-chromatic')['scheme' + name];
27780
27810
  if (n > colors.length) {
27781
27811
  stop(name, 'does not contain', n, 'colors');
27782
27812
  }
@@ -27789,6 +27819,11 @@ ${svg}
27789
27819
  index.diverging.includes(name) || index.rainbow.includes(name);
27790
27820
  }
27791
27821
 
27822
+ function isCategoricalColorScheme(name) {
27823
+ initSchemes();
27824
+ return index.categorical.includes(name);
27825
+ }
27826
+
27792
27827
  function getColorRamp(name, n, stops) {
27793
27828
  initSchemes();
27794
27829
  var lib = require('d3-scale-chromatic');
@@ -28278,7 +28313,7 @@ ${svg}
28278
28313
  };
28279
28314
  }
28280
28315
 
28281
- function getSequentialClassifier$1(classValues, nullValue, dataValues, opts) {
28316
+ function getSequentialClassifier$1(classValues, nullValue, dataValues, method, opts) {
28282
28317
  var numValues = classValues.length;
28283
28318
  var numBuckets = opts.continuous ? numValues - 1 : numValues;
28284
28319
 
@@ -28286,7 +28321,6 @@ ${svg}
28286
28321
  // discreetly classed values
28287
28322
  var numBreaks = numBuckets - 1;
28288
28323
  var round = opts.precision ? getRoundingFunction(opts.precision) : null;
28289
- var method = opts.method || 'quantile';
28290
28324
  var breaks, classifier, dataToClass, classToValue;
28291
28325
 
28292
28326
  if (round) {
@@ -28891,34 +28925,35 @@ ${svg}
28891
28925
  var opts = optsArg || {};
28892
28926
  var records = lyr.data && lyr.data.getRecords();
28893
28927
  var nullValue = opts.null_value || null;
28894
- var looksLikeColors = !!opts.colors || !!opts.color_scheme;
28928
+ var valuesAreColors = !!opts.colors || !!opts.color_scheme;
28895
28929
  var colorScheme;
28896
- var classValues, classifyByValue, classifyById;
28897
- var numBuckets, numValues;
28930
+ var values, classifyByValue, classifyById;
28931
+ var numClasses, numValues;
28898
28932
  var dataField, outputField;
28933
+ var method;
28899
28934
 
28900
28935
  // validate explicitly set classes
28901
28936
  if (opts.classes) {
28902
28937
  if (!utils.isInteger(opts.classes) || opts.classes > 1 === false) {
28903
28938
  stop('Invalid number of classes:', opts.classes, '(expected a value greater than 1)');
28904
28939
  }
28905
- numBuckets = opts.classes;
28940
+ numClasses = opts.classes;
28906
28941
  }
28907
28942
 
28908
28943
  // TODO: better validation of breaks values
28909
28944
  if (opts.breaks) {
28910
- numBuckets = opts.breaks.length + 1;
28945
+ numClasses = opts.breaks.length + 1;
28911
28946
  }
28912
28947
 
28913
28948
  if (opts.index_field) {
28914
28949
  dataField = opts.index_field;
28915
- if (numBuckets > 0 === false) {
28950
+ if (numClasses > 0 === false) {
28916
28951
  stop('The index-field= option requires the classes= option to be set');
28917
28952
  }
28918
28953
  // You can't infer the number of classes by looking at index values;
28919
28954
  // this can cause unwanted interpolation if one or more values are
28920
28955
  // not present in the index field
28921
- // numBuckets = validateClassIndexField(records, opts.index_field);
28956
+ // numClasses = validateClassIndexField(records, opts.index_field);
28922
28957
 
28923
28958
  } else if (opts.field) {
28924
28959
  dataField = opts.field;
@@ -28929,7 +28964,19 @@ ${svg}
28929
28964
  opts.categories = getUniqFieldValues(records, dataField);
28930
28965
  }
28931
28966
 
28932
- if (opts.method == 'non-adjacent') {
28967
+ // get classification method
28968
+ //
28969
+ if (opts.method) {
28970
+ method = opts.method;
28971
+ } else if (opts.categories) {
28972
+ method = 'categorical';
28973
+ } else if (opts.index_field) {
28974
+ method = 'indexed';
28975
+ } else {
28976
+ method = 'quantile'; // TODO: validate data field
28977
+ }
28978
+
28979
+ if (method == 'non-adjacent') {
28933
28980
  if (lyr.geometry_type != 'polygon') {
28934
28981
  stop('The non-adjacent option requires a polygon layer');
28935
28982
  }
@@ -28942,8 +28989,8 @@ ${svg}
28942
28989
  requireDataField(lyr.data, dataField);
28943
28990
  }
28944
28991
 
28945
- if (numBuckets) {
28946
- numValues = opts.continuous ? numBuckets + 1 : numBuckets;
28992
+ if (numClasses) {
28993
+ numValues = opts.continuous ? numClasses + 1 : numClasses;
28947
28994
  }
28948
28995
 
28949
28996
  // support both deprecated color-scheme= option and colors=<color-scheme> syntax
@@ -28958,39 +29005,44 @@ ${svg}
28958
29005
  opts.colors.forEach(parseColor); // validate colors -- error if unparsable
28959
29006
  }
28960
29007
 
29008
+ /// get values (usually colors)
29009
+ ///
28961
29010
  if (colorScheme) {
28962
- // using a named color scheme: generate a ramp
29011
+ if (method == 'non-adjacent') {
29012
+ numClasses = numValues = numClasses || 5;
29013
+ values = getCategoricalColorScheme(colorScheme, numValues);
29014
+
29015
+ } else if (method == 'categorical') {
29016
+ values = getCategoricalColorScheme(colorScheme, opts.categories.length);
29017
+ numClasses = numValues = values.length;
28963
29018
 
28964
- if (opts.categories) {
28965
- classValues = getCategoricalColorScheme(colorScheme, opts.categories.length);
28966
- numBuckets = numValues = classValues.length;
28967
29019
  } else {
28968
- if (!numBuckets) {
29020
+ if (!numClasses) {
28969
29021
  // stop('color-scheme= option requires classes= or breaks=');
28970
- numBuckets = 4; // use a default number of classes
28971
- numValues = opts.continuous ? numBuckets + 1 : numBuckets;
29022
+ numClasses = 4; // use a default number of classes
29023
+ numValues = opts.continuous ? numClasses + 1 : numClasses;
28972
29024
  }
28973
- classValues = getColorRamp(colorScheme, numValues, opts.stops);
29025
+ values = getColorRamp(colorScheme, numValues, opts.stops);
28974
29026
  }
28975
29027
 
28976
29028
  } else if (opts.colors || opts.values) {
28977
- classValues = opts.values ? parseValues(opts.values) : opts.colors;
29029
+ values = opts.values ? parseValues(opts.values) : opts.colors;
28978
29030
  if (!numValues) {
28979
- numValues = classValues.length;
29031
+ numValues = values.length;
28980
29032
  }
28981
- if ((classValues.length != numValues || opts.stops) && numValues > 1) {
29033
+ if ((values.length != numValues || opts.stops) && numValues > 1) {
28982
29034
  // TODO: handle numValues == 1
28983
29035
  // TODO: check for non-interpolatable value types (e.g. boolean, text)
28984
- classValues = interpolateValuesToClasses(classValues, numValues, opts.stops);
29036
+ values = interpolateValuesToClasses(values, numValues, opts.stops);
28985
29037
  }
28986
29038
 
28987
29039
  } else if (numValues > 1) {
28988
29040
  // no values were given: assign indexes for each class
28989
- classValues = getIndexValues(numValues);
29041
+ values = getIndexValues(numValues);
28990
29042
  nullValue = -1;
28991
29043
  }
28992
29044
 
28993
- if (looksLikeColors) {
29045
+ if (valuesAreColors) {
28994
29046
  nullValue = nullValue || '#eee';
28995
29047
  }
28996
29048
 
@@ -28999,24 +29051,24 @@ ${svg}
28999
29051
  }
29000
29052
 
29001
29053
  if (opts.invert) {
29002
- classValues = classValues.concat().reverse();
29054
+ values = values.concat().reverse();
29003
29055
  }
29004
29056
 
29005
- if (looksLikeColors) {
29006
- message('Colors:', formatValuesForLogging(classValues));
29057
+ if (valuesAreColors) {
29058
+ message('Colors:', formatValuesForLogging(values));
29007
29059
  }
29008
29060
 
29009
29061
  // get a function to convert input data to class indexes
29010
29062
  //
29011
- if (opts.method == 'non-adjacent') {
29012
- classifyById = getNonAdjacentClassifier(lyr, dataset, classValues);
29063
+ if (method == 'non-adjacent') {
29064
+ classifyById = getNonAdjacentClassifier(lyr, dataset, values);
29013
29065
  } else if (opts.index_field) {
29014
29066
  // data is pre-classified... just read the index from a field
29015
- classifyByValue = getIndexedClassifier(classValues, nullValue, opts);
29016
- } else if (opts.categories) {
29017
- classifyByValue = getCategoricalClassifier(classValues, nullValue, opts);
29067
+ classifyByValue = getIndexedClassifier(values, nullValue, opts);
29068
+ } else if (method == 'categorical') {
29069
+ classifyByValue = getCategoricalClassifier(values, nullValue, opts);
29018
29070
  } else {
29019
- classifyByValue = getSequentialClassifier$1(classValues, nullValue, getFieldValues(records, dataField), opts);
29071
+ classifyByValue = getSequentialClassifier$1(values, nullValue, getFieldValues(records, dataField), method, opts);
29020
29072
  }
29021
29073
 
29022
29074
  if (classifyByValue) {
@@ -29029,7 +29081,7 @@ ${svg}
29029
29081
 
29030
29082
  // get the name of the output field
29031
29083
  //
29032
- if (looksLikeColors) {
29084
+ if (valuesAreColors) {
29033
29085
  outputField = lyr.geometry_type == 'polyline' ? 'stroke' : 'fill';
29034
29086
  } else {
29035
29087
  outputField = 'class';
@@ -36641,6 +36693,10 @@ ${svg}
36641
36693
  };
36642
36694
  }
36643
36695
 
36696
+ cmd.print = function(msgArg) {
36697
+ print(msgArg || '');
36698
+ };
36699
+
36644
36700
  cmd.renameLayers = function(layers, names, catalog) {
36645
36701
  if (names && names.join('').indexOf('=') > -1) {
36646
36702
  renameByAssignment(names, catalog);
@@ -39148,7 +39204,7 @@ ${svg}
39148
39204
  }
39149
39205
  if (!(name == 'graticule' || name == 'i' || name == 'help' ||
39150
39206
  name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
39151
- name == 'include')) {
39207
+ name == 'include' || name == 'print')) {
39152
39208
  throw new UserError("No data is available");
39153
39209
  }
39154
39210
  }
@@ -39333,6 +39389,9 @@ ${svg}
39333
39389
  } else if (name == 'polygons') {
39334
39390
  outputLayers = cmd.polygons(targetLayers, targetDataset, opts);
39335
39391
 
39392
+ } else if (name == 'print') {
39393
+ cmd.print(command._.join(' '));
39394
+
39336
39395
  } else if (name == 'proj') {
39337
39396
  initProjLibrary(opts, function() {
39338
39397
  var err = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.88",
3
+ "version": "0.5.92",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -40,7 +40,7 @@
40
40
  "!.DS_Store"
41
41
  ],
42
42
  "dependencies": {
43
- "commander": "^5.1.0",
43
+ "commander": "7.0.0",
44
44
  "cookies": "^0.8.0",
45
45
  "d3-color": "2.0.0",
46
46
  "d3-scale-chromatic": "2.0.0",
package/www/index.html CHANGED
@@ -201,7 +201,7 @@ a smoother appearance.</div></div></div></div>
201
201
 
202
202
  <div id="splash-screen" class="main-area">
203
203
  <div>
204
- <h3>Mapshaper is an editor for map data</h3>
204
+ <h3 id="splash-screen-blurb">Mapshaper is an editor for map data</h3>
205
205
  </div>
206
206
  <div id="drop-areas" class="drop-area-wrapper main-area">
207
207