mapshaper 0.6.43 → 0.6.44

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
@@ -61,7 +61,10 @@ function startServer(port) {
61
61
  http.createServer(function(request, response) {
62
62
  var uri = url.parse(request.url).pathname;
63
63
  clearTimeout(timeout);
64
- if (uri == '/close') {
64
+ if (uri.includes('..')) {
65
+ // block attempts to load files outside webroot
66
+ serve404(response);
67
+ } else if (uri == '/close') {
65
68
  // end process when page closes, unless page is immediately refreshed
66
69
  timeout = setTimeout(function() {
67
70
  process.exit(0);
@@ -116,10 +119,14 @@ function serveError(text, code, response) {
116
119
  response.end();
117
120
  }
118
121
 
122
+ function serve404(response) {
123
+ serveError("404 Not Found\n", 404, response);
124
+ }
125
+
119
126
  function serveFile(filename, response) {
120
127
  fs.readFile(filename, function(err, content) {
121
128
  if (err) {
122
- serveError("404 Not Found\n", 404, response);
129
+ serve404(response);
123
130
  } else {
124
131
  serveContent(content, response, getMimeType(filename));
125
132
  }
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.43";
3
+ var VERSION = "0.6.44";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -8,6 +8,7 @@
8
8
  get default () { return utils; },
9
9
  get getUniqueName () { return getUniqueName; },
10
10
  get isFunction () { return isFunction; },
11
+ get isPromise () { return isPromise; },
11
12
  get isObject () { return isObject; },
12
13
  get clamp () { return clamp; },
13
14
  get isArray () { return isArray; },
@@ -147,6 +148,10 @@
147
148
  return typeof obj == 'function';
148
149
  }
149
150
 
151
+ function isPromise(arg) {
152
+ return arg ? isFunction(arg.then) : false;
153
+ }
154
+
150
155
  function isObject(obj) {
151
156
  return obj === Object(obj); // via underscore
152
157
  }
@@ -12488,7 +12493,6 @@
12488
12493
  return +n.toPrecision(d);
12489
12494
  }
12490
12495
 
12491
-
12492
12496
  function roundToDigits(n, d) {
12493
12497
  return +n.toFixed(d); // string conversion makes this slow
12494
12498
  }
@@ -12552,6 +12556,37 @@
12552
12556
  });
12553
12557
  }
12554
12558
 
12559
+ const fround2 = (function() {
12560
+ var arr = new Float32Array(1);
12561
+ return function(x) {
12562
+ arr[0] = x;
12563
+ return arr[0];
12564
+ };
12565
+ })();
12566
+
12567
+ // This function rounds towards 0 (i.e. floor). TODO: round properly
12568
+ // @bits: number of bits to round
12569
+ // performance: about 3x slower than Math.fround()
12570
+ function getBinaryRoundingFunction(bits) {
12571
+ // double: sign (1) exponent (11) fraction (52)
12572
+ // single: sign (1) exponent (8) fraction (23)
12573
+ if ((bits >= 1 && bits <= 32) === false) {
12574
+ error('Invalid bits argument:', bits);
12575
+ }
12576
+ var isLE = require('os').endianness() == 'LE';
12577
+ var fp = new Float64Array(1);
12578
+ var leastBits = new Uint32Array(fp.buffer, isLE ? 0 : 4, 1);
12579
+ var mask = 2 ** 32 - 2 ** bits; // e.g. bits = 4 -> 0b11110000
12580
+ return function(x) {
12581
+ fp[0] = x;
12582
+ leastBits[0] = leastBits[0] & mask;
12583
+ return fp[0];
12584
+ };
12585
+ }
12586
+
12587
+ // "round to even" on the 23rd bit of the mantissa
12588
+ const fround = Math.fround || fround2;
12589
+
12555
12590
  function setCoordinatePrecision(dataset, precision) {
12556
12591
  var round = getRoundingFunction(precision);
12557
12592
  // var dissolvePolygon, nodes;
@@ -12586,6 +12621,9 @@
12586
12621
  getRoundedCoordString: getRoundedCoordString,
12587
12622
  getRoundedCoords: getRoundedCoords,
12588
12623
  roundPoints: roundPoints,
12624
+ fround2: fround2,
12625
+ getBinaryRoundingFunction: getBinaryRoundingFunction,
12626
+ fround: fround,
12589
12627
  setCoordinatePrecision: setCoordinatePrecision
12590
12628
  });
12591
12629
 
@@ -16458,7 +16496,8 @@
16458
16496
  if (id >= 0 && id < n) {
16459
16497
  return index[id] - 1;
16460
16498
  } else {
16461
- error('Invalid index');
16499
+ return -1;
16500
+ // error('Invalid index');
16462
16501
  }
16463
16502
  };
16464
16503
  }
@@ -18412,7 +18451,8 @@
18412
18451
  // null values indicate the lack of a function for parsing/identifying this property
18413
18452
  // (in which case a heuristic is used for distinguishing a string literal from an expression)
18414
18453
  var stylePropertyTypes = {
18415
- css: null,
18454
+ // css: null,
18455
+ css: 'inlinecss',
18416
18456
  class: 'classname',
18417
18457
  dx: 'measure',
18418
18458
  dy: 'measure',
@@ -18599,6 +18639,8 @@
18599
18639
  val = isPattern(strVal) ? strVal : null;
18600
18640
  } else if (type == 'boolean') {
18601
18641
  val = parseBoolean(strVal);
18642
+ } else if (type == 'inlinecss') {
18643
+ val = strVal; // TODO: validate
18602
18644
  }
18603
18645
  // else {
18604
18646
  // // unknown type -- assume literal value
@@ -24696,9 +24738,9 @@ ${svg}
24696
24738
  .option('class', {
24697
24739
  describe: 'name of CSS class or classes (space-separated)'
24698
24740
  })
24699
- // .option('css', {
24700
- // describe: 'inline css style'
24701
- // })
24741
+ .option('css', {
24742
+ describe: 'inline css style'
24743
+ })
24702
24744
  .option('fill', {
24703
24745
  describe: 'fill color; examples: #eee pink rgba(0, 0, 0, 0.2)'
24704
24746
  })
@@ -41274,21 +41316,24 @@ ${svg}
41274
41316
  parseConsoleCommands: parseConsoleCommands
41275
41317
  });
41276
41318
 
41277
- cmd.run = function(job, targets, opts, cb) {
41319
+ cmd.run = async function(job, targets, opts) {
41278
41320
  var commandStr, commands;
41279
41321
  if (!opts.expression) {
41280
41322
  stop("Missing expression parameter");
41281
41323
  }
41282
41324
  commandStr = runGlobalExpression(opts.expression, targets);
41325
+ // Support async functions as expressions
41326
+ if (utils.isPromise(commandStr)) {
41327
+ commandStr = await commandStr;
41328
+ }
41283
41329
  if (commandStr) {
41284
41330
  message(`command: [${commandStr}]`);
41285
41331
  commands = parseCommands(commandStr);
41286
- runParsedCommands(commands, job, cb);
41287
- } else {
41288
- cb(null);
41332
+ await utils.promisify(runParsedCommands)(commands, job);
41289
41333
  }
41290
41334
  };
41291
41335
 
41336
+ // This could return a Promise or a value or nothing
41292
41337
  function runGlobalExpression(expression, targets) {
41293
41338
  var ctx = getBaseContext();
41294
41339
  var output, targetData;
@@ -42415,6 +42460,7 @@ ${svg}
42415
42460
  shapes = lyr0.shapes,
42416
42461
  index = {},
42417
42462
  splitLayers = [],
42463
+ n = getFeatureCount(lyr0),
42418
42464
  namer;
42419
42465
 
42420
42466
  if (opts.ids) {
@@ -42423,11 +42469,18 @@ ${svg}
42423
42469
  namer = getSplitNameFunction(lyr0, expression);
42424
42470
  }
42425
42471
 
42472
+ // // halt if split field is missing
42426
42473
  // if (splitField) {
42427
42474
  // internal.requireDataField(lyr0, splitField);
42428
42475
  // }
42429
42476
 
42430
- utils.repeat(getFeatureCount(lyr0), function(i) {
42477
+ // if input layer is empty, return original layer
42478
+ // TODO: consider halting
42479
+ if (n === 0) {
42480
+ return [lyr0];
42481
+ }
42482
+
42483
+ utils.repeat(n, function(i) {
42431
42484
  var name = namer(i),
42432
42485
  lyr;
42433
42486
 
@@ -42450,6 +42503,7 @@ ${svg}
42450
42503
  lyr.data.getRecords().push(properties[i]);
42451
42504
  }
42452
42505
  });
42506
+
42453
42507
  return splitLayers;
42454
42508
  };
42455
42509
 
@@ -42460,26 +42514,34 @@ ${svg}
42460
42514
  };
42461
42515
  }
42462
42516
 
42463
- function getDefaultSplitFunction(lyr) {
42464
- // if not splitting on an expression and layer is unnamed, name split-apart layers
42465
- // like: split-1, split-2, ...
42466
- return function(i) {
42467
- return (lyr && lyr.name || 'split') + '-' + (i + 1);
42468
- };
42469
- }
42470
-
42471
- function getSplitNameFunction(lyr, exp) {
42517
+ function getSplitNameFunction(lyr, arg) {
42472
42518
  var compiled;
42473
- if (!exp) return getDefaultSplitFunction(lyr);
42519
+ if (!arg) {
42520
+ // if not splitting on an expression and layer is unnamed, name split-apart layers
42521
+ // like: split-1, split-2, ...
42522
+ return function(i) {
42523
+ return (lyr && lyr.name || 'split') + '-' + (i + 1);
42524
+ };
42525
+ }
42526
+ if (lyr.data && lyr.data.fieldExists(arg)) {
42527
+ // Argument is a field name
42528
+ return function(i) {
42529
+ var rec = lyr.data.getRecords()[i];
42530
+ return rec ? valueToLayerName(rec[arg]) : '';
42531
+ };
42532
+ }
42533
+ // Assume: argument is an expression
42474
42534
  lyr = {name: lyr.name, data: lyr.data}; // remove shape info
42475
- compiled = compileValueExpression(exp, lyr, null);
42535
+ compiled = compileValueExpression(arg, lyr, null);
42476
42536
  return function(i) {
42477
42537
  var val = compiled(i);
42478
- return String(val);
42479
- // return val || val === 0 ? String(val) : '';
42538
+ return valueToLayerName(val);
42480
42539
  };
42481
42540
  }
42482
42541
 
42542
+ function valueToLayerName(val) {
42543
+ return String(val);
42544
+ }
42483
42545
 
42484
42546
  // internal.getSplitKey = function(i, field, properties) {
42485
42547
  // var rec = field && properties ? properties[i] : null;
@@ -42515,6 +42577,9 @@ ${svg}
42515
42577
 
42516
42578
  cmd.svgStyle = function(lyr, dataset, opts) {
42517
42579
  var filter;
42580
+ if (getFeatureCount(lyr) === 0) {
42581
+ return;
42582
+ }
42518
42583
  if (!lyr.data) {
42519
42584
  initDataTable(lyr);
42520
42585
  }
@@ -43820,7 +43885,7 @@ ${svg}
43820
43885
  });
43821
43886
 
43822
43887
  } else if (name == 'run') {
43823
- await utils.promisify(cmd.run)(job, targets, opts);
43888
+ await cmd.run(job, targets, opts);
43824
43889
 
43825
43890
  } else if (name == 'scalebar') {
43826
43891
  cmd.scalebar(job.catalog, opts);
@@ -43843,7 +43908,7 @@ ${svg}
43843
43908
 
43844
43909
  } else if (name == 'snap') {
43845
43910
  // cmd.snap(targetDataset, opts);
43846
- applyCommandToEachTarget(targets, opts);
43911
+ applyCommandToEachTarget(cmd.snap, targets, opts);
43847
43912
 
43848
43913
  } else if (name == 'sort') {
43849
43914
  applyCommandToEachLayer(cmd.sortFeatures, targetLayers, arcs, opts);
@@ -44097,6 +44162,13 @@ ${svg}
44097
44162
  }
44098
44163
  });
44099
44164
 
44165
+ var lastCmd = commands[commands.length - 1];
44166
+ if (!runningInBrowser() && lastCmd.name == 'o') {
44167
+ // in CLI, set 'final' flag on final -o command, so the export function knows
44168
+ // that it can modify the output dataset in-place instead of making a copy.
44169
+ lastCmd.options.final = true;
44170
+ }
44171
+
44100
44172
  var batches = divideImportCommand(commands);
44101
44173
  utils.reduceAsync(batches, null, nextGroup, done);
44102
44174
 
@@ -44165,11 +44237,6 @@ ${svg}
44165
44237
  // @done: function([error], [job])
44166
44238
  //
44167
44239
  function runParsedCommands(commands, job, done) {
44168
- if (!runningInBrowser() && commands[commands.length-1].name == 'o') {
44169
- // in CLI, set 'final' flag on final -o command, so the export function knows
44170
- // that it can modify the output dataset in-place instead of making a copy.
44171
- commands[commands.length-1].options.final = true;
44172
- }
44173
44240
  if (!job) job = new Job();
44174
44241
  commands = readAndRemoveSettings(job, commands);
44175
44242
  if (!runningInBrowser()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.43",
3
+ "version": "0.6.44",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -5,6 +5,7 @@
5
5
  get default () { return utils; },
6
6
  get getUniqueName () { return getUniqueName; },
7
7
  get isFunction () { return isFunction; },
8
+ get isPromise () { return isPromise; },
8
9
  get isObject () { return isObject; },
9
10
  get clamp () { return clamp; },
10
11
  get isArray () { return isArray; },
@@ -2157,11 +2158,18 @@
2157
2158
  }
2158
2159
 
2159
2160
  function downloadNextFile(memo, item, next) {
2160
- var blob, err;
2161
- fetch(item.url).then(resp => resp.blob()).then(b => {
2162
- blob = b;
2163
- blob.name = item.basename;
2164
- memo.push(blob);
2161
+ var err;
2162
+ fetch(item.url).then(resp => {
2163
+ if (resp.status != 200) {
2164
+ // e.g. 404 because a URL listed in the GUI query string does not exist
2165
+ throw Error();
2166
+ }
2167
+ return resp.blob();
2168
+ }).then(blob => {
2169
+ if (blob) {
2170
+ blob.name = item.basename;
2171
+ memo.push(blob);
2172
+ }
2165
2173
  }).catch(e => {
2166
2174
  err = "Error&nbsp;loading&nbsp;" + item.name + ". Possible causes include: wrong URL, no network connection, server not configured for cross-domain sharing (CORS).";
2167
2175
  }).finally(() => {
@@ -5209,6 +5217,10 @@
5209
5217
  return typeof obj == 'function';
5210
5218
  }
5211
5219
 
5220
+ function isPromise(arg) {
5221
+ return arg ? isFunction(arg.then) : false;
5222
+ }
5223
+
5212
5224
  function isObject(obj) {
5213
5225
  return obj === Object(obj); // via underscore
5214
5226
  }
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.43";
3
+ var VERSION = "0.6.44";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -8,6 +8,7 @@
8
8
  get default () { return utils; },
9
9
  get getUniqueName () { return getUniqueName; },
10
10
  get isFunction () { return isFunction; },
11
+ get isPromise () { return isPromise; },
11
12
  get isObject () { return isObject; },
12
13
  get clamp () { return clamp; },
13
14
  get isArray () { return isArray; },
@@ -147,6 +148,10 @@
147
148
  return typeof obj == 'function';
148
149
  }
149
150
 
151
+ function isPromise(arg) {
152
+ return arg ? isFunction(arg.then) : false;
153
+ }
154
+
150
155
  function isObject(obj) {
151
156
  return obj === Object(obj); // via underscore
152
157
  }
@@ -12488,7 +12493,6 @@
12488
12493
  return +n.toPrecision(d);
12489
12494
  }
12490
12495
 
12491
-
12492
12496
  function roundToDigits(n, d) {
12493
12497
  return +n.toFixed(d); // string conversion makes this slow
12494
12498
  }
@@ -12552,6 +12556,37 @@
12552
12556
  });
12553
12557
  }
12554
12558
 
12559
+ const fround2 = (function() {
12560
+ var arr = new Float32Array(1);
12561
+ return function(x) {
12562
+ arr[0] = x;
12563
+ return arr[0];
12564
+ };
12565
+ })();
12566
+
12567
+ // This function rounds towards 0 (i.e. floor). TODO: round properly
12568
+ // @bits: number of bits to round
12569
+ // performance: about 3x slower than Math.fround()
12570
+ function getBinaryRoundingFunction(bits) {
12571
+ // double: sign (1) exponent (11) fraction (52)
12572
+ // single: sign (1) exponent (8) fraction (23)
12573
+ if ((bits >= 1 && bits <= 32) === false) {
12574
+ error('Invalid bits argument:', bits);
12575
+ }
12576
+ var isLE = require('os').endianness() == 'LE';
12577
+ var fp = new Float64Array(1);
12578
+ var leastBits = new Uint32Array(fp.buffer, isLE ? 0 : 4, 1);
12579
+ var mask = 2 ** 32 - 2 ** bits; // e.g. bits = 4 -> 0b11110000
12580
+ return function(x) {
12581
+ fp[0] = x;
12582
+ leastBits[0] = leastBits[0] & mask;
12583
+ return fp[0];
12584
+ };
12585
+ }
12586
+
12587
+ // "round to even" on the 23rd bit of the mantissa
12588
+ const fround = Math.fround || fround2;
12589
+
12555
12590
  function setCoordinatePrecision(dataset, precision) {
12556
12591
  var round = getRoundingFunction(precision);
12557
12592
  // var dissolvePolygon, nodes;
@@ -12586,6 +12621,9 @@
12586
12621
  getRoundedCoordString: getRoundedCoordString,
12587
12622
  getRoundedCoords: getRoundedCoords,
12588
12623
  roundPoints: roundPoints,
12624
+ fround2: fround2,
12625
+ getBinaryRoundingFunction: getBinaryRoundingFunction,
12626
+ fround: fround,
12589
12627
  setCoordinatePrecision: setCoordinatePrecision
12590
12628
  });
12591
12629
 
@@ -16458,7 +16496,8 @@
16458
16496
  if (id >= 0 && id < n) {
16459
16497
  return index[id] - 1;
16460
16498
  } else {
16461
- error('Invalid index');
16499
+ return -1;
16500
+ // error('Invalid index');
16462
16501
  }
16463
16502
  };
16464
16503
  }
@@ -18412,7 +18451,8 @@
18412
18451
  // null values indicate the lack of a function for parsing/identifying this property
18413
18452
  // (in which case a heuristic is used for distinguishing a string literal from an expression)
18414
18453
  var stylePropertyTypes = {
18415
- css: null,
18454
+ // css: null,
18455
+ css: 'inlinecss',
18416
18456
  class: 'classname',
18417
18457
  dx: 'measure',
18418
18458
  dy: 'measure',
@@ -18599,6 +18639,8 @@
18599
18639
  val = isPattern(strVal) ? strVal : null;
18600
18640
  } else if (type == 'boolean') {
18601
18641
  val = parseBoolean(strVal);
18642
+ } else if (type == 'inlinecss') {
18643
+ val = strVal; // TODO: validate
18602
18644
  }
18603
18645
  // else {
18604
18646
  // // unknown type -- assume literal value
@@ -24696,9 +24738,9 @@ ${svg}
24696
24738
  .option('class', {
24697
24739
  describe: 'name of CSS class or classes (space-separated)'
24698
24740
  })
24699
- // .option('css', {
24700
- // describe: 'inline css style'
24701
- // })
24741
+ .option('css', {
24742
+ describe: 'inline css style'
24743
+ })
24702
24744
  .option('fill', {
24703
24745
  describe: 'fill color; examples: #eee pink rgba(0, 0, 0, 0.2)'
24704
24746
  })
@@ -41274,21 +41316,24 @@ ${svg}
41274
41316
  parseConsoleCommands: parseConsoleCommands
41275
41317
  });
41276
41318
 
41277
- cmd.run = function(job, targets, opts, cb) {
41319
+ cmd.run = async function(job, targets, opts) {
41278
41320
  var commandStr, commands;
41279
41321
  if (!opts.expression) {
41280
41322
  stop("Missing expression parameter");
41281
41323
  }
41282
41324
  commandStr = runGlobalExpression(opts.expression, targets);
41325
+ // Support async functions as expressions
41326
+ if (utils.isPromise(commandStr)) {
41327
+ commandStr = await commandStr;
41328
+ }
41283
41329
  if (commandStr) {
41284
41330
  message(`command: [${commandStr}]`);
41285
41331
  commands = parseCommands(commandStr);
41286
- runParsedCommands(commands, job, cb);
41287
- } else {
41288
- cb(null);
41332
+ await utils.promisify(runParsedCommands)(commands, job);
41289
41333
  }
41290
41334
  };
41291
41335
 
41336
+ // This could return a Promise or a value or nothing
41292
41337
  function runGlobalExpression(expression, targets) {
41293
41338
  var ctx = getBaseContext();
41294
41339
  var output, targetData;
@@ -42415,6 +42460,7 @@ ${svg}
42415
42460
  shapes = lyr0.shapes,
42416
42461
  index = {},
42417
42462
  splitLayers = [],
42463
+ n = getFeatureCount(lyr0),
42418
42464
  namer;
42419
42465
 
42420
42466
  if (opts.ids) {
@@ -42423,11 +42469,18 @@ ${svg}
42423
42469
  namer = getSplitNameFunction(lyr0, expression);
42424
42470
  }
42425
42471
 
42472
+ // // halt if split field is missing
42426
42473
  // if (splitField) {
42427
42474
  // internal.requireDataField(lyr0, splitField);
42428
42475
  // }
42429
42476
 
42430
- utils.repeat(getFeatureCount(lyr0), function(i) {
42477
+ // if input layer is empty, return original layer
42478
+ // TODO: consider halting
42479
+ if (n === 0) {
42480
+ return [lyr0];
42481
+ }
42482
+
42483
+ utils.repeat(n, function(i) {
42431
42484
  var name = namer(i),
42432
42485
  lyr;
42433
42486
 
@@ -42450,6 +42503,7 @@ ${svg}
42450
42503
  lyr.data.getRecords().push(properties[i]);
42451
42504
  }
42452
42505
  });
42506
+
42453
42507
  return splitLayers;
42454
42508
  };
42455
42509
 
@@ -42460,26 +42514,34 @@ ${svg}
42460
42514
  };
42461
42515
  }
42462
42516
 
42463
- function getDefaultSplitFunction(lyr) {
42464
- // if not splitting on an expression and layer is unnamed, name split-apart layers
42465
- // like: split-1, split-2, ...
42466
- return function(i) {
42467
- return (lyr && lyr.name || 'split') + '-' + (i + 1);
42468
- };
42469
- }
42470
-
42471
- function getSplitNameFunction(lyr, exp) {
42517
+ function getSplitNameFunction(lyr, arg) {
42472
42518
  var compiled;
42473
- if (!exp) return getDefaultSplitFunction(lyr);
42519
+ if (!arg) {
42520
+ // if not splitting on an expression and layer is unnamed, name split-apart layers
42521
+ // like: split-1, split-2, ...
42522
+ return function(i) {
42523
+ return (lyr && lyr.name || 'split') + '-' + (i + 1);
42524
+ };
42525
+ }
42526
+ if (lyr.data && lyr.data.fieldExists(arg)) {
42527
+ // Argument is a field name
42528
+ return function(i) {
42529
+ var rec = lyr.data.getRecords()[i];
42530
+ return rec ? valueToLayerName(rec[arg]) : '';
42531
+ };
42532
+ }
42533
+ // Assume: argument is an expression
42474
42534
  lyr = {name: lyr.name, data: lyr.data}; // remove shape info
42475
- compiled = compileValueExpression(exp, lyr, null);
42535
+ compiled = compileValueExpression(arg, lyr, null);
42476
42536
  return function(i) {
42477
42537
  var val = compiled(i);
42478
- return String(val);
42479
- // return val || val === 0 ? String(val) : '';
42538
+ return valueToLayerName(val);
42480
42539
  };
42481
42540
  }
42482
42541
 
42542
+ function valueToLayerName(val) {
42543
+ return String(val);
42544
+ }
42483
42545
 
42484
42546
  // internal.getSplitKey = function(i, field, properties) {
42485
42547
  // var rec = field && properties ? properties[i] : null;
@@ -42515,6 +42577,9 @@ ${svg}
42515
42577
 
42516
42578
  cmd.svgStyle = function(lyr, dataset, opts) {
42517
42579
  var filter;
42580
+ if (getFeatureCount(lyr) === 0) {
42581
+ return;
42582
+ }
42518
42583
  if (!lyr.data) {
42519
42584
  initDataTable(lyr);
42520
42585
  }
@@ -43820,7 +43885,7 @@ ${svg}
43820
43885
  });
43821
43886
 
43822
43887
  } else if (name == 'run') {
43823
- await utils.promisify(cmd.run)(job, targets, opts);
43888
+ await cmd.run(job, targets, opts);
43824
43889
 
43825
43890
  } else if (name == 'scalebar') {
43826
43891
  cmd.scalebar(job.catalog, opts);
@@ -43843,7 +43908,7 @@ ${svg}
43843
43908
 
43844
43909
  } else if (name == 'snap') {
43845
43910
  // cmd.snap(targetDataset, opts);
43846
- applyCommandToEachTarget(targets, opts);
43911
+ applyCommandToEachTarget(cmd.snap, targets, opts);
43847
43912
 
43848
43913
  } else if (name == 'sort') {
43849
43914
  applyCommandToEachLayer(cmd.sortFeatures, targetLayers, arcs, opts);
@@ -44097,6 +44162,13 @@ ${svg}
44097
44162
  }
44098
44163
  });
44099
44164
 
44165
+ var lastCmd = commands[commands.length - 1];
44166
+ if (!runningInBrowser() && lastCmd.name == 'o') {
44167
+ // in CLI, set 'final' flag on final -o command, so the export function knows
44168
+ // that it can modify the output dataset in-place instead of making a copy.
44169
+ lastCmd.options.final = true;
44170
+ }
44171
+
44100
44172
  var batches = divideImportCommand(commands);
44101
44173
  utils.reduceAsync(batches, null, nextGroup, done);
44102
44174
 
@@ -44165,11 +44237,6 @@ ${svg}
44165
44237
  // @done: function([error], [job])
44166
44238
  //
44167
44239
  function runParsedCommands(commands, job, done) {
44168
- if (!runningInBrowser() && commands[commands.length-1].name == 'o') {
44169
- // in CLI, set 'final' flag on final -o command, so the export function knows
44170
- // that it can modify the output dataset in-place instead of making a copy.
44171
- commands[commands.length-1].options.final = true;
44172
- }
44173
44240
  if (!job) job = new Job();
44174
44241
  commands = readAndRemoveSettings(job, commands);
44175
44242
  if (!runningInBrowser()) {