mapshaper 0.6.13 → 0.6.14

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.13";
3
+ var VERSION = "0.6.14";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -7066,15 +7066,6 @@
7066
7066
  transformPoints: transformPoints
7067
7067
  });
7068
7068
 
7069
- function runningInBrowser() {
7070
- return typeof window !== 'undefined' && typeof window.document !== 'undefined';
7071
- }
7072
-
7073
- var Env = /*#__PURE__*/Object.freeze({
7074
- __proto__: null,
7075
- runningInBrowser: runningInBrowser
7076
- });
7077
-
7078
7069
  function getPathSep(path) {
7079
7070
  // TODO: improve
7080
7071
  return path.indexOf('/') == -1 && path.indexOf('\\') != -1 ? '\\' : '/';
@@ -7127,6 +7118,11 @@
7127
7118
  return getPathBase(path) + '.' + ext;
7128
7119
  }
7129
7120
 
7121
+ function toLowerCaseExtension(name) {
7122
+ var ext = getFileExtension(name);
7123
+ return ext ? getPathBase(name) + '.' + ext.toLowerCase() : name;
7124
+ }
7125
+
7130
7126
  function getCommonFileBase(names) {
7131
7127
  return names.reduce(function(memo, name, i) {
7132
7128
  if (i === 0) {
@@ -7150,10 +7146,157 @@
7150
7146
  getFileExtension: getFileExtension,
7151
7147
  getPathBase: getPathBase,
7152
7148
  replaceFileExtension: replaceFileExtension,
7149
+ toLowerCaseExtension: toLowerCaseExtension,
7153
7150
  getCommonFileBase: getCommonFileBase,
7154
7151
  getOutputFileBase: getOutputFileBase
7155
7152
  });
7156
7153
 
7154
+ // Guess the type of a data file from file extension, or return null if not sure
7155
+ function guessInputFileType(file) {
7156
+ var ext = getFileExtension(file || '').toLowerCase(),
7157
+ type = null;
7158
+ if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
7159
+ type = ext;
7160
+ } else if (/json$/.test(ext)) {
7161
+ type = 'json';
7162
+ } else if (ext == 'csv' || ext == 'tsv' || ext == 'txt' || ext == 'tab') {
7163
+ type = 'text';
7164
+ }
7165
+ return type;
7166
+ }
7167
+
7168
+ function guessInputContentType(content) {
7169
+ var type = null;
7170
+ if (utils.isString(content)) {
7171
+ type = stringLooksLikeJSON(content) && 'json' ||
7172
+ stringLooksLikeKML(content) && 'kml' || 'text';
7173
+ } else if (utils.isObject(content) && content.type || utils.isArray(content)) {
7174
+ type = 'json';
7175
+ }
7176
+ return type;
7177
+ }
7178
+
7179
+ function guessInputType(file, content) {
7180
+ return guessInputFileType(file) || guessInputContentType(content);
7181
+ }
7182
+
7183
+ function stringLooksLikeJSON(str) {
7184
+ return /^\s*[{[]/.test(String(str));
7185
+ }
7186
+
7187
+ function stringLooksLikeKML(str) {
7188
+ str = String(str);
7189
+ return str.includes('<kml ') && str.includes('xmlns="http://www.opengis.net/kml/');
7190
+ }
7191
+
7192
+ function couldBeDsvFile(name) {
7193
+ var ext = getFileExtension(name).toLowerCase();
7194
+ return /csv|tsv|txt$/.test(ext);
7195
+ }
7196
+
7197
+ function isZipFile(file) {
7198
+ return /\.zip$/i.test(file);
7199
+ }
7200
+
7201
+ function isSupportedOutputFormat(fmt) {
7202
+ var types = ['geojson', 'topojson', 'json', 'dsv', 'dbf', 'shapefile', 'svg'];
7203
+ return types.indexOf(fmt) > -1;
7204
+ }
7205
+
7206
+ function getFormatName(fmt) {
7207
+ return {
7208
+ geojson: 'GeoJSON',
7209
+ topojson: 'TopoJSON',
7210
+ json: 'JSON records',
7211
+ dsv: 'CSV',
7212
+ dbf: 'DBF',
7213
+ shapefile: 'Shapefile',
7214
+ svg: 'SVG'
7215
+ }[fmt] || '';
7216
+ }
7217
+
7218
+ // Assumes file at @path is one of Mapshaper's supported file types
7219
+ function isSupportedBinaryInputType(path) {
7220
+ var ext = getFileExtension(path).toLowerCase();
7221
+ return ext == 'shp' || ext == 'shx' || ext == 'dbf'; // GUI also supports zip files
7222
+ }
7223
+
7224
+ // Detect extensions of some unsupported file types, for cmd line validation
7225
+ function filenameIsUnsupportedOutputType(file) {
7226
+ var rxp = /\.(shx|prj|xls|xlsx|gdb|sbn|sbx|xml|kml)$/i;
7227
+ return rxp.test(file);
7228
+ }
7229
+
7230
+ var FileTypes = /*#__PURE__*/Object.freeze({
7231
+ __proto__: null,
7232
+ guessInputFileType: guessInputFileType,
7233
+ guessInputContentType: guessInputContentType,
7234
+ guessInputType: guessInputType,
7235
+ stringLooksLikeJSON: stringLooksLikeJSON,
7236
+ stringLooksLikeKML: stringLooksLikeKML,
7237
+ couldBeDsvFile: couldBeDsvFile,
7238
+ isZipFile: isZipFile,
7239
+ isSupportedOutputFormat: isSupportedOutputFormat,
7240
+ getFormatName: getFormatName,
7241
+ isSupportedBinaryInputType: isSupportedBinaryInputType,
7242
+ filenameIsUnsupportedOutputType: filenameIsUnsupportedOutputType
7243
+ });
7244
+
7245
+ // input: input file path or a Buffer containing .zip file bytes
7246
+ // cache: destination for extracted file contents
7247
+ function extractFiles(input, cache) {
7248
+ var zip = new require('adm-zip')(input);
7249
+ var files = zip.getEntries().map(function(entry) {
7250
+ // entry.entryName // path, including filename
7251
+ // entry.name // filename
7252
+ var file = toLowerCaseExtension(entry.name);
7253
+ if (file[0] == '.') return ''; // skip hidden system file
7254
+ var type = guessInputFileType(file);
7255
+ if (!type) return ''; // skip unrecognized extensions
7256
+ cache[file] = entry.getData();
7257
+ return file;
7258
+ });
7259
+ // remove auxiliary files from the import list
7260
+ // (these are files that can't be converted into datasets);
7261
+ return files.filter(function(file) {
7262
+ if (!file) return false;
7263
+ var type = guessInputFileType(file);
7264
+ if (type == 'dbf') {
7265
+ // don't import .dbf separately if .shp is present
7266
+ if (replaceFileExtension(file, 'shp') in cache) return false;
7267
+ }
7268
+ return type == 'text' || type == 'json' || type == 'shp' || type == 'dbf';
7269
+ });
7270
+ }
7271
+
7272
+ function convertOutputFiles(files, opts) {
7273
+ var filename = opts.zipfile || 'output.zip';
7274
+ var dirname = parseLocalPath(filename).basename;
7275
+ var zip = new require('adm-zip')();
7276
+ files.forEach(function(o) {
7277
+ var ofile = require('path').join(dirname, o.filename);
7278
+ var buf = Buffer.from(o.content);
7279
+ if (buf instanceof ArrayBuffer) {
7280
+ buf = new Uint8Array(buf);
7281
+ }
7282
+ zip.addFile(ofile, buf);
7283
+ delete o.content; // for gc?
7284
+ });
7285
+ return [{
7286
+ filename: filename,
7287
+ content: zip.toBuffer()
7288
+ }];
7289
+ }
7290
+
7291
+ function runningInBrowser() {
7292
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
7293
+ }
7294
+
7295
+ var Env = /*#__PURE__*/Object.freeze({
7296
+ __proto__: null,
7297
+ runningInBrowser: runningInBrowser
7298
+ });
7299
+
7157
7300
  var cli = {};
7158
7301
 
7159
7302
  cli.isFile = function(path, cache) {
@@ -7303,6 +7446,9 @@
7303
7446
  // trigger EAGAIN error, e.g. when piped to less)
7304
7447
  return cli.writeFile('/dev/stdout', exports[0].content, cb);
7305
7448
  } else {
7449
+ if (opts.zip) {
7450
+ exports = convertOutputFiles(exports, opts);
7451
+ }
7306
7452
  var paths = getOutputPaths(utils.pluck(exports, 'filename'), opts);
7307
7453
  var inputFiles = getStashedVar('input_files');
7308
7454
  exports.forEach(function(obj, i) {
@@ -7312,7 +7458,7 @@
7312
7458
  obj.content = cli.convertArrayBuffer(obj.content); // convert to Buffer
7313
7459
  }
7314
7460
  if (opts.gzip) {
7315
- path = path + '.gz';
7461
+ path = /gz$/i.test(path) ? path : path + '.gz';
7316
7462
  obj.content = require$1('zlib').gzipSync(obj.content);
7317
7463
  }
7318
7464
  if (opts.output) {
@@ -17292,97 +17438,6 @@ ${svg}
17292
17438
  exportJSONTable: exportJSONTable
17293
17439
  });
17294
17440
 
17295
- // Guess the type of a data file from file extension, or return null if not sure
17296
- function guessInputFileType(file) {
17297
- var ext = getFileExtension(file || '').toLowerCase(),
17298
- type = null;
17299
- if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
17300
- type = ext;
17301
- } else if (/json$/.test(ext)) {
17302
- type = 'json';
17303
- } else if (ext == 'csv' || ext == 'tsv' || ext == 'txt' || ext == 'tab') {
17304
- type = 'text';
17305
- }
17306
- return type;
17307
- }
17308
-
17309
- function guessInputContentType(content) {
17310
- var type = null;
17311
- if (utils.isString(content)) {
17312
- type = stringLooksLikeJSON(content) && 'json' ||
17313
- stringLooksLikeKML(content) && 'kml' || 'text';
17314
- } else if (utils.isObject(content) && content.type || utils.isArray(content)) {
17315
- type = 'json';
17316
- }
17317
- return type;
17318
- }
17319
-
17320
- function guessInputType(file, content) {
17321
- return guessInputFileType(file) || guessInputContentType(content);
17322
- }
17323
-
17324
- function stringLooksLikeJSON(str) {
17325
- return /^\s*[{[]/.test(String(str));
17326
- }
17327
-
17328
- function stringLooksLikeKML(str) {
17329
- str = String(str);
17330
- return str.includes('<kml ') && str.includes('xmlns="http://www.opengis.net/kml/');
17331
- }
17332
-
17333
- function couldBeDsvFile(name) {
17334
- var ext = getFileExtension(name).toLowerCase();
17335
- return /csv|tsv|txt$/.test(ext);
17336
- }
17337
-
17338
- function isZipFile(file) {
17339
- return /\.zip$/i.test(file);
17340
- }
17341
-
17342
- function isSupportedOutputFormat(fmt) {
17343
- var types = ['geojson', 'topojson', 'json', 'dsv', 'dbf', 'shapefile', 'svg'];
17344
- return types.indexOf(fmt) > -1;
17345
- }
17346
-
17347
- function getFormatName(fmt) {
17348
- return {
17349
- geojson: 'GeoJSON',
17350
- topojson: 'TopoJSON',
17351
- json: 'JSON records',
17352
- dsv: 'CSV',
17353
- dbf: 'DBF',
17354
- shapefile: 'Shapefile',
17355
- svg: 'SVG'
17356
- }[fmt] || '';
17357
- }
17358
-
17359
- // Assumes file at @path is one of Mapshaper's supported file types
17360
- function isSupportedBinaryInputType(path) {
17361
- var ext = getFileExtension(path).toLowerCase();
17362
- return ext == 'shp' || ext == 'shx' || ext == 'dbf'; // GUI also supports zip files
17363
- }
17364
-
17365
- // Detect extensions of some unsupported file types, for cmd line validation
17366
- function filenameIsUnsupportedOutputType(file) {
17367
- var rxp = /\.(shx|prj|xls|xlsx|gdb|sbn|sbx|xml|kml)$/i;
17368
- return rxp.test(file);
17369
- }
17370
-
17371
- var FileTypes = /*#__PURE__*/Object.freeze({
17372
- __proto__: null,
17373
- guessInputFileType: guessInputFileType,
17374
- guessInputContentType: guessInputContentType,
17375
- guessInputType: guessInputType,
17376
- stringLooksLikeJSON: stringLooksLikeJSON,
17377
- stringLooksLikeKML: stringLooksLikeKML,
17378
- couldBeDsvFile: couldBeDsvFile,
17379
- isZipFile: isZipFile,
17380
- isSupportedOutputFormat: isSupportedOutputFormat,
17381
- getFormatName: getFormatName,
17382
- isSupportedBinaryInputType: isSupportedBinaryInputType,
17383
- filenameIsUnsupportedOutputType: filenameIsUnsupportedOutputType
17384
- });
17385
-
17386
17441
  function getOutputFormat(dataset, opts) {
17387
17442
  var outFile = opts.file || null,
17388
17443
  inFmt = dataset.info && dataset.info.input_formats && dataset.info.input_formats[0],
@@ -18545,9 +18600,19 @@ ${svg}
18545
18600
  // (cli.writeFile() now creates directories that don't exist)
18546
18601
  // cli.validateOutputDir(o.directory);
18547
18602
  }
18548
- if (pathInfo.extension == 'gz') {
18549
- o.file = pathInfo.basename;
18603
+ if (/gz/i.test(pathInfo.extension)) {
18604
+ // handle arguments like -o out.json.gz (the preferred format)
18605
+ if (parseLocalPath(pathInfo.basename).extension) {
18606
+ o.file = pathInfo.basename;
18607
+ } else {
18608
+ // handle arguments like -o out.gz
18609
+ o.file = pathInfo.filename;
18610
+ }
18550
18611
  o.gzip = true;
18612
+ } else if (/zip/i.test(pathInfo.extension)) {
18613
+ o.file = null;
18614
+ o.zipfile = pathInfo.filename;
18615
+ o.zip = true;
18551
18616
  } else {
18552
18617
  o.file = pathInfo.filename;
18553
18618
  }
@@ -19361,6 +19426,10 @@ ${svg}
19361
19426
  describe: 'apply gzip compression to output files',
19362
19427
  type: 'flag'
19363
19428
  })
19429
+ .option('zip', {
19430
+ describe: 'save all output files in a single .zip file',
19431
+ type: 'flag'
19432
+ })
19364
19433
  .option('dry-run', {
19365
19434
  // describe: 'do not output any files'
19366
19435
  type: 'flag'
@@ -23725,36 +23794,6 @@ ${svg}
23725
23794
  importFileContent: importFileContent
23726
23795
  });
23727
23796
 
23728
- // Import multiple files to a single dataset
23729
- function importFiles(files, opts) {
23730
- var unbuiltTopology = false;
23731
- var datasets = files.map(function(fname) {
23732
- // import without topology or snapping
23733
- var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
23734
- var dataset = importFile(fname, importOpts);
23735
- // check if dataset contains non-topological paths
23736
- // TODO: may also need to rebuild topology if multiple topojson files are merged
23737
- if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
23738
- unbuiltTopology = true;
23739
- }
23740
- return dataset;
23741
- });
23742
- var combined = mergeDatasets(datasets);
23743
- // Build topology, if needed
23744
- // TODO: consider updating topology of TopoJSON files instead of concatenating arcs
23745
- // (but problem of mismatched coordinates due to quantization in input files.)
23746
- if (unbuiltTopology && !opts.no_topology) {
23747
- cleanPathsAfterImport(combined, opts);
23748
- buildTopology(combined);
23749
- }
23750
- return combined;
23751
- }
23752
-
23753
- var MergeFiles = /*#__PURE__*/Object.freeze({
23754
- __proto__: null,
23755
- importFiles: importFiles
23756
- });
23757
-
23758
23797
  cmd.importFiles = function(opts) {
23759
23798
  var files = opts.files || [],
23760
23799
  dataset;
@@ -23768,17 +23807,16 @@ ${svg}
23768
23807
  }
23769
23808
 
23770
23809
  verbose("Importing: " + files.join(' '));
23771
-
23772
- if (files.length == 1) {
23810
+ if (files.length == 1 && /\.zip/i.test(files[0])) {
23811
+ dataset = importZipFile(files[0], opts);
23812
+ } else if (files.length == 1) {
23773
23813
  dataset = importFile(files[0], opts);
23774
23814
  } else if (opts.merge_files) {
23775
23815
  // TODO: deprecate and remove this option (use -merge-layers cmd instead)
23776
- dataset = importFiles(files, opts);
23816
+ dataset = importFilesTogether(files, opts);
23777
23817
  dataset.layers = cmd.mergeLayers(dataset.layers);
23778
- } else if (opts.combine_files) {
23779
- dataset = importFiles(files, opts);
23780
23818
  } else {
23781
- stop('Invalid inputs');
23819
+ dataset = importFilesTogether(files, opts);
23782
23820
  }
23783
23821
  return dataset;
23784
23822
  };
@@ -23848,6 +23886,49 @@ ${svg}
23848
23886
  return importContent(input, opts);
23849
23887
  };
23850
23888
 
23889
+
23890
+ function importZipFile(path, opts) {
23891
+ var cache = {};
23892
+ var input;
23893
+ if (opts.input && (path in opts.input)) {
23894
+ // reading from a buffer
23895
+ input = opts.input[path];
23896
+ } else {
23897
+ // reading from a file
23898
+ cli.checkFileExists(path);
23899
+ input = path;
23900
+ }
23901
+ var files = extractFiles(input, cache);
23902
+ var zipOpts = Object.assign({}, opts, {input: cache});
23903
+ return importFilesTogether(files, zipOpts);
23904
+ }
23905
+
23906
+ // Import multiple files to a single dataset
23907
+ function importFilesTogether(files, opts) {
23908
+ var unbuiltTopology = false;
23909
+ var datasets = files.map(function(fname) {
23910
+ // import without topology or snapping
23911
+ var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
23912
+ var dataset = importFile(fname, importOpts);
23913
+ // check if dataset contains non-topological paths
23914
+ // TODO: may also need to rebuild topology if multiple topojson files are merged
23915
+ if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
23916
+ unbuiltTopology = true;
23917
+ }
23918
+ return dataset;
23919
+ });
23920
+ var combined = mergeDatasets(datasets);
23921
+ // Build topology, if needed
23922
+ // TODO: consider updating topology of TopoJSON files instead of concatenating arcs
23923
+ // (but problem of mismatched coordinates due to quantization in input files.)
23924
+ if (unbuiltTopology && !opts.no_topology) {
23925
+ cleanPathsAfterImport(combined, opts);
23926
+ buildTopology(combined);
23927
+ }
23928
+ return combined;
23929
+ }
23930
+
23931
+
23851
23932
  function getUnsupportedFileMessage(path) {
23852
23933
  var ext = getFileExtension(path);
23853
23934
  var msg = 'Unable to import ' + path;
@@ -23885,7 +23966,8 @@ ${svg}
23885
23966
  var FileImport = /*#__PURE__*/Object.freeze({
23886
23967
  __proto__: null,
23887
23968
  replaceImportFile: replaceImportFile,
23888
- importFile: importFile
23969
+ importFile: importFile,
23970
+ importFilesTogether: importFilesTogether
23889
23971
  });
23890
23972
 
23891
23973
  function convertSourceName(name, targets) {
@@ -42779,7 +42861,6 @@ ${svg}
42779
42861
  LayerUtils,
42780
42862
  Lines,
42781
42863
  Logging,
42782
- MergeFiles,
42783
42864
  Merging,
42784
42865
  MosaicIndex$1,
42785
42866
  OptionParsingUtils,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.13",
3
+ "version": "0.6.14",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -42,6 +42,7 @@
42
42
  "dependencies": {
43
43
  "@tmcw/togeojson": "^4.7.0",
44
44
  "@xmldom/xmldom": "^0.8.2",
45
+ "adm-zip": "^0.5.9",
45
46
  "commander": "7.0.0",
46
47
  "cookies": "^0.8.0",
47
48
  "d3-color": "2.0.0",
package/www/basemap.js CHANGED
@@ -1,6 +1,6 @@
1
1
  window.mapboxParams = {
2
- js: 'https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.js',
3
- css: 'https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.css',
2
+ js: 'https://api.mapbox.com/mapbox-gl-js/v2.11.1/mapbox-gl.js',
3
+ css: 'https://api.mapbox.com/mapbox-gl-js/v2.11.1/mapbox-gl.css',
4
4
  key: 'pk.eyJ1IjoiZ3JhbW1hdGEiLCJhIjoiY2wxMzI4b3dqMDNhMjNpcDhzcmU0aGh5diJ9.m1lacx48pTYls-X3FVhG9g',
5
5
  styles: [{
6
6
  name: 'Map',