mapshaper 0.6.110 → 0.6.112

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.110",
3
+ "version": "0.6.112",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -1937,8 +1937,20 @@
1937
1937
  .on('paste', onpaste);
1938
1938
  area.node().addEventListener('paste', onpaste);
1939
1939
  function ondrop(e) {
1940
+ var files = e.dataTransfer.files;
1941
+ var types = e.dataTransfer.types;
1940
1942
  block(e);
1941
- cb(e.dataTransfer.files);
1943
+ if (files.length) {
1944
+ cb(files);
1945
+ } else if (types.includes('text/uri-list')) {
1946
+ cb(e.dataTransfer.getData('text/uri-list').split(','));
1947
+ } else if (types.includes('text/html')) {
1948
+ // drag-dropping a highlighted link may pull in a chunk of html
1949
+ var urls = e.dataTransfer.getData('text/html').match(/https?:[^"']+/);
1950
+ if (urls.length) {
1951
+ cb(urls);
1952
+ }
1953
+ }
1942
1954
  }
1943
1955
  function onpaste(e) {
1944
1956
  var types = Array.from(e.clipboardData.types || []).join(',');
@@ -1955,15 +1967,18 @@
1955
1967
  // Single files of all types are pasted as a string and an image/png
1956
1968
  // Multiple files are pasted as a string containing a list of file names
1957
1969
 
1958
- // import text from the clipboard (could be csv, json, etc)
1970
+ // import text from the clipboard (could be csv, json, a url, etc)
1959
1971
  // formatted text can be available as both text/plain and text/html (e.g.
1960
1972
  // a JSON data object copied from a GitHub issue).
1961
1973
  //
1962
1974
  if (types.includes('text/plain')) {
1963
- // if (types == 'text/plain') {
1964
1975
  // text from clipboard (supported by Chrome, FF, Safari)
1965
1976
  // TODO: handle FF case of string containing multiple file names.
1966
- files = [pastedTextToFile(e.clipboardData.getData('text/plain'))];
1977
+ var str = e.clipboardData.getData('text/plain');
1978
+ if (isUrl(str)) {
1979
+ return cb(str.split(','));
1980
+ }
1981
+ files = [pastedTextToFile(str)];
1967
1982
  } else {
1968
1983
  files = items.map(function(item) {
1969
1984
  return item.kind == 'file' && !item.type.includes('image') ?
@@ -1997,6 +2012,10 @@
1997
2012
  return new File([blob], name);
1998
2013
  }
1999
2014
 
2015
+ function isUrl(str) {
2016
+ return /^https?:\/\//.test(str);
2017
+ }
2018
+
2000
2019
  // @el DOM element for select button
2001
2020
  // @cb function(<FileList>)
2002
2021
  function FileChooser(el, cb) {
@@ -2040,7 +2059,7 @@
2040
2059
 
2041
2060
  var submitBtn = new SimpleButton('#import-options .submit-btn').on('click', importQueuedFiles);
2042
2061
  new SimpleButton('#import-options .cancel-btn').on('click', gui.clearMode);
2043
- new DropControl(gui, 'body', receiveFilesWithOption);
2062
+ new DropControl(gui, 'body', receiveDroppedItems);
2044
2063
  new FileChooser('#import-options .add-btn', receiveFilesWithOption);
2045
2064
  new FileChooser('#add-file-btn', receiveFiles);
2046
2065
  new SimpleButton('#add-empty-btn').on('click', function() {
@@ -2056,7 +2075,7 @@
2056
2075
 
2057
2076
  function turnOn() {
2058
2077
  if (manifestFiles.length > 0) {
2059
- downloadFiles(manifestFiles, true);
2078
+ downloadFiles(manifestFiles);
2060
2079
  manifestFiles = [];
2061
2080
  } else if (model.isEmpty()) {
2062
2081
  showImportMenu();
@@ -2157,6 +2176,14 @@
2157
2176
  submitBtn.classed('disabled', queuedFiles.length === 0);
2158
2177
  }
2159
2178
 
2179
+ function receiveDroppedItems(arr) {
2180
+ if (utils$1.isString(arr[0])) { // assume array of URLs
2181
+ downloadFiles(arr);
2182
+ } else { // assume array of Files
2183
+ receiveFilesWithOption(arr);
2184
+ }
2185
+ }
2186
+
2160
2187
  function receiveFilesWithOption(files) {
2161
2188
  var quickView = !El('.advanced-import-options').node().checked;
2162
2189
  receiveFiles(files, quickView);
@@ -2312,9 +2339,8 @@
2312
2339
 
2313
2340
  function prepFilesForDownload(names) {
2314
2341
  var items = names.map(function(name) {
2315
- var isUrl = /:\/\//.test(name);
2316
2342
  var item = {name: name};
2317
- if (isUrl) {
2343
+ if (isUrl(name)) {
2318
2344
  item.url = name;
2319
2345
  item.basename = GUI.getUrlFilename(name);
2320
2346
 
@@ -2667,7 +2693,7 @@
2667
2693
  var lyr;
2668
2694
  if (memo) return memo; // already found a match
2669
2695
  // try to match import filename of this dataset
2670
- if (d.info.input_files[0] == src) return d;
2696
+ if (d.info?.input_files?.[0] == src) return d;
2671
2697
  // try to match name of a layer in this dataset
2672
2698
  lyr = utils$1.find(d.layers, function(lyr) {return lyr.name == src;});
2673
2699
  return lyr ? internal.isolateLayer(lyr, d) : null;
@@ -4176,13 +4202,6 @@
4176
4202
  flags.union || flags.mosaic || flags.snap || flags.clean || flags.drop || false;
4177
4203
  }
4178
4204
 
4179
- // check for operations that may change the number of self intersections in the
4180
- // target layer.
4181
- function intersectionsMayHaveChanged(flags) {
4182
- return arcsMayHaveChanged(flags) || flags.select || flags['merge-layers'] ||
4183
- flags.filter || flags.dissolve || flags.dissolve2;
4184
- }
4185
-
4186
4205
  // Test if an update allows hover popup to stay open
4187
4206
  function popupCanStayOpen(flags) {
4188
4207
  // keeping popup open after -drop geometry causes problems...
@@ -4207,7 +4226,7 @@
4207
4226
  return c;
4208
4227
  }
4209
4228
 
4210
- function RepairControl(gui) {
4229
+ function IntersectionControl(gui) {
4211
4230
  var map = gui.map,
4212
4231
  model = gui.model,
4213
4232
  el = gui.container.findChild(".intersection-display"),
@@ -4243,12 +4262,24 @@
4243
4262
  gui.session.simplificationRepair();
4244
4263
  });
4245
4264
 
4265
+ // check for operations that may change the number of self intersections in the
4266
+ // target layer.
4267
+ function intersectionsMayHaveChanged(flags) {
4268
+ return arcsMayHaveChanged(flags) || flags.select || flags.repair ||
4269
+ flags.clean || flags.filter || flags.dissolve || flags.dissolve2 ||
4270
+ flags['merge-layers'] || flags.simplify_method || flags.simplify ||
4271
+ flags.split;
4272
+ }
4273
+
4274
+
4246
4275
  model.on('update', function(e) {
4247
- var needRefresh = e.flags.simplify_method || e.flags.simplify ||
4248
- e.flags.repair || e.flags.clean || e.flags.select || intersectionsMayHaveChanged(e.flags);
4276
+ var needRefresh = intersectionsMayHaveChanged(e.flags);
4249
4277
  if (!intersectionsAreOn()) {
4250
4278
  reset();
4251
4279
  } else if (needRefresh) {
4280
+ // don't continue to show old intersections when map redraws
4281
+ map.setIntersectionLayer(null, null, false);
4282
+ // regenerate intersections and redraw map
4252
4283
  updateAsync();
4253
4284
  } else if (e.flags.simplify_amount) {
4254
4285
  // slider is being dragged - hide readout and dots, retain data
@@ -4256,7 +4287,7 @@
4256
4287
  } else {
4257
4288
  // keep displaying the current intersections
4258
4289
  }
4259
- });
4290
+ }, 10);
4260
4291
 
4261
4292
  function updateRepairBtn() {
4262
4293
  if (intersectionsAreOn() && gui.getMode() == 'simplify' &&
@@ -4340,7 +4371,7 @@
4340
4371
  }
4341
4372
  }
4342
4373
 
4343
- utils$1.inherit(RepairControl, EventDispatcher);
4374
+ utils$1.inherit(IntersectionControl, EventDispatcher);
4344
4375
 
4345
4376
  async function saveFileContentToClipboard(content) {
4346
4377
  var str = utils$1.isString(content) ? content : content.toString();
@@ -5063,7 +5094,7 @@
5063
5094
  var lyr = o.layer;
5064
5095
  var opts = {
5065
5096
  show_source: layerCount < 5,
5066
- pinnable: pinnableCount > 1 && isPinnable(lyr)
5097
+ pinnable: pinnableCount > 0 && isPinnable(lyr)
5067
5098
  };
5068
5099
  var html, element;
5069
5100
  html = renderLayer(lyr, o.dataset, opts);
@@ -6294,6 +6325,18 @@
6294
6325
  }
6295
6326
  }
6296
6327
 
6328
+ function time(slug) {
6329
+ if (useDebug()) {
6330
+ console.time(slug);
6331
+ }
6332
+ }
6333
+
6334
+ function timeEnd(slug) {
6335
+ if (useDebug()) {
6336
+ console.timeEnd(slug);
6337
+ }
6338
+ }
6339
+
6297
6340
  function printError(err) {
6298
6341
  var msg;
6299
6342
  if (!LOGGING) return;
@@ -7457,8 +7500,13 @@
7457
7500
  if (len >= 2) {
7458
7501
  first = str.charAt(0);
7459
7502
  last = str.charAt(len-1);
7460
- if (first == '"' && last == '"' && !str.includes('","') ||
7461
- first == "'" && last == "'" && !str.includes("','")) {
7503
+ // if (first == '"' && last == '"' && !str.includes('","') ||
7504
+ // first == "'" && last == "'" && !str.includes("','")) {
7505
+ // don't strip if there are unescaped quotes
7506
+ // e.g. expressions that start and end with quotes
7507
+ // e.g. comma-separated list of quoted values
7508
+ if (first == '"' && last == '"' && !/[^\\]"./.test(str) ||
7509
+ first == "'" && last == "'" && !/[^\\]'./.test(str)) {
7462
7510
  str = str.substr(1, len-2);
7463
7511
  // remove string escapes
7464
7512
  str = str.replace(first == '"' ? /\\(?=")/g : /\\(?=')/g, '');
@@ -10100,6 +10148,9 @@
10100
10148
  // special overlay: shape editing mode
10101
10149
  lyr = getOverlayLayer(activeLyr, hitData.ids);
10102
10150
  lyr.gui.style = getLineEditingStyle(hitData);
10151
+ if (activeLyr.geometry_type == 'polygon') {
10152
+ lyr.gui.style.fillColor = hoverFill;
10153
+ }
10103
10154
  return [lyr];
10104
10155
  }
10105
10156
  layers = [];
@@ -13014,7 +13065,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13014
13065
  });
13015
13066
 
13016
13067
  // Update display of segment intersections
13017
- this.setIntersectionLayer = function(lyr, dataset) {
13068
+ this.setIntersectionLayer = function(lyr, dataset, redraw) {
13018
13069
  if (lyr == _intersectionLyr) return; // no change
13019
13070
  if (lyr) {
13020
13071
  enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
@@ -13024,7 +13075,9 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13024
13075
  _intersectionLyr = null;
13025
13076
  }
13026
13077
  // TODO: try to avoid redrawing layers twice (in some situations)
13027
- drawLayers();
13078
+ if (redraw !== false) {
13079
+ drawLayers();
13080
+ }
13028
13081
  };
13029
13082
 
13030
13083
  this.pixelCoordsToLngLatCoords = function(x, y) {
@@ -13996,7 +14049,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13996
14049
  // }
13997
14050
 
13998
14051
  new AlertControl(gui);
13999
- new RepairControl(gui);
14052
+ new IntersectionControl(gui);
14000
14053
  new SimplifyControl(gui);
14001
14054
  new ImportControl(gui, importOpts);
14002
14055
  new ExportControl(gui);