mapshaper 0.5.68 → 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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ v0.5.69
2
+ * Added undocumented -ignore command.
3
+ * Bug fix
4
+
5
+ v0.5.68
6
+ * Bug fix
7
+
1
8
  v0.5.67
2
9
  * Bug fix
3
10
 
package/mapshaper.js CHANGED
@@ -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,
@@ -14306,7 +14324,7 @@
14306
14324
  joinStr = obj.tag == 'text' || obj.tag == 'tspan' ? '' : '\n';
14307
14325
  svg += '>' + joinStr;
14308
14326
  if (obj.value) {
14309
- svg += obj.value;
14327
+ svg += stringEscape(obj.value);
14310
14328
  }
14311
14329
  if (obj.children) {
14312
14330
  svg += obj.children.map(stringify).join(joinStr);
@@ -14329,8 +14347,13 @@
14329
14347
  "'": '''
14330
14348
  };
14331
14349
  function stringEscape(s) {
14332
- return String(s).replace(rxp, function(s) {
14333
- 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;
14334
14357
  });
14335
14358
  }
14336
14359
 
@@ -19168,6 +19191,14 @@ ${svg}
19168
19191
  .option('target', targetOpt)
19169
19192
  .option('no-replace', noReplaceOpt);
19170
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
+
19171
19202
  parser.command('inlay')
19172
19203
  .describe('inscribe a polygon layer inside another polygon layer')
19173
19204
  .option('source', {
@@ -33282,6 +33313,12 @@ ${svg}
33282
33313
  };
33283
33314
  }
33284
33315
 
33316
+ cmd.ignore = function(targetLayer, dataset, opts) {
33317
+ if (opts.empty && layerIsEmpty(targetLayer)) {
33318
+ interrupt('Layer is empty, stopping processing');
33319
+ }
33320
+ };
33321
+
33285
33322
  cmd.include = function(opts) {
33286
33323
  var content, obj, context;
33287
33324
  // TODO: handle web context
@@ -37707,6 +37744,9 @@ ${svg}
37707
37744
  outputLayers = targetDataset.layers; // kludge to allow layer naming below
37708
37745
  }
37709
37746
 
37747
+ } else if (name == 'ignore') {
37748
+ applyCommandToEachLayer(cmd.ignore, targetLayers, targetDataset, opts);
37749
+
37710
37750
  } else if (name == 'include') {
37711
37751
  cmd.include(opts);
37712
37752
 
@@ -38077,6 +38117,7 @@ ${svg}
38077
38117
  cmd.options.output = outputArr;
38078
38118
  }
38079
38119
  });
38120
+
38080
38121
  runParsedCommands(commands, null, callback);
38081
38122
  }
38082
38123
 
@@ -38137,10 +38178,6 @@ ${svg}
38137
38178
  error("Changed in v0.4: runParsedCommands() takes a Catalog object");
38138
38179
  }
38139
38180
 
38140
- if (!utils.isFunction(done)) {
38141
- error("Missing a callback function");
38142
- }
38143
-
38144
38181
  if (!utils.isArray(commands)) {
38145
38182
  error("Expected an array of parsed commands");
38146
38183
  }
@@ -38161,18 +38198,25 @@ ${svg}
38161
38198
  // that it can modify the output dataset in-place instead of making a copy.
38162
38199
  commands[commands.length-1].options.final = true;
38163
38200
  }
38164
- commands = divideImportCommand(commands);
38165
- utils.reduceAsync(commands, catalog, nextCommand, done);
38166
38201
 
38167
- function nextCommand(catalog, cmd, next) {
38168
- setStateVar('current_command', cmd.name); // for log msgs
38169
- setStateVar('verbose', !!cmd.options.verbose);
38170
- setStateVar('debug', !!cmd.options.debug);
38171
- 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
+ });
38172
38216
  }
38173
38217
 
38174
38218
  function done(err, catalog) {
38175
- if (err) printError(err);
38219
+ err = filterError(err);
38176
38220
  cb(err, catalog);
38177
38221
  setStateVar('current_command', null);
38178
38222
  setStateVar('verbose', false);
@@ -38180,11 +38224,31 @@ ${svg}
38180
38224
  }
38181
38225
  }
38182
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
+
38183
38247
  // If an initial import command indicates that several input files should be
38184
38248
  // processed separately, then duplicate the sequence of commands to run
38185
38249
  // once for each input file
38186
38250
  // @commands Array of parsed commands
38187
- // Returns: either original command array or array of duplicated commands.
38251
+ // Returns: Array of one or more sequences of parsed commands
38188
38252
  //
38189
38253
  function divideImportCommand(commands) {
38190
38254
  var firstCmd = commands[0],
@@ -38192,23 +38256,23 @@ ${svg}
38192
38256
 
38193
38257
  if (firstCmd.name != 'i' || opts.stdin || opts.merge_files ||
38194
38258
  opts.combine_files || !opts.files || opts.files.length < 2) {
38195
- return commands;
38259
+ return [commands];
38196
38260
  }
38197
38261
 
38198
- return (opts.files).reduce(function(memo, file) {
38199
- var importCmd = {
38262
+ return opts.files.map(function(file) {
38263
+ var group = [{
38200
38264
  name: 'i',
38201
38265
  options: utils.defaults({
38202
38266
  files:[file],
38203
38267
  replace: true // kludge to replace data catalog
38204
38268
  }, opts)
38205
- };
38206
- memo.push(importCmd);
38207
- memo.push.apply(memo, commands.slice(1));
38208
- return memo;
38209
- }, []);
38269
+ }];
38270
+ group.push.apply(group, commands.slice(1));
38271
+ return group;
38272
+ });
38210
38273
  }
38211
38274
 
38275
+
38212
38276
  function printStartupMessages() {
38213
38277
  // print heap memory message if running with a custom amount
38214
38278
  var rxp = /^--max-old-space-size=([0-9]+)$/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.68",
3
+ "version": "0.5.69",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -3976,6 +3976,10 @@
3976
3976
  throw new UserError$1(formatLogArgs(arguments));
3977
3977
  };
3978
3978
 
3979
+ var _interrupt = function() {
3980
+ throw new NonFatalError(formatLogArgs(arguments));
3981
+ };
3982
+
3979
3983
  var _message = function() {
3980
3984
  logArgs(arguments);
3981
3985
  };
@@ -3994,10 +3998,14 @@
3994
3998
  }
3995
3999
 
3996
4000
  // Handle an error caused by invalid input or misuse of API
3997
- function stop$1 () {
4001
+ function stop$1() {
3998
4002
  _stop.apply(null, utils$1.toArray(arguments));
3999
4003
  }
4000
4004
 
4005
+ function interrupt() {
4006
+ _interrupt.apply(null, utils$1.toArray(arguments));
4007
+ }
4008
+
4001
4009
  // Print a status message
4002
4010
  function message$1() {
4003
4011
  _message.apply(null, messageArgs(arguments));
@@ -4037,7 +4045,9 @@
4037
4045
  if (utils$1.isString(err)) {
4038
4046
  err = new UserError$1(err);
4039
4047
  }
4040
- if (err.name == 'UserError') {
4048
+ if (err.name == 'NonFatalError') {
4049
+ console.error(messageArgs([err.message]).join(' '));
4050
+ } else if (err.name == 'UserError') {
4041
4051
  msg = err.message;
4042
4052
  if (!/Error/.test(msg)) {
4043
4053
  msg = "Error: " + msg;
@@ -4057,6 +4067,12 @@
4057
4067
  return err;
4058
4068
  }
4059
4069
 
4070
+ function NonFatalError(msg) {
4071
+ var err = new Error(msg);
4072
+ err.name = 'NonFatalError';
4073
+ return err;
4074
+ }
4075
+
4060
4076
  function formatColumns(arr, alignments) {
4061
4077
  var widths = arr.reduce(function(memo, line) {
4062
4078
  return line.map(function(str, i) {
package/www/mapshaper.js CHANGED
@@ -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,
@@ -14306,7 +14324,7 @@
14306
14324
  joinStr = obj.tag == 'text' || obj.tag == 'tspan' ? '' : '\n';
14307
14325
  svg += '>' + joinStr;
14308
14326
  if (obj.value) {
14309
- svg += obj.value;
14327
+ svg += stringEscape(obj.value);
14310
14328
  }
14311
14329
  if (obj.children) {
14312
14330
  svg += obj.children.map(stringify).join(joinStr);
@@ -14329,8 +14347,13 @@
14329
14347
  "'": '&apos;'
14330
14348
  };
14331
14349
  function stringEscape(s) {
14332
- return String(s).replace(rxp, function(s) {
14333
- return map[s];
14350
+ return String(s).replace(rxp, function(match, i) {
14351
+ var entity = map[match];
14352
+ // don't replace &amp; with &amp;amp;
14353
+ if (match == '&' && s.substr(i, entity.length) == entity) {
14354
+ return '&';
14355
+ }
14356
+ return entity;
14334
14357
  });
14335
14358
  }
14336
14359
 
@@ -19168,6 +19191,14 @@ ${svg}
19168
19191
  .option('target', targetOpt)
19169
19192
  .option('no-replace', noReplaceOpt);
19170
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
+
19171
19202
  parser.command('inlay')
19172
19203
  .describe('inscribe a polygon layer inside another polygon layer')
19173
19204
  .option('source', {
@@ -33282,6 +33313,12 @@ ${svg}
33282
33313
  };
33283
33314
  }
33284
33315
 
33316
+ cmd.ignore = function(targetLayer, dataset, opts) {
33317
+ if (opts.empty && layerIsEmpty(targetLayer)) {
33318
+ interrupt('Layer is empty, stopping processing');
33319
+ }
33320
+ };
33321
+
33285
33322
  cmd.include = function(opts) {
33286
33323
  var content, obj, context;
33287
33324
  // TODO: handle web context
@@ -37707,6 +37744,9 @@ ${svg}
37707
37744
  outputLayers = targetDataset.layers; // kludge to allow layer naming below
37708
37745
  }
37709
37746
 
37747
+ } else if (name == 'ignore') {
37748
+ applyCommandToEachLayer(cmd.ignore, targetLayers, targetDataset, opts);
37749
+
37710
37750
  } else if (name == 'include') {
37711
37751
  cmd.include(opts);
37712
37752
 
@@ -38077,6 +38117,7 @@ ${svg}
38077
38117
  cmd.options.output = outputArr;
38078
38118
  }
38079
38119
  });
38120
+
38080
38121
  runParsedCommands(commands, null, callback);
38081
38122
  }
38082
38123
 
@@ -38137,10 +38178,6 @@ ${svg}
38137
38178
  error("Changed in v0.4: runParsedCommands() takes a Catalog object");
38138
38179
  }
38139
38180
 
38140
- if (!utils.isFunction(done)) {
38141
- error("Missing a callback function");
38142
- }
38143
-
38144
38181
  if (!utils.isArray(commands)) {
38145
38182
  error("Expected an array of parsed commands");
38146
38183
  }
@@ -38161,18 +38198,25 @@ ${svg}
38161
38198
  // that it can modify the output dataset in-place instead of making a copy.
38162
38199
  commands[commands.length-1].options.final = true;
38163
38200
  }
38164
- commands = divideImportCommand(commands);
38165
- utils.reduceAsync(commands, catalog, nextCommand, done);
38166
38201
 
38167
- function nextCommand(catalog, cmd, next) {
38168
- setStateVar('current_command', cmd.name); // for log msgs
38169
- setStateVar('verbose', !!cmd.options.verbose);
38170
- setStateVar('debug', !!cmd.options.debug);
38171
- 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
+ });
38172
38216
  }
38173
38217
 
38174
38218
  function done(err, catalog) {
38175
- if (err) printError(err);
38219
+ err = filterError(err);
38176
38220
  cb(err, catalog);
38177
38221
  setStateVar('current_command', null);
38178
38222
  setStateVar('verbose', false);
@@ -38180,11 +38224,31 @@ ${svg}
38180
38224
  }
38181
38225
  }
38182
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
+
38183
38247
  // If an initial import command indicates that several input files should be
38184
38248
  // processed separately, then duplicate the sequence of commands to run
38185
38249
  // once for each input file
38186
38250
  // @commands Array of parsed commands
38187
- // Returns: either original command array or array of duplicated commands.
38251
+ // Returns: Array of one or more sequences of parsed commands
38188
38252
  //
38189
38253
  function divideImportCommand(commands) {
38190
38254
  var firstCmd = commands[0],
@@ -38192,23 +38256,23 @@ ${svg}
38192
38256
 
38193
38257
  if (firstCmd.name != 'i' || opts.stdin || opts.merge_files ||
38194
38258
  opts.combine_files || !opts.files || opts.files.length < 2) {
38195
- return commands;
38259
+ return [commands];
38196
38260
  }
38197
38261
 
38198
- return (opts.files).reduce(function(memo, file) {
38199
- var importCmd = {
38262
+ return opts.files.map(function(file) {
38263
+ var group = [{
38200
38264
  name: 'i',
38201
38265
  options: utils.defaults({
38202
38266
  files:[file],
38203
38267
  replace: true // kludge to replace data catalog
38204
38268
  }, opts)
38205
- };
38206
- memo.push(importCmd);
38207
- memo.push.apply(memo, commands.slice(1));
38208
- return memo;
38209
- }, []);
38269
+ }];
38270
+ group.push.apply(group, commands.slice(1));
38271
+ return group;
38272
+ });
38210
38273
  }
38211
38274
 
38275
+
38212
38276
  function printStartupMessages() {
38213
38277
  // print heap memory message if running with a custom amount
38214
38278
  var rxp = /^--max-old-space-size=([0-9]+)$/;