mapshaper 0.6.10 → 0.6.12

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/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.10";
3
+ var VERSION = "0.6.12";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -7311,15 +7311,18 @@
7311
7311
  // replacing content so ArrayBuffers can be gc'd
7312
7312
  obj.content = cli.convertArrayBuffer(obj.content); // convert to Buffer
7313
7313
  }
7314
+ if (opts.gzip) {
7315
+ path = path + '.gz';
7316
+ obj.content = require$1('zlib').gzipSync(obj.content);
7317
+ }
7314
7318
  if (opts.output) {
7315
7319
  opts.output.push({filename: path, content: obj.content});
7316
- } else {
7317
- if (!opts.force && inputFiles.indexOf(path) > -1) {
7318
- stop('Need to use the "-o force" option to overwrite input files.');
7319
- }
7320
- cli.writeFile(path, obj.content);
7321
- message("Wrote " + path);
7320
+ return;
7321
+ } if (!opts.force && inputFiles.indexOf(path) > -1) {
7322
+ stop('Need to use the "-o force" option to overwrite input files.');
7322
7323
  }
7324
+ cli.writeFile(path, obj.content);
7325
+ message("Wrote " + path);
7323
7326
  });
7324
7327
  }
7325
7328
  if (cb) cb(null);
@@ -15641,9 +15644,11 @@ ${svg}
15641
15644
  } else if (buf instanceof ArrayBuffer) {
15642
15645
  // we're good
15643
15646
  } else if (typeof B$3 == 'function' && buf instanceof B$3) {
15644
- // Since node 0.10, DataView constructor doesn't accept Buffers,
15645
- // so need to copy Buffer to ArrayBuffer
15646
- buf = BinArray.toArrayBuffer(buf);
15647
+ if (buf.buffer && buf.buffer.byteLength == buf.length) {
15648
+ buf = buf.buffer;
15649
+ } else {
15650
+ buf = BinArray.copyToArrayBuffer(buf);
15651
+ }
15647
15652
  } else {
15648
15653
  error("BinArray constructor takes an integer, ArrayBuffer or Buffer argument");
15649
15654
  }
@@ -15689,7 +15694,7 @@ ${svg}
15689
15694
  return bytes;
15690
15695
  };
15691
15696
 
15692
- BinArray.toArrayBuffer = function(src) {
15697
+ BinArray.copyToArrayBuffer = function(src) {
15693
15698
  var n = src.length,
15694
15699
  dest = new ArrayBuffer(n),
15695
15700
  view = new Uint8Array(dest);
@@ -19346,6 +19351,10 @@ ${svg}
19346
19351
  describe: 'allow overwriting input files',
19347
19352
  type: 'flag'
19348
19353
  })
19354
+ .option('gzip', {
19355
+ describe: 'apply gzip compression to output files',
19356
+ type: 'flag'
19357
+ })
19349
19358
  .option('dry-run', {
19350
19359
  // describe: 'do not output any files'
19351
19360
  type: 'flag'
@@ -23490,9 +23499,9 @@ ${svg}
23490
23499
 
23491
23500
  if (!content) {
23492
23501
  reader = new FileReader(filename);
23493
- } else if (content instanceof ArrayBuffer) {
23502
+ } else if (content instanceof ArrayBuffer || content instanceof Buffer) {
23494
23503
  // Web API imports JSON as ArrayBuffer, to support larger files
23495
- if (content.byteLength < 1e7) {
23504
+ if ((content.byteLength || content.length) < 1e7) {
23496
23505
  // content = utils.createBuffer(content).toString();
23497
23506
  content = bufferToString(utils.createBuffer(content));
23498
23507
  } else {
@@ -23517,7 +23526,7 @@ ${svg}
23517
23526
  content = JSON.parse(content); // ~3sec for 100MB string
23518
23527
  } catch(e) {
23519
23528
  // stop("Unable to parse JSON");
23520
- stop('JSON parsing error --', e.message);
23529
+ stop('JSON parsing error:', e.message);
23521
23530
  }
23522
23531
  }
23523
23532
  if (opts.json_path) {
@@ -23800,6 +23809,16 @@ ${svg}
23800
23809
  } else if (fileType) { // string type, e.g. kml, geojson
23801
23810
  content = cli.readFile(path, encoding || 'utf-8', cache);
23802
23811
 
23812
+ } else if (getFileExtension(path) == 'gz') {
23813
+ var pathgz = path;
23814
+ path = pathgz.replace(/\.gz$/, '');
23815
+ fileType = guessInputFileType(path);
23816
+ if (!fileType) {
23817
+ stop('Unrecognized file type:', path);
23818
+ }
23819
+ // TODO: consider using a temp file, to support incremental reading
23820
+ content = require('zlib').gunzipSync(cli.readFile(pathgz));
23821
+
23803
23822
  } else { // type can't be inferred from filename -- try reading as text
23804
23823
  content = cli.readFile(path, encoding || 'utf-8', cache);
23805
23824
  fileType = guessInputContentType(content);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.10",
3
+ "version": "0.6.12",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/index.html CHANGED
@@ -97,7 +97,10 @@
97
97
  <img class="pin-btn pinned" src="images/eye2.png">
98
98
  </div>
99
99
  <div class="layer-list"></div>
100
- <div><div id="add-file-btn" class="dialog-btn btn">Add a file</div></div>
100
+ <div>
101
+ <div id="add-file-btn" class="dialog-btn btn">Add a file</div>
102
+ <!-- <div id="add-empty-btn" class="dialog-btn btn">Empty layer</div> -->
103
+ </div>
101
104
  </div>
102
105
  </div>
103
106
  </div>
@@ -1277,6 +1277,7 @@
1277
1277
  new FileChooser('#file-selection-btn', receiveFiles);
1278
1278
  new FileChooser('#import-buttons .add-btn', receiveFiles);
1279
1279
  new FileChooser('#add-file-btn', receiveFiles);
1280
+ // new SimpleButton('#add-empty-btn').on('click', addEmptyLayer);
1280
1281
  initDropArea('#import-quick-drop', true);
1281
1282
  initDropArea('#import-drop');
1282
1283
  gui.keyboard.onMenuSubmit(El('#import-options'), importQueuedFiles);
@@ -1322,9 +1323,12 @@
1322
1323
  await importFiles(files);
1323
1324
  }
1324
1325
  } catch(e) {
1325
- console.error(e);
1326
+ gui.alert(e.message, 'Import error');
1327
+ }
1328
+ if (gui.getMode() == 'import') {
1329
+ // Mode could also be 'alert' if an error is thrown and handled
1330
+ gui.clearMode();
1326
1331
  }
1327
- gui.clearMode();
1328
1332
  }
1329
1333
 
1330
1334
  function turnOn() {
@@ -1388,10 +1392,20 @@
1388
1392
  }
1389
1393
 
1390
1394
  async function receiveFiles(files) {
1391
- // TODO: show importing message here?
1392
- var expanded = await expandFiles(files);
1395
+ var expanded = [];
1396
+ try {
1397
+ expanded = await expandFiles(files);
1398
+ } catch(e) {
1399
+ gui.alert(e.message, 'Import error');
1400
+ return;
1401
+ }
1393
1402
  addFilesToQueue(expanded);
1394
- if (queuedFiles.length === 0) return;
1403
+ if (queuedFiles.length === 0) {
1404
+ var names = getFileNames(files);
1405
+ var msg = `Unable to import data from: ${names.join(', ')}`;
1406
+ gui.alert(msg, 'Import error');
1407
+ return;
1408
+ }
1395
1409
  gui.enterMode('import');
1396
1410
  if (useQuickView()) {
1397
1411
  importQueuedFiles();
@@ -1402,6 +1416,10 @@
1402
1416
  }
1403
1417
  }
1404
1418
 
1419
+ function getFileNames(files) {
1420
+ return Array.from(files).map(function(f) {return f.name;});
1421
+ }
1422
+
1405
1423
  async function expandFiles(files) {
1406
1424
  var files2 = [], expanded;
1407
1425
  for (var f of files) {
@@ -1442,6 +1460,19 @@
1442
1460
  gui.session.fileImported(group.filename, optStr);
1443
1461
  }
1444
1462
 
1463
+ function addEmptyLayer() {
1464
+ var dataset = {
1465
+ layers: [{
1466
+ name: 'New layer',
1467
+ geometry_type: 'point',
1468
+ shapes: []
1469
+ }],
1470
+ info: {}
1471
+ };
1472
+ model.addDataset(dataset);
1473
+ gui.clearMode();
1474
+ }
1475
+
1445
1476
  function filesMayContainPaths(files) {
1446
1477
  return utils$1.some(files, function(f) {
1447
1478
  var type = internal.guessInputFileType(f.name);
@@ -1497,16 +1528,6 @@
1497
1528
  }
1498
1529
  }
1499
1530
 
1500
- function handleImportError(e, fileName) {
1501
- var msg = utils$1.isString(e) ? e : e.message;
1502
- if (fileName) {
1503
- msg = "Error importing <i>" + fileName + "</i><br>" + msg;
1504
- }
1505
- clearQueuedFiles();
1506
- gui.alert(msg);
1507
- console.error(e);
1508
- }
1509
-
1510
1531
  function prepFilesForDownload(names) {
1511
1532
  var items = names.map(function(name) {
1512
1533
  var isUrl = /:\/\//.test(name);
@@ -1565,7 +1586,7 @@
1565
1586
  }
1566
1587
 
1567
1588
  async function readZipFile(file) {
1568
- var files;
1589
+ var files = [];
1569
1590
  await wait(35); // pause a beat so status message can display
1570
1591
  try {
1571
1592
  files = await runAsync(GUI.readZipFile, file);
@@ -1575,8 +1596,8 @@
1575
1596
  return !/\.txt$/i.test(f.name);
1576
1597
  });
1577
1598
  } catch(e) {
1578
- handleImportError(e, file.name);
1579
- files = [];
1599
+ console.error(e);
1600
+ throw Error(`Unable to unzip ${file.name}`);
1580
1601
  }
1581
1602
  return files;
1582
1603
  }
@@ -1592,9 +1613,9 @@
1592
1613
  type: internal.guessInputType(file.name, content)
1593
1614
  };
1594
1615
  } catch (e) {
1595
- handleImportError("Web browser was unable to load the file.", file.name);
1616
+ console.error(e);
1617
+ throw Error(`Browser was unable to load the file ${file.name}`);
1596
1618
  }
1597
- return null;
1598
1619
  }
1599
1620
 
1600
1621
  async function readFiles(files) {
@@ -2985,15 +3006,19 @@
2985
3006
  var el;
2986
3007
  gui.addMode('alert', function() {}, turnOff);
2987
3008
 
2988
- gui.alert = function(str) {
2989
- var infoBox;
3009
+ gui.alert = function(str, title) {
3010
+ var infoBox, html = '';
2990
3011
  if (!el) {
2991
3012
  el = El('div').appendTo('body').addClass('error-wrapper');
2992
3013
  infoBox = El('div').appendTo(el).addClass('error-box info-box selectable');
2993
- El('p').addClass('error-message').appendTo(infoBox);
3014
+ El('div').appendTo(infoBox).addClass('error-content');
2994
3015
  El('div').addClass("btn dialog-btn").appendTo(infoBox).html('close').on('click', gui.clearMode);
2995
3016
  }
2996
- el.findChild('.error-message').html(str);
3017
+ if (title) {
3018
+ html += `<div class="error-title">${title}</div>`;
3019
+ }
3020
+ html += `<p class="error-message">${str}</p>`;
3021
+ el.findChild('.error-content').html(html);
2997
3022
  gui.enterMode('alert');
2998
3023
  };
2999
3024
 
@@ -6936,7 +6961,7 @@
6936
6961
 
6937
6962
  el.hide();
6938
6963
 
6939
- gui.on('map_navigation', function() {
6964
+ gui.on('map_rendered', function() {
6940
6965
  if (!_on) return;
6941
6966
  redraw();
6942
6967
  });
@@ -7060,7 +7085,7 @@
7060
7085
  function coordsToPix(bbox, ext) {
7061
7086
  var a = ext.translateCoords(bbox[0], bbox[1]);
7062
7087
  var b = ext.translateCoords(bbox[2], bbox[3]);
7063
- return [a[0], b[1], b[0], a[1]];
7088
+ return [Math.round(a[0]), Math.round(b[1]), Math.round(b[0]), Math.round(a[1])];
7064
7089
  }
7065
7090
 
7066
7091
  function pixToCoords(bbox, ext) {
@@ -7100,21 +7125,29 @@
7100
7125
  }
7101
7126
 
7102
7127
  function showHandles(handles, props) {
7103
- var SIZE = 6; // should match .handle size in page.css
7128
+ var scaledSize = Math.ceil(Math.min(props.width, props.height) / 5);
7129
+ var HANDLE_SIZE = Math.min(scaledSize, 7);
7104
7130
  handles.forEach(function(handle) {
7105
7131
  var top = 0,
7106
7132
  left = 0;
7107
7133
  if (handle.col == 'center') {
7108
- left += props.width / 2 - SIZE / 2;
7134
+ left += props.width / 2 - HANDLE_SIZE / 2;
7109
7135
  } else if (handle.col == 'right') {
7110
- left += props.width - SIZE;
7136
+ left += props.width - HANDLE_SIZE + 1;
7137
+ } else {
7138
+ left -= 1;
7111
7139
  }
7112
7140
  if (handle.row == 'center') {
7113
- top += props.height / 2 - SIZE / 2;
7141
+ top += props.height / 2 - HANDLE_SIZE / 2;
7114
7142
  } else if (handle.row == 'bottom') {
7115
- top += props.height - SIZE;
7143
+ top += props.height - HANDLE_SIZE + 1;
7144
+ } else {
7145
+ top -= 1;
7116
7146
  }
7147
+
7117
7148
  handle.el.css({
7149
+ width: HANDLE_SIZE,
7150
+ height: HANDLE_SIZE,
7118
7151
  top: top,
7119
7152
  left: left
7120
7153
  });
@@ -7158,11 +7191,6 @@
7158
7191
  ext.home();
7159
7192
  });
7160
7193
 
7161
- ext.on('change', function() {
7162
- // kludge so controls (e.g. HighlightBox) can initialize before map is ready
7163
- gui.dispatchEvent('map_navigation');
7164
- });
7165
-
7166
7194
  zoomTween.on('change', function(e) {
7167
7195
  ext.zoomToExtent(e.value, _fx, _fy);
7168
7196
  });
@@ -10602,6 +10630,7 @@
10602
10630
  _stack.drawOverlayLayer(_overlayLyr, action);
10603
10631
  // draw furniture
10604
10632
  _stack.drawFurnitureLayers(furnitureLayers, action);
10633
+ gui.dispatchEvent('map_rendered');
10605
10634
  }
10606
10635
  }
10607
10636
 
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.10";
3
+ var VERSION = "0.6.12";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -7311,15 +7311,18 @@
7311
7311
  // replacing content so ArrayBuffers can be gc'd
7312
7312
  obj.content = cli.convertArrayBuffer(obj.content); // convert to Buffer
7313
7313
  }
7314
+ if (opts.gzip) {
7315
+ path = path + '.gz';
7316
+ obj.content = require$1('zlib').gzipSync(obj.content);
7317
+ }
7314
7318
  if (opts.output) {
7315
7319
  opts.output.push({filename: path, content: obj.content});
7316
- } else {
7317
- if (!opts.force && inputFiles.indexOf(path) > -1) {
7318
- stop('Need to use the "-o force" option to overwrite input files.');
7319
- }
7320
- cli.writeFile(path, obj.content);
7321
- message("Wrote " + path);
7320
+ return;
7321
+ } if (!opts.force && inputFiles.indexOf(path) > -1) {
7322
+ stop('Need to use the "-o force" option to overwrite input files.');
7322
7323
  }
7324
+ cli.writeFile(path, obj.content);
7325
+ message("Wrote " + path);
7323
7326
  });
7324
7327
  }
7325
7328
  if (cb) cb(null);
@@ -15641,9 +15644,11 @@ ${svg}
15641
15644
  } else if (buf instanceof ArrayBuffer) {
15642
15645
  // we're good
15643
15646
  } else if (typeof B$3 == 'function' && buf instanceof B$3) {
15644
- // Since node 0.10, DataView constructor doesn't accept Buffers,
15645
- // so need to copy Buffer to ArrayBuffer
15646
- buf = BinArray.toArrayBuffer(buf);
15647
+ if (buf.buffer && buf.buffer.byteLength == buf.length) {
15648
+ buf = buf.buffer;
15649
+ } else {
15650
+ buf = BinArray.copyToArrayBuffer(buf);
15651
+ }
15647
15652
  } else {
15648
15653
  error("BinArray constructor takes an integer, ArrayBuffer or Buffer argument");
15649
15654
  }
@@ -15689,7 +15694,7 @@ ${svg}
15689
15694
  return bytes;
15690
15695
  };
15691
15696
 
15692
- BinArray.toArrayBuffer = function(src) {
15697
+ BinArray.copyToArrayBuffer = function(src) {
15693
15698
  var n = src.length,
15694
15699
  dest = new ArrayBuffer(n),
15695
15700
  view = new Uint8Array(dest);
@@ -19346,6 +19351,10 @@ ${svg}
19346
19351
  describe: 'allow overwriting input files',
19347
19352
  type: 'flag'
19348
19353
  })
19354
+ .option('gzip', {
19355
+ describe: 'apply gzip compression to output files',
19356
+ type: 'flag'
19357
+ })
19349
19358
  .option('dry-run', {
19350
19359
  // describe: 'do not output any files'
19351
19360
  type: 'flag'
@@ -23490,9 +23499,9 @@ ${svg}
23490
23499
 
23491
23500
  if (!content) {
23492
23501
  reader = new FileReader(filename);
23493
- } else if (content instanceof ArrayBuffer) {
23502
+ } else if (content instanceof ArrayBuffer || content instanceof Buffer) {
23494
23503
  // Web API imports JSON as ArrayBuffer, to support larger files
23495
- if (content.byteLength < 1e7) {
23504
+ if ((content.byteLength || content.length) < 1e7) {
23496
23505
  // content = utils.createBuffer(content).toString();
23497
23506
  content = bufferToString(utils.createBuffer(content));
23498
23507
  } else {
@@ -23517,7 +23526,7 @@ ${svg}
23517
23526
  content = JSON.parse(content); // ~3sec for 100MB string
23518
23527
  } catch(e) {
23519
23528
  // stop("Unable to parse JSON");
23520
- stop('JSON parsing error --', e.message);
23529
+ stop('JSON parsing error:', e.message);
23521
23530
  }
23522
23531
  }
23523
23532
  if (opts.json_path) {
@@ -23800,6 +23809,16 @@ ${svg}
23800
23809
  } else if (fileType) { // string type, e.g. kml, geojson
23801
23810
  content = cli.readFile(path, encoding || 'utf-8', cache);
23802
23811
 
23812
+ } else if (getFileExtension(path) == 'gz') {
23813
+ var pathgz = path;
23814
+ path = pathgz.replace(/\.gz$/, '');
23815
+ fileType = guessInputFileType(path);
23816
+ if (!fileType) {
23817
+ stop('Unrecognized file type:', path);
23818
+ }
23819
+ // TODO: consider using a temp file, to support incremental reading
23820
+ content = require('zlib').gunzipSync(cli.readFile(pathgz));
23821
+
23803
23822
  } else { // type can't be inferred from filename -- try reading as text
23804
23823
  content = cli.readFile(path, encoding || 'utf-8', cache);
23805
23824
  fileType = guessInputContentType(content);
package/www/page.css CHANGED
@@ -251,6 +251,11 @@ body {
251
251
  left: 0;
252
252
  }
253
253
 
254
+ .error-title {
255
+ font-weight: bold;
256
+ margin-bottom: 4px;
257
+ }
258
+
254
259
  div.error-box {
255
260
  margin-top: 55px;
256
261
  overflow: auto;
@@ -1249,8 +1254,6 @@ div.basemap-style-btn.active img {
1249
1254
  /* cursor: pointer; */
1250
1255
  background: #cc6acc;
1251
1256
  pointer-events: all;
1252
- width: 6px;
1253
- height: 6px;
1254
1257
  }
1255
1258
 
1256
1259
  /* Simplification control ------------ */