mapshaper 0.5.117 → 0.5.118

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,7 @@
1
+ v0.5.118
2
+ * Added -comment command, as a way to add inline comments in long sequences of commands.
3
+ * Added support for importing .cpg files (Shapefile text encoding) in the web UI.
4
+
1
5
  v0.5.117
2
6
  * Support reading DBF files larger than 2GB (command line program only).
3
7
 
package/bin/mapshaper-gui CHANGED
@@ -247,6 +247,7 @@ function expandShapefiles(files) {
247
247
  if (isUrl(f)) return; // TODO: try to load aux files from URLs
248
248
  addAuxFile(files, f, '.dbf');
249
249
  addAuxFile(files, f, '.prj');
250
+ addAuxFile(files, f, '.shx');
250
251
  addAuxFile(files, f, '.cpg');
251
252
  });
252
253
  return files;
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.117";
3
+ var VERSION = "0.5.118";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -17215,7 +17215,7 @@ ${svg}
17215
17215
  function guessInputFileType(file) {
17216
17216
  var ext = getFileExtension(file || '').toLowerCase(),
17217
17217
  type = null;
17218
- if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml') {
17218
+ if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
17219
17219
  type = ext;
17220
17220
  } else if (/json$/.test(ext)) {
17221
17221
  type = 'json';
@@ -21088,6 +21088,10 @@ ${svg}
21088
21088
  parser.command('colors')
21089
21089
  .describe('print list of color scheme names');
21090
21090
 
21091
+ parser.command('comment')
21092
+ .describe('add a comment to the sequence of commands')
21093
+ .flag('multi_arg');
21094
+
21091
21095
  parser.command('encodings')
21092
21096
  .describe('print list of supported text encodings (for .dbf import)');
21093
21097
 
@@ -21516,11 +21520,12 @@ ${svg}
21516
21520
 
21517
21521
  // Show a sample of decoded text if non-ascii-range text has been found
21518
21522
  if (encoding && samples.length > 0) {
21523
+ msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
21524
+ message(msg);
21519
21525
  msg = decodeSamples(encoding, samples);
21520
21526
  msg = formatStringsAsGrid(msg.split('\n'));
21521
21527
  msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
21522
- msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "") + msg;
21523
- message(msg);
21528
+ verbose(msg);
21524
21529
  }
21525
21530
  return encoding;
21526
21531
  }
@@ -23612,6 +23617,10 @@ ${svg}
23612
23617
  if (obj.prj) {
23613
23618
  dataset.info.prj = obj.prj.content;
23614
23619
  }
23620
+ if (obj.cpg) {
23621
+ // TODO: consider using the input encoding as the default output encoding
23622
+ dataset.info.cpg = obj.cpg.content;
23623
+ }
23615
23624
  return dataset;
23616
23625
  }
23617
23626
 
@@ -24061,6 +24070,7 @@ ${svg}
24061
24070
  clearStash(); // prevent errors from overwriting stash
24062
24071
  stashVar('current_command', cmd.name);
24063
24072
  stashVar('DEBUG', job.settings.DEBUG || cmd.debug);
24073
+ stashVar('VERBOSE', job.settings.VERBOSE || cmd.verbose);
24064
24074
  stashVar('QUIET', job.settings.QUIET || cmd.quiet);
24065
24075
  stashVar('defs', job.defs);
24066
24076
  stashVar('input_files', job.input_files);
@@ -30487,6 +30497,9 @@ ${svg}
30487
30497
  targetDataset.arcs = mergedDataset.arcs;
30488
30498
  // dissolve clip layer shapes (to remove overlaps and other topological issues
30489
30499
  // that might confuse the clipping function)
30500
+ // use a data-free copy of the clip lyr, so data records are not dissolved
30501
+ // (this avoids triggering an unnecessary and expensive DBF read operation in some cases).
30502
+ clipLyr = utils.defaults({data: null}, clipLyr);
30490
30503
  clipLyr = dissolvePolygonLayer2(clipLyr, mergedDataset, {quiet: true, silent: true});
30491
30504
 
30492
30505
  } else {
@@ -30888,6 +30901,8 @@ ${svg}
30888
30901
  getColorizerFunction: getColorizerFunction
30889
30902
  });
30890
30903
 
30904
+ cmd.comment = function() {}; // no-op, so -comment doesn't trigger a parsing error
30905
+
30891
30906
  function expressionUsesGeoJSON(exp) {
30892
30907
  return exp.includes('this.geojson');
30893
30908
  }
@@ -39802,7 +39817,7 @@ ${svg}
39802
39817
  function commandAcceptsEmptyTarget(name) {
39803
39818
  return name == 'graticule' || name == 'i' || name == 'help' ||
39804
39819
  name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
39805
- name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
39820
+ name == 'include' || name == 'print' || name == 'comment' || name == 'if' || name == 'elif' ||
39806
39821
  name == 'else' || name == 'endif';
39807
39822
  }
39808
39823
 
@@ -39910,6 +39925,9 @@ ${svg}
39910
39925
  } else if (name == 'colorizer') {
39911
39926
  outputLayers = cmd.colorizer(opts);
39912
39927
 
39928
+ } else if (name == 'comment') {
39929
+ // no-op
39930
+
39913
39931
  } else if (name == 'dashlines') {
39914
39932
  applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
39915
39933
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.117",
3
+ "version": "0.5.118",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/elements.css CHANGED
@@ -67,10 +67,10 @@ div.tip {
67
67
  z-index: 500;
68
68
  cursor: pointer;
69
69
  text-align: center;
70
- font-size: 13px;
70
+ font-size: 14px;
71
71
  line-height: 1;
72
72
  font-weight: normal;
73
- color: #799FCB;
73
+ color: #1385B7;
74
74
  }
75
75
 
76
76
  .tip-button .tip-anchor {
Binary file
package/www/index.html CHANGED
@@ -130,7 +130,8 @@
130
130
 
131
131
  <div class="export-options main-area popup-dialog">
132
132
  <div class="info-box">
133
- <h3>Export menu</h3>
133
+ <div class="close2-btn"></div>
134
+ <h3>Export options</h3>
134
135
  <div style="height:3px"></div>
135
136
  <div class=export-layers>
136
137
  <h4 class="menu-title">Layers</h4>
@@ -140,22 +141,23 @@
140
141
  <div class="export-formats option-menu">
141
142
  </div>
142
143
 
143
- <div class="option-menu"><input type="text" class="advanced-options" placeholder="export options" /><div class="tip-button">?<div class="tip-anchor">
144
+ <div class="option-menu"><input type="text" class="advanced-options" placeholder="command line options" /><div class="tip-button">?<div class="tip-anchor">
144
145
  <div class="tip">Enter options from the command line interface for the -o command. Examples: "bbox" "no-quantization"
145
146
  "precision=0.001"</div></div></div></div>
146
- <div class="cancel-btn btn dialog-btn">Cancel</div>
147
+ <!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
147
148
  <div class="save-btn btn dialog-btn">Export</div>
148
149
  </div>
149
150
  </div>
150
151
 
151
152
  <div class="basemap-options main-area popup-dialog">
152
153
  <div class="info-box">
154
+ <div class="close2-btn"></div>
153
155
  <h3>Basemap options</h3>
154
156
  <p class="basemap-note">Your data will be displayed using the Mercator projection.</p>
155
157
  <p class="basemap-warning"></p>
156
158
  <div class="basemap-styles"></div>
157
159
  <div>
158
- <div class="close-btn btn dialog-btn">Close</div>
160
+ <!-- <div class="close-btn btn dialog-btn">Close</div> -->
159
161
  <div class="clear-btn btn dialog-btn disabled">Clear</div>
160
162
  <div class="fade-btn btn dialog-btn disabled">Fade</div>
161
163
  <!-- <div class="hide-btn btn dialog-btn disabled">Hide</div> -->
@@ -165,7 +167,8 @@
165
167
 
166
168
  <div class="simplify-options main-area popup-dialog">
167
169
  <div class="info-box">
168
- <h3>Simplification menu</h3>
170
+ <div class="close2-btn"></div>
171
+ <h3>Simplification</h3>
169
172
  <div class="option-menu">
170
173
  <div><label for="import-retain-opt"><input type="checkbox" class="checkbox import-retain-opt"/>prevent shape removal</label>
171
174
  <div class="tip-button">?<div class="tip-anchor">
@@ -208,7 +211,7 @@ a smoother appearance.</div></div></div></div>
208
211
  </div> <!-- option menu -->
209
212
 
210
213
  <div>
211
- <div class="cancel-btn btn dialog-btn">Cancel</div>
214
+ <!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
212
215
  <div class="submit-btn btn dialog-btn">Apply</div>
213
216
  </div>
214
217
  </div> <!-- .info-box -->
@@ -310,7 +310,6 @@
310
310
 
311
311
  // tests if filename is a type that can be used
312
312
  GUI.isReadableFileType = function(filename) {
313
- var ext = internal.getFileExtension(filename).toLowerCase();
314
313
  return !!internal.guessInputFileType(filename) || internal.couldBeDsvFile(filename) ||
315
314
  internal.isZipFile(filename);
316
315
  };
@@ -1354,7 +1353,6 @@
1354
1353
  }
1355
1354
  }
1356
1355
  model.updated({select: true});
1357
-
1358
1356
  }
1359
1357
 
1360
1358
  function clearQueuedFiles() {
@@ -1451,9 +1449,8 @@
1451
1449
  }
1452
1450
 
1453
1451
 
1454
- // TODO: support .cpg
1455
1452
  function isShapefilePart(name) {
1456
- return /\.(shp|shx|dbf|prj)$/i.test(name);
1453
+ return /\.(shp|shx|dbf|prj|cpg)$/i.test(name);
1457
1454
  }
1458
1455
 
1459
1456
  function readImportOpts() {
@@ -2131,7 +2128,7 @@
2131
2128
 
2132
2129
  // init settings menu
2133
2130
  new SimpleButton(menu.findChild('.submit-btn').addClass('default-btn')).on('click', onSubmit);
2134
- new SimpleButton(menu.findChild('.cancel-btn')).on('click', function() {
2131
+ new SimpleButton(menu.findChild('.close2-btn')).on('click', function() {
2135
2132
  if (el.visible()) {
2136
2133
  // cancel just hides menu if slider is visible
2137
2134
  menu.hide();
@@ -3159,7 +3156,7 @@
3159
3156
  var layersArr = [];
3160
3157
  var toggleBtn = null; // checkbox <input> for toggling layer selection
3161
3158
  var exportBtn = gui.container.findChild('.export-btn');
3162
- new SimpleButton(menu.findChild('.cancel-btn')).on('click', gui.clearMode);
3159
+ new SimpleButton(menu.findChild('.close2-btn')).on('click', gui.clearMode);
3163
3160
 
3164
3161
  if (!GUI.exportIsSupported()) {
3165
3162
  exportBtn.on('click', function() {
@@ -9764,7 +9761,7 @@
9764
9761
  var menu = gui.container.findChild('.basemap-options');
9765
9762
  // var hideBtn = new SimpleButton(menu.findChild('.hide-btn'));
9766
9763
  var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
9767
- var closeBtn = new SimpleButton(menu.findChild('.close-btn'));
9764
+ var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
9768
9765
  var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
9769
9766
  var list = menu.findChild('.basemap-styles');
9770
9767
  var container = gui.container.findChild('.basemap-container');
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.117";
3
+ var VERSION = "0.5.118";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -17215,7 +17215,7 @@ ${svg}
17215
17215
  function guessInputFileType(file) {
17216
17216
  var ext = getFileExtension(file || '').toLowerCase(),
17217
17217
  type = null;
17218
- if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml') {
17218
+ if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
17219
17219
  type = ext;
17220
17220
  } else if (/json$/.test(ext)) {
17221
17221
  type = 'json';
@@ -21088,6 +21088,10 @@ ${svg}
21088
21088
  parser.command('colors')
21089
21089
  .describe('print list of color scheme names');
21090
21090
 
21091
+ parser.command('comment')
21092
+ .describe('add a comment to the sequence of commands')
21093
+ .flag('multi_arg');
21094
+
21091
21095
  parser.command('encodings')
21092
21096
  .describe('print list of supported text encodings (for .dbf import)');
21093
21097
 
@@ -21516,11 +21520,12 @@ ${svg}
21516
21520
 
21517
21521
  // Show a sample of decoded text if non-ascii-range text has been found
21518
21522
  if (encoding && samples.length > 0) {
21523
+ msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
21524
+ message(msg);
21519
21525
  msg = decodeSamples(encoding, samples);
21520
21526
  msg = formatStringsAsGrid(msg.split('\n'));
21521
21527
  msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
21522
- msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "") + msg;
21523
- message(msg);
21528
+ verbose(msg);
21524
21529
  }
21525
21530
  return encoding;
21526
21531
  }
@@ -23612,6 +23617,10 @@ ${svg}
23612
23617
  if (obj.prj) {
23613
23618
  dataset.info.prj = obj.prj.content;
23614
23619
  }
23620
+ if (obj.cpg) {
23621
+ // TODO: consider using the input encoding as the default output encoding
23622
+ dataset.info.cpg = obj.cpg.content;
23623
+ }
23615
23624
  return dataset;
23616
23625
  }
23617
23626
 
@@ -24061,6 +24070,7 @@ ${svg}
24061
24070
  clearStash(); // prevent errors from overwriting stash
24062
24071
  stashVar('current_command', cmd.name);
24063
24072
  stashVar('DEBUG', job.settings.DEBUG || cmd.debug);
24073
+ stashVar('VERBOSE', job.settings.VERBOSE || cmd.verbose);
24064
24074
  stashVar('QUIET', job.settings.QUIET || cmd.quiet);
24065
24075
  stashVar('defs', job.defs);
24066
24076
  stashVar('input_files', job.input_files);
@@ -30487,6 +30497,9 @@ ${svg}
30487
30497
  targetDataset.arcs = mergedDataset.arcs;
30488
30498
  // dissolve clip layer shapes (to remove overlaps and other topological issues
30489
30499
  // that might confuse the clipping function)
30500
+ // use a data-free copy of the clip lyr, so data records are not dissolved
30501
+ // (this avoids triggering an unnecessary and expensive DBF read operation in some cases).
30502
+ clipLyr = utils.defaults({data: null}, clipLyr);
30490
30503
  clipLyr = dissolvePolygonLayer2(clipLyr, mergedDataset, {quiet: true, silent: true});
30491
30504
 
30492
30505
  } else {
@@ -30888,6 +30901,8 @@ ${svg}
30888
30901
  getColorizerFunction: getColorizerFunction
30889
30902
  });
30890
30903
 
30904
+ cmd.comment = function() {}; // no-op, so -comment doesn't trigger a parsing error
30905
+
30891
30906
  function expressionUsesGeoJSON(exp) {
30892
30907
  return exp.includes('this.geojson');
30893
30908
  }
@@ -39802,7 +39817,7 @@ ${svg}
39802
39817
  function commandAcceptsEmptyTarget(name) {
39803
39818
  return name == 'graticule' || name == 'i' || name == 'help' ||
39804
39819
  name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
39805
- name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
39820
+ name == 'include' || name == 'print' || name == 'comment' || name == 'if' || name == 'elif' ||
39806
39821
  name == 'else' || name == 'endif';
39807
39822
  }
39808
39823
 
@@ -39910,6 +39925,9 @@ ${svg}
39910
39925
  } else if (name == 'colorizer') {
39911
39926
  outputLayers = cmd.colorizer(opts);
39912
39927
 
39928
+ } else if (name == 'comment') {
39929
+ // no-op
39930
+
39913
39931
  } else if (name == 'dashlines') {
39914
39932
  applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
39915
39933
 
package/www/page.css CHANGED
@@ -222,7 +222,7 @@ body {
222
222
  }
223
223
 
224
224
  .export-options .option-menu .advanced-options {
225
- width: 175px;
225
+ width: 195px;
226
226
  }
227
227
 
228
228
  /* --- Main area ------------- */
@@ -456,11 +456,12 @@ body.dragover #import-options-drop-area .drop-area {
456
456
  .info-box,.popup {
457
457
  border-radius: 9px;
458
458
  /* border: 1px solid #ddd; */
459
- box-shadow: 0 4px 6px rgba(0,0,0,0.35);
459
+ box-shadow: 0 3px 6px rgba(0,0,0,0.35);
460
460
  background-color: #fff;
461
461
  }
462
462
 
463
463
  .info-box {
464
+ min-width: 230px;
464
465
  word-wrap: break-word;
465
466
  text-align: left;
466
467
  margin-top: 12px;
@@ -472,13 +473,16 @@ body.dragover #import-options-drop-area .drop-area {
472
473
  }
473
474
 
474
475
  .info-box h3 {
475
- font-size: 1.2em;
476
+ font-size: 19px;
477
+ line-height: 1.1;
476
478
  padding: 0;
477
- margin: 0 0 0.2em 0;
479
+ margin: 0 0 0.3em 0;
480
+ font-weight: normal;
478
481
  }
479
482
 
480
483
  .info-box h4 {
481
484
  font-size: 1em;
485
+ font-weight: normal;
482
486
  margin: 0 0 1px 0;
483
487
  }
484
488
 
@@ -491,9 +495,11 @@ body.dragover #import-options-drop-area .drop-area {
491
495
  padding: 0 0 9px 0;
492
496
  }
493
497
 
494
- .option-menu input {
498
+ .option-menu input[type="radio"],
499
+ .option-menu input[type="checkbox"]
500
+ {
495
501
  position: relative;
496
- top: 2px;
502
+ top: 1px;
497
503
  width: 12px;
498
504
  height: 12px;
499
505
  }
@@ -720,6 +726,28 @@ body.simplify .layer-control-btn {
720
726
 
721
727
  img.close-btn {
722
728
  opacity: 0.2;
729
+ position: absolute;
730
+ top: 8px;
731
+ right: 8px;
732
+ z-index: 2;
733
+ }
734
+
735
+ .close2-btn {
736
+ display: inline-block;
737
+ background-color: #f1f1f1;
738
+ background-image: url("images/close2.png");
739
+ background-size: cover;
740
+ float: right;
741
+ height: 18px;
742
+ width: 18px;
743
+ margin-top: 2px;
744
+ margin-right: -5px;
745
+ cursor: pointer;
746
+ border-radius: 4px;
747
+ }
748
+
749
+ .close2-btn:hover {
750
+ background-color: #ddd;
723
751
  }
724
752
 
725
753
  .pin-all img {
@@ -1016,6 +1044,7 @@ img.close-btn:hover,
1016
1044
  }
1017
1045
 
1018
1046
  .basemap-styles {
1047
+ margin: 0 -2px;
1019
1048
  white-space: nowrap;
1020
1049
  }
1021
1050
 
@@ -1040,19 +1069,14 @@ img.close-btn:hover,
1040
1069
 
1041
1070
  .basemap-styles > div:nth-child(even) {
1042
1071
  position: relative;
1043
- left: 6px;
1044
- margin-left: 2px;
1072
+ margin-left: 10px;
1045
1073
  }
1046
1074
 
1047
1075
  .basemap-style-btn img {
1048
1076
  display: block;
1049
- left: -2px;
1050
1077
  position: relative;
1051
1078
  border: 2px solid transparent;
1052
- /*width: 120px;
1053
- height: 90px;*/
1054
- width: 96px;
1055
- height: 72px;
1079
+ width: 108px;
1056
1080
  }
1057
1081
 
1058
1082
  div.basemap-style-btn.active img {
@@ -1064,6 +1088,10 @@ div.basemap-style-btn.active img {
1064
1088
  border: 2px solid #ead683;
1065
1089
  }
1066
1090
 
1091
+ .basemap-style-label {
1092
+ margin-left: 2px;
1093
+ }
1094
+
1067
1095
  .mapbox-improve-map {
1068
1096
  display: none;
1069
1097
  }