mapshaper 0.5.65 → 0.5.69

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/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.64";
3
+ var VERSION = "0.5.68";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -1167,6 +1167,10 @@
1167
1167
  throw new UserError(formatLogArgs(arguments));
1168
1168
  };
1169
1169
 
1170
+ var _interrupt = function() {
1171
+ throw new NonFatalError(formatLogArgs(arguments));
1172
+ };
1173
+
1170
1174
  var _message = function() {
1171
1175
  logArgs(arguments);
1172
1176
  };
@@ -1185,10 +1189,14 @@
1185
1189
  }
1186
1190
 
1187
1191
  // Handle an error caused by invalid input or misuse of API
1188
- function stop () {
1192
+ function stop() {
1189
1193
  _stop.apply(null, utils.toArray(arguments));
1190
1194
  }
1191
1195
 
1196
+ function interrupt() {
1197
+ _interrupt.apply(null, utils.toArray(arguments));
1198
+ }
1199
+
1192
1200
  // Print a status message
1193
1201
  function message() {
1194
1202
  _message.apply(null, messageArgs(arguments));
@@ -1228,7 +1236,9 @@
1228
1236
  if (utils.isString(err)) {
1229
1237
  err = new UserError(err);
1230
1238
  }
1231
- if (err.name == 'UserError') {
1239
+ if (err.name == 'NonFatalError') {
1240
+ console.error(messageArgs([err.message]).join(' '));
1241
+ } else if (err.name == 'UserError') {
1232
1242
  msg = err.message;
1233
1243
  if (!/Error/.test(msg)) {
1234
1244
  msg = "Error: " + msg;
@@ -1248,6 +1258,12 @@
1248
1258
  return err;
1249
1259
  }
1250
1260
 
1261
+ function NonFatalError(msg) {
1262
+ var err = new Error(msg);
1263
+ err.name = 'NonFatalError';
1264
+ return err;
1265
+ }
1266
+
1251
1267
  function formatColumns(arr, alignments) {
1252
1268
  var widths = arr.reduce(function(memo, line) {
1253
1269
  return line.map(function(str, i) {
@@ -1308,6 +1324,7 @@
1308
1324
  loggingEnabled: loggingEnabled,
1309
1325
  error: error,
1310
1326
  stop: stop,
1327
+ interrupt: interrupt,
1311
1328
  message: message,
1312
1329
  setLoggingFunctions: setLoggingFunctions,
1313
1330
  print: print,
@@ -1315,6 +1332,7 @@
1315
1332
  debug: debug,
1316
1333
  printError: printError,
1317
1334
  UserError: UserError,
1335
+ NonFatalError: NonFatalError,
1318
1336
  formatColumns: formatColumns,
1319
1337
  formatStringsAsGrid: formatStringsAsGrid,
1320
1338
  formatLogArgs: formatLogArgs,
@@ -9035,7 +9053,8 @@
9035
9053
  var i = s.indexOf('.');
9036
9054
  return hasDot ? i > -1 : i == -1;
9037
9055
  };
9038
- return utils.uniq(matches.filter(f));
9056
+ var vars = utils.uniq(matches.filter(f));
9057
+ return vars;
9039
9058
  }
9040
9059
 
9041
9060
  // Return array of objects with properties assigned via dot notation
@@ -9100,23 +9119,24 @@
9100
9119
  }
9101
9120
 
9102
9121
  function getExpressionContext(lyr, mixins, opts) {
9122
+ var defs = getStateVar('defs');
9103
9123
  var env = getBaseContext();
9104
9124
  var ctx = {};
9105
9125
  var fields = lyr.data ? lyr.data.getFields() : [];
9106
9126
  opts = opts || {};
9107
9127
  addUtils(env); // mix in round(), sprintf(), etc.
9108
- if (lyr.data) {
9128
+ if (fields.length > 0) {
9109
9129
  // default to null values, so assignments to missing data properties
9110
9130
  // are applied to the data record, not the global object
9111
9131
  nullifyUnsetProperties(fields, env);
9112
9132
  }
9113
9133
  // Add global 'defs' to the expression context
9114
- mixins = utils.defaults(mixins || {}, getStateVar('defs'));
9134
+ mixins = utils.defaults(mixins || {}, defs);
9135
+ // also add defs as 'global' object
9136
+ env.global = defs;
9115
9137
  Object.keys(mixins).forEach(function(key) {
9116
9138
  // Catch name collisions between data fields and user-defined functions
9117
9139
  var d = Object.getOwnPropertyDescriptor(mixins, key);
9118
- if (key in env) {
9119
- }
9120
9140
  if (d.get) {
9121
9141
  // copy accessor function from mixins to context
9122
9142
  Object.defineProperty(ctx, key, {get: d.get}); // copy getter function to context
@@ -11465,13 +11485,22 @@
11465
11485
  var T = {
11466
11486
  stack: [],
11467
11487
  start: function() {
11468
- T.stack.push(+new Date());
11488
+ T.stack.push(Date.now());
11469
11489
  },
11470
11490
  stop: function() {
11471
- return (+new Date() - T.stack.pop()) + 'ms';
11491
+ return (Date.now() - T.stack.pop()) + 'ms';
11472
11492
  }
11473
11493
  };
11474
11494
 
11495
+ function tick(msg) {
11496
+ var now = Date.now();
11497
+ var elapsed = tickTime ? ' - ' + (now - tickTime) + 'ms' : '';
11498
+ tickTime = now;
11499
+ console.log((msg || '') + elapsed);
11500
+ }
11501
+
11502
+ var tickTime = 0;
11503
+
11475
11504
  // Create a mosaic layer from a dataset (useful for debugging commands like -clean
11476
11505
  // that create a mosaic as an intermediate data structure)
11477
11506
  // Create additional layers if the "debug" flag is present
@@ -14295,7 +14324,7 @@
14295
14324
  joinStr = obj.tag == 'text' || obj.tag == 'tspan' ? '' : '\n';
14296
14325
  svg += '>' + joinStr;
14297
14326
  if (obj.value) {
14298
- svg += obj.value;
14327
+ svg += stringEscape(obj.value);
14299
14328
  }
14300
14329
  if (obj.children) {
14301
14330
  svg += obj.children.map(stringify).join(joinStr);
@@ -14318,8 +14347,13 @@
14318
14347
  "'": '''
14319
14348
  };
14320
14349
  function stringEscape(s) {
14321
- return String(s).replace(rxp, function(s) {
14322
- return map[s];
14350
+ return String(s).replace(rxp, function(match, i) {
14351
+ var entity = map[match];
14352
+ // don't replace & with &
14353
+ if (match == '&' && s.substr(i, entity.length) == entity) {
14354
+ return '&';
14355
+ }
14356
+ return entity;
14323
14357
  });
14324
14358
  }
14325
14359
 
@@ -17129,7 +17163,7 @@ ${svg}
17129
17163
  c = buf[i];
17130
17164
  if (c == DQUOTE) {
17131
17165
  inQuotedText = !inQuotedText;
17132
- } else if (c == CR || c == LF) {
17166
+ } else if ((c == CR || c == LF) && !inQuotedText) {
17133
17167
  if (c == CR && i + 1 < bufLen && buf[i + 1] == LF) {
17134
17168
  // first half of CRLF pair: advance one byte
17135
17169
  i++;
@@ -17223,6 +17257,7 @@ ${svg}
17223
17257
  getRowConverter: getRowConverter,
17224
17258
  parseDelimHeaderSection: parseDelimHeaderSection,
17225
17259
  getDelimFieldFilter: getDelimFieldFilter,
17260
+ readLinesAsString: readLinesAsString,
17226
17261
  parseDelimText: parseDelimText
17227
17262
  });
17228
17263
 
@@ -18404,6 +18439,9 @@ ${svg}
18404
18439
  type: 'strings',
18405
18440
  describe: '[CSV] comma-sep. list of fields to import'
18406
18441
  })
18442
+ // .option('csv-comment', {
18443
+ // describe: '[CSV] comment line character(s)'
18444
+ // })
18407
18445
  .option('decimal-comma', {
18408
18446
  type: 'flag',
18409
18447
  describe: '[CSV] import numbers formatted like 1.000,01 or 1 000,01'
@@ -19153,6 +19191,14 @@ ${svg}
19153
19191
  .option('target', targetOpt)
19154
19192
  .option('no-replace', noReplaceOpt);
19155
19193
 
19194
+ parser.command('ignore')
19195
+ // .describe('stop processing if a condition is met')
19196
+ .option('empty', {
19197
+ describe: 'ignore empty files',
19198
+ type: 'flag'
19199
+ })
19200
+ .option('target', targetOpt);
19201
+
19156
19202
  parser.command('inlay')
19157
19203
  .describe('inscribe a polygon layer inside another polygon layer')
19158
19204
  .option('source', {
@@ -20419,7 +20465,7 @@ ${svg}
20419
20465
  function findStringEncoding() {
20420
20466
  var ldid = header.ldid,
20421
20467
  codepage = lookupCodePage(ldid),
20422
- samples = getNonAsciiSamples(50),
20468
+ samples = getNonAsciiSamples(),
20423
20469
  only7bit = samples.length === 0,
20424
20470
  encoding, msg;
20425
20471
 
@@ -20464,21 +20510,25 @@ ${svg}
20464
20510
  return arr;
20465
20511
  }
20466
20512
 
20467
- // Return up to @size buffers containing text samples
20513
+ // Return an array of buffers containing text samples
20468
20514
  // with at least one byte outside the 7-bit ascii range.
20469
- function getNonAsciiSamples(size) {
20515
+ function getNonAsciiSamples() {
20470
20516
  var samples = [];
20471
20517
  var stringFields = header.fields.filter(function(f) {
20472
20518
  return f.type == 'C';
20473
20519
  });
20520
+ var cols = stringFields.length;
20521
+ // don't scan all the rows in large files (slow)
20522
+ var rows = Math.min(header.recordCount, 10000);
20523
+ var maxSamples = 50;
20474
20524
  var buf = utils.createBuffer(256);
20475
20525
  var index = {};
20476
20526
  var f, chars, sample, hash;
20477
20527
  // include non-ascii field names, if any
20478
20528
  samples = getNonAsciiHeaders();
20479
- for (var r=0, rows=header.recordCount; r<rows; r++) {
20480
- for (var c=0, cols=stringFields.length; c<cols; c++) {
20481
- if (samples.length >= size) break;
20529
+ for (var r=0; r<rows; r++) {
20530
+ for (var c=0; c<cols; c++) {
20531
+ if (samples.length >= maxSamples) break;
20482
20532
  f = stringFields[c];
20483
20533
  bin.position(getRowOffset(r) + f.columnOffset);
20484
20534
  chars = readStringBytes(bin, f.size, buf);
@@ -29661,7 +29711,7 @@ ${svg}
29661
29711
  stop('Missing an assignment expression');
29662
29712
  }
29663
29713
  var defs = getStateVar('defs');
29664
- var compiled = compileFeatureExpression(opts.expression, {}, null, {});
29714
+ var compiled = compileFeatureExpression(opts.expression, {}, null, {no_warn: true});
29665
29715
  var result = compiled(null, defs);
29666
29716
  };
29667
29717
 
@@ -33263,6 +33313,12 @@ ${svg}
33263
33313
  };
33264
33314
  }
33265
33315
 
33316
+ cmd.ignore = function(targetLayer, dataset, opts) {
33317
+ if (opts.empty && layerIsEmpty(targetLayer)) {
33318
+ interrupt('Layer is empty, stopping processing');
33319
+ }
33320
+ };
33321
+
33266
33322
  cmd.include = function(opts) {
33267
33323
  var content, obj, context;
33268
33324
  // TODO: handle web context
@@ -37688,6 +37744,9 @@ ${svg}
37688
37744
  outputLayers = targetDataset.layers; // kludge to allow layer naming below
37689
37745
  }
37690
37746
 
37747
+ } else if (name == 'ignore') {
37748
+ applyCommandToEachLayer(cmd.ignore, targetLayers, targetDataset, opts);
37749
+
37691
37750
  } else if (name == 'include') {
37692
37751
  cmd.include(opts);
37693
37752
 
@@ -38058,6 +38117,7 @@ ${svg}
38058
38117
  cmd.options.output = outputArr;
38059
38118
  }
38060
38119
  });
38120
+
38061
38121
  runParsedCommands(commands, null, callback);
38062
38122
  }
38063
38123
 
@@ -38118,10 +38178,6 @@ ${svg}
38118
38178
  error("Changed in v0.4: runParsedCommands() takes a Catalog object");
38119
38179
  }
38120
38180
 
38121
- if (!utils.isFunction(done)) {
38122
- error("Missing a callback function");
38123
- }
38124
-
38125
38181
  if (!utils.isArray(commands)) {
38126
38182
  error("Expected an array of parsed commands");
38127
38183
  }
@@ -38142,18 +38198,25 @@ ${svg}
38142
38198
  // that it can modify the output dataset in-place instead of making a copy.
38143
38199
  commands[commands.length-1].options.final = true;
38144
38200
  }
38145
- commands = divideImportCommand(commands);
38146
- utils.reduceAsync(commands, catalog, nextCommand, done);
38147
38201
 
38148
- function nextCommand(catalog, cmd, next) {
38149
- setStateVar('current_command', cmd.name); // for log msgs
38150
- setStateVar('verbose', !!cmd.options.verbose);
38151
- setStateVar('debug', !!cmd.options.debug);
38152
- runCommand(cmd, catalog, next);
38202
+ var groups = divideImportCommand(commands);
38203
+ if (groups.length == 1) {
38204
+ // run a simple sequence of commands (input files are not batched)
38205
+ return runParsedCommands2(commands, catalog, done);
38206
+ }
38207
+
38208
+ // run duplicated commands (i.e. batch mode)
38209
+ utils.reduceAsync(groups, catalog, nextGroup, done);
38210
+
38211
+ function nextGroup(catalog, commands, next) {
38212
+ runParsedCommands2(commands, catalog, function(err, catalog) {
38213
+ err = filterError(err);
38214
+ next(err, catalog);
38215
+ });
38153
38216
  }
38154
38217
 
38155
38218
  function done(err, catalog) {
38156
- if (err) printError(err);
38219
+ err = filterError(err);
38157
38220
  cb(err, catalog);
38158
38221
  setStateVar('current_command', null);
38159
38222
  setStateVar('verbose', false);
@@ -38161,11 +38224,31 @@ ${svg}
38161
38224
  }
38162
38225
  }
38163
38226
 
38227
+ function filterError(err) {
38228
+ if (err) printError(err);
38229
+ if (err && err.name == 'NonFatalError') {
38230
+ return null;
38231
+ }
38232
+ return err;
38233
+ }
38234
+
38235
+ function runParsedCommands2(commands, catalog, cb) {
38236
+ utils.reduceAsync(commands, catalog, nextCommand, cb);
38237
+
38238
+ function nextCommand(catalog, cmd, next) {
38239
+ setStateVar('current_command', cmd.name); // for log msgs
38240
+ setStateVar('verbose', !!cmd.options.verbose);
38241
+ setStateVar('debug', !!cmd.options.debug);
38242
+ runCommand(cmd, catalog, next);
38243
+ }
38244
+ }
38245
+
38246
+
38164
38247
  // If an initial import command indicates that several input files should be
38165
38248
  // processed separately, then duplicate the sequence of commands to run
38166
38249
  // once for each input file
38167
38250
  // @commands Array of parsed commands
38168
- // Returns: either original command array or array of duplicated commands.
38251
+ // Returns: Array of one or more sequences of parsed commands
38169
38252
  //
38170
38253
  function divideImportCommand(commands) {
38171
38254
  var firstCmd = commands[0],
@@ -38173,23 +38256,23 @@ ${svg}
38173
38256
 
38174
38257
  if (firstCmd.name != 'i' || opts.stdin || opts.merge_files ||
38175
38258
  opts.combine_files || !opts.files || opts.files.length < 2) {
38176
- return commands;
38259
+ return [commands];
38177
38260
  }
38178
38261
 
38179
- return (opts.files).reduce(function(memo, file) {
38180
- var importCmd = {
38262
+ return opts.files.map(function(file) {
38263
+ var group = [{
38181
38264
  name: 'i',
38182
38265
  options: utils.defaults({
38183
38266
  files:[file],
38184
38267
  replace: true // kludge to replace data catalog
38185
38268
  }, opts)
38186
- };
38187
- memo.push(importCmd);
38188
- memo.push.apply(memo, commands.slice(1));
38189
- return memo;
38190
- }, []);
38269
+ }];
38270
+ group.push.apply(group, commands.slice(1));
38271
+ return group;
38272
+ });
38191
38273
  }
38192
38274
 
38275
+
38193
38276
  function printStartupMessages() {
38194
38277
  // print heap memory message if running with a custom amount
38195
38278
  var rxp = /^--max-old-space-size=([0-9]+)$/;
package/www/page.css CHANGED
@@ -60,8 +60,7 @@ body {
60
60
  color: #10699b;
61
61
  }
62
62
 
63
- .dot-underline,
64
- .zoom-box.zooming {
63
+ .dot-underline {
65
64
  border-color: #10699b;
66
65
  }
67
66
 
@@ -457,7 +456,7 @@ body.dragover #import-options-drop-area .drop-area {
457
456
  text-align: left;
458
457
  margin-top: 12px;
459
458
  margin-right: 20px;
460
- padding: 11px 15px 9px 15px;
459
+ padding: 12px 18px 12px 18px;
461
460
  vertical-align: top;
462
461
  display: inline-block;
463
462
  /* border: 1px solid #aaa; */
@@ -905,7 +904,7 @@ img.close-btn:hover,
905
904
  box-sizing: border-box;
906
905
  overflow: hidden;
907
906
  overflow-y: auto;
908
- padding: 4px 12px;
907
+ padding: 4px 12px 3px;
909
908
  line-height: 1.2;
910
909
  }
911
910
 
@@ -1120,12 +1119,14 @@ img.close-btn:hover,
1120
1119
 
1121
1120
  .zoom-box {
1122
1121
  position: absolute;
1123
- border: 1px solid #f74b80;
1122
+ border: 1px solid #cc6acc;
1124
1123
  z-index: 15;
1125
1124
  pointer-events: none;
1126
1125
  }
1127
1126
 
1128
-
1127
+ .zoom-box.zooming {
1128
+ border-color: #1385B7;
1129
+ }
1129
1130
 
1130
1131
  /* Simplification control ------------ */
1131
1132