mapshaper 0.6.23 → 0.6.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.23",
3
+ "version": "0.6.25",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -44,7 +44,6 @@
44
44
  "@tmcw/togeojson": "^5.6.0",
45
45
  "@xmldom/xmldom": "^0.8.6",
46
46
  "adm-zip": "^0.5.9",
47
- "bson": "^4.7.0",
48
47
  "commander": "7.0.0",
49
48
  "cookies": "^0.8.0",
50
49
  "d3-color": "3.1.0",
@@ -58,7 +57,7 @@
58
57
  "idb-keyval": "^6.2.0",
59
58
  "kdbush": "^3.0.0",
60
59
  "mproj": "0.0.35",
61
- "msgpackr": "^1.8.1",
60
+ "msgpackr": "^1.8.5",
62
61
  "opn": "^5.3.0",
63
62
  "rw": "~1.3.3",
64
63
  "sync-request": "5.0.0",
package/www/index.html CHANGED
@@ -118,6 +118,7 @@
118
118
  <div>
119
119
  <div class="select-btn btn dialog-btn">Select</div>
120
120
  <div class="clip-btn btn dialog-btn">Clip</div>
121
+ <div class="erase-btn btn dialog-btn">Erase</div>
121
122
  <div class="info-btn btn dialog-btn">Info</div>
122
123
  <!-- <div class="zoom-btn btn dialog-btn">Zoom In</div>
123
124
  <div class="rectangle-btn btn dialog-btn">Rectangle</div> -->
@@ -1437,7 +1437,9 @@
1437
1437
  closeMenu(100);
1438
1438
  }).text('restore');
1439
1439
  El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
1440
- var buf = await idb.get(item.id);
1440
+ var obj = await idb.get(item.id);
1441
+ await internal.applyCompression(obj, {consume: true});
1442
+ var buf = internal.pack(obj);
1441
1443
  saveBlobToLocalFile('mapshaper_snapshot.msx', new Blob([buf]));
1442
1444
  }).text('export');
1443
1445
  El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
@@ -1485,20 +1487,24 @@
1485
1487
  }
1486
1488
 
1487
1489
  async function saveSnapshot(gui) {
1488
- var buf = await captureSnapshot(gui);
1490
+ var obj = await captureSnapshot(gui);
1491
+ // storing an unpacked object is usually a bit faster (~20%)
1492
+ // note: we don't know the size of unpacked snapshot objects
1493
+ // obj = internal.pack(obj);
1489
1494
  var entryId = String(++snapshotCount).padStart(3, '0');
1490
1495
  var snapshotId = sessionId + '_' + entryId; // e.g. session_d89fw_001
1496
+ var size = obj.length;
1491
1497
  var entry = {
1492
1498
  created: Date.now(),
1493
1499
  session: sessionId,
1494
1500
  id: snapshotId,
1495
1501
  name: snapshotCount + '.',
1496
1502
  number: snapshotCount,
1497
- size: buf.length,
1498
- display_size: formatSize(buf.length)
1503
+ size: size,
1504
+ display_size: formatSize(size)
1499
1505
  };
1500
1506
 
1501
- await idb.set(entry.id, buf);
1507
+ await idb.set(entry.id, obj);
1502
1508
  await addToIndex(entry);
1503
1509
  renderMenu();
1504
1510
  }
@@ -1507,9 +1513,8 @@
1507
1513
  function formatSize(bytes) {
1508
1514
  var kb = Math.round(bytes / 1000);
1509
1515
  var mb = (bytes / 1e6).toFixed(1);
1510
- if (kb < 990) {
1511
- return kb + 'kB';
1512
- }
1516
+ if (!kb) return '';
1517
+ if (kb < 990) return kb + 'kB';
1513
1518
  return mb + 'MB';
1514
1519
  }
1515
1520
 
@@ -1531,13 +1536,13 @@
1531
1536
  }
1532
1537
 
1533
1538
  async function restoreSnapshotById(id, gui) {
1534
- var buf = await idb.get(id);
1535
- if (!buf) {
1536
- console.log('Snapshot not available:', id);
1537
- return;
1539
+ var data;
1540
+ try {
1541
+ data = await internal.restoreSessionData(await idb.get(id));
1542
+ } catch(e) {
1543
+ console.error(e);
1544
+ stop$1('Snapshot is not available');
1538
1545
  }
1539
- var data = await internal.unpackSession(buf);
1540
- buf = null;
1541
1546
  gui.model.clear();
1542
1547
  importDatasets(data.datasets, gui);
1543
1548
  gui.clearMode();
@@ -1550,7 +1555,7 @@
1550
1555
  if (buf instanceof ArrayBuffer) {
1551
1556
  buf = new Uint8Array(buf);
1552
1557
  }
1553
- var data = await internal.unpackSession(buf);
1558
+ var data = await internal.unpackSessionData(buf);
1554
1559
  importDatasets(data.datasets, gui);
1555
1560
  }
1556
1561
 
@@ -1573,7 +1578,7 @@
1573
1578
  // console.timeEnd('msx')
1574
1579
  delete lyr.active;
1575
1580
  obj.gui = getGuiState(gui);
1576
- return internal.pack(obj);
1581
+ return obj;
1577
1582
  }
1578
1583
 
1579
1584
  // TODO: capture gui state information to allow restoring more of the UI
@@ -3040,21 +3045,13 @@
3040
3045
  }
3041
3046
 
3042
3047
  function getHistory() {
3043
- var hist;
3044
- try {
3045
- hist = JSON.parse(window.localStorage.getItem('console_history'));
3046
- } catch(e) {
3047
- }
3048
- return hist && hist.length > 0 ? hist : [];
3048
+ return GUI.getSavedValue('console_history') || [];
3049
3049
  }
3050
3050
 
3051
3051
  function saveHistory() {
3052
- try {
3053
- history = history.filter(Boolean); // TODO: fix condition that leaves a blank line on the history
3054
- if (history.length) {
3055
- window.localStorage.setItem('console_history', JSON.stringify(history.slice(-50)));
3056
- }
3057
- } catch(e) {
3052
+ history = history.filter(Boolean); // TODO: fix condition that leaves a blank line on the history
3053
+ if (history.length > 0) {
3054
+ GUI.setSavedValue('console_history', history.slice(-100));
3058
3055
  }
3059
3056
  }
3060
3057
 
@@ -3678,7 +3675,13 @@
3678
3675
  gui.addMode('export', turnOn, turnOff, exportBtn);
3679
3676
  gui.keyboard.onMenuSubmit(menu, onExportClick);
3680
3677
  if (window.showSaveFilePicker) {
3681
- menu.findChild('#save-preference').css('display', 'inline-block');
3678
+ menu.findChild('#save-preference')
3679
+ .css('display', 'inline-block')
3680
+ .findChild('input')
3681
+ .on('change', function() {
3682
+ GUI.setSavedValue('choose-save-dir', this.checked);
3683
+ })
3684
+ .attr('checked', GUI.getSavedValue('choose-save-dir') || null);
3682
3685
  }
3683
3686
 
3684
3687
  function turnOn() {
@@ -3702,8 +3705,6 @@
3702
3705
 
3703
3706
  function onExportClick() {
3704
3707
  var layers = getSelectedLayers();
3705
- var chooseDir = menu.findChild('#save-preference input').node().checked;
3706
- GUI.setSavedValue('choose-save-dir', chooseDir);
3707
3708
  if (layers.length === 0) {
3708
3709
  return gui.alert('No layers were selected');
3709
3710
  }
@@ -8054,8 +8055,14 @@
8054
8055
  }
8055
8056
  });
8056
8057
 
8058
+ // add new field form
8059
+ if (editable) {
8060
+ renderNewRow(tableEl, rec, table);
8061
+ }
8062
+
8063
+ tableEl.appendTo(el);
8057
8064
  if (rows > 0) {
8058
- tableEl.appendTo(el);
8065
+ // tableEl.appendTo(el);
8059
8066
 
8060
8067
  tableEl.on('copy', function(e) {
8061
8068
  // remove leading or trailing tabs that sometimes get copied when
@@ -8075,15 +8082,26 @@
8075
8082
  el.html(utils$1.format('<div class="note">This %s is missing attribute data.</div>',
8076
8083
  table && table.getFields().length > 0 ? 'feature': 'layer'));
8077
8084
  }
8085
+
8086
+ if (editable) {
8087
+ var line = El('div').appendTo(el);
8088
+ El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
8089
+
8090
+ }).text('add field');
8091
+ }
8092
+ }
8093
+
8094
+ function renderNewRow(el, rec, table) {
8095
+
8078
8096
  }
8079
8097
 
8080
8098
  function renderRow(table, rec, key, type, editable) {
8081
- var rowHtml = '<td class="field-name">%s</td><td><span class="value">%s</span> </td>';
8082
8099
  var val = rec[key];
8083
8100
  var str = formatInspectorValue(val, type);
8101
+ var rowHtml = `<td class="field-name">${key}</td><td><span class="value">${utils$1.htmlEscape(str)}</span> </td>`;
8084
8102
  var cell = El('tr')
8085
8103
  .appendTo(table)
8086
- .html(utils$1.format(rowHtml, key, utils$1.htmlEscape(str)))
8104
+ .html(rowHtml)
8087
8105
  .findChild('.value');
8088
8106
  setFieldClass(cell, val, type);
8089
8107
  if (editable) {
@@ -9797,19 +9815,26 @@
9797
9815
  bx = t.bx,
9798
9816
  by = t.by;
9799
9817
  var x, y, xp, yp;
9818
+ var count = 0;
9800
9819
  if (!vec.hasNext()) return;
9801
- x = xp = round(vec.x * mx + bx);
9802
- y = yp = round(vec.y * my + by);
9820
+ x = round(vec.x * mx + bx);
9821
+ y = round(vec.y * my + by);
9803
9822
  ctx.moveTo(x, y);
9804
9823
  while (vec.hasNext()) {
9824
+ xp = x;
9825
+ yp = y;
9805
9826
  x = round(vec.x * mx + bx);
9806
9827
  y = round(vec.y * my + by);
9807
9828
  if (x != xp || y != yp) {
9808
9829
  ctx.lineTo(x, y);
9809
- xp = x;
9810
- yp = y;
9830
+ count++;
9811
9831
  }
9812
9832
  }
9833
+ if (count === 0) {
9834
+ // draw a tiny line if all coords round to the same location,
9835
+ // so tiny shapes with strokes will consistently be drawn as dots,
9836
+ ctx.lineTo(x + 0.1, y);
9837
+ }
9813
9838
  }
9814
9839
 
9815
9840
  function roundToPix(x) {
@@ -10187,6 +10212,10 @@
10187
10212
  runCommand('-clip bbox=' + box.getDataCoords().join(','));
10188
10213
  });
10189
10214
 
10215
+ new SimpleButton(popup.findChild('.erase-btn')).on('click', function() {
10216
+ runCommand('-erase bbox=' + box.getDataCoords().join(','));
10217
+ });
10218
+
10190
10219
  gui.addMode('box_tool', turnOn, turnOff);
10191
10220
 
10192
10221
  gui.on('interaction_mode_change', function(e) {