mapshaper 0.6.93 → 0.6.94

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.
Files changed (3) hide show
  1. package/mapshaper.js +110 -48
  2. package/package.json +1 -1
  3. package/www/mapshaper.js +110 -48
package/mapshaper.js CHANGED
@@ -4660,11 +4660,14 @@
4660
4660
 
4661
4661
  var mproj$1 = require$1('mproj');
4662
4662
 
4663
- // A compound projection, consisting of a default projection and one or more rectangular frames
4664
- // that are projected separately and affine transformed.
4663
+ // Constructor function for a compound projection consisting of a default
4664
+ // projection and one or more rectangular frames that are projected separately
4665
+ // and affine transformed.
4665
4666
  // @mainParams: parameters for main projection, including:
4666
4667
  // proj: Proj string
4667
4668
  // bbox: lat-lon bounding box
4669
+ // Returns a mproj CRS object for the main CRS with the CRS objects of the
4670
+ // embedded projections attached.
4668
4671
  function MixedProjection(mainParams, options) {
4669
4672
  var mainFrame = initFrame(mainParams);
4670
4673
  var mainP = mainFrame.crs;
@@ -5056,6 +5059,9 @@
5056
5059
  return str in projectionAliases;
5057
5060
  }
5058
5061
 
5062
+ // str: projection string in a variety of forms accepted by the -proj command
5063
+ // (e.g. alias, EPSG:XXXX, Proj.4 string, bare Proj.4 projection name)
5064
+ // Returns a properly formatted Proj.4 string or an instantiated mproj object
5059
5065
  function getProjDefn(str) {
5060
5066
  var defn;
5061
5067
  // prepend '+proj=' to bare proj names
@@ -7701,7 +7707,7 @@
7701
7707
  if (currentUnpackr.mapsAsObjects) {
7702
7708
  let object = {};
7703
7709
  for (let i = 0; i < token; i++) {
7704
- let key = readKey$1();
7710
+ let key = readKey();
7705
7711
  if (key === '__proto__')
7706
7712
  key = '__proto_';
7707
7713
  object[key] = read();
@@ -8063,7 +8069,7 @@
8063
8069
  if (currentUnpackr.mapsAsObjects) {
8064
8070
  let object = {};
8065
8071
  for (let i = 0; i < length; i++) {
8066
- let key = readKey$1();
8072
+ let key = readKey();
8067
8073
  if (key === '__proto__')
8068
8074
  key = '__proto_';
8069
8075
  object[key] = read();
@@ -8286,7 +8292,7 @@
8286
8292
  }
8287
8293
 
8288
8294
  var keyCache = new Array(4096);
8289
- function readKey$1() {
8295
+ function readKey() {
8290
8296
  let length = src[position$1++];
8291
8297
  if (length >= 0xa0 && length < 0xc0) {
8292
8298
  // fixstr, potentially use key cache
@@ -11316,9 +11322,11 @@
11316
11322
  function guessInputFileType(file) {
11317
11323
  var ext = getFileExtension(file || '').toLowerCase(),
11318
11324
  type = null;
11319
- if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
11325
+ if (ext == 'dbf' || ext == 'shp' || ext == 'kml') {
11320
11326
  type = ext;
11321
- } else if (/json$/.test(ext)) {
11327
+ } else if (isAuxiliaryInputFileType(ext)) {
11328
+ type = ext;
11329
+ } else if (/json$/.test(ext)) { // matches topojson, geojson, json
11322
11330
  type = 'json';
11323
11331
  } else if (ext == 'csv' || ext == 'tsv' || ext == 'txt' || ext == 'tab') {
11324
11332
  type = 'text';
@@ -11328,6 +11336,11 @@
11328
11336
  return type;
11329
11337
  }
11330
11338
 
11339
+ // File types that can be imported but are not convertible to datasets
11340
+ function isAuxiliaryInputFileType(type) {
11341
+ return type == 'prj' || type == 'shx' || type == 'cpg';
11342
+ }
11343
+
11331
11344
  function guessInputContentType(content) {
11332
11345
  var type = null;
11333
11346
  if (utils.isString(content)) {
@@ -11428,6 +11441,7 @@
11428
11441
  var FileTypes = /*#__PURE__*/Object.freeze({
11429
11442
  __proto__: null,
11430
11443
  guessInputFileType: guessInputFileType,
11444
+ isAuxiliaryInputFileType: isAuxiliaryInputFileType,
11431
11445
  guessInputContentType: guessInputContentType,
11432
11446
  guessInputType: guessInputType,
11433
11447
  stringLooksLikeJSON: stringLooksLikeJSON,
@@ -28085,7 +28099,7 @@ ${svg}
28085
28099
 
28086
28100
  var EOF; // undefined is used as an EOF marker
28087
28101
 
28088
- var RESERVE = 0X1000; // RESERVE is the number of bytes to keep in read buffer
28102
+ var RESERVE = 4096; // RESERVE is the number of bytes to keep in read buffer
28089
28103
  var BUFLEN = 1e7; // buffer chunk size
28090
28104
  var MAX_STRLEN = 5e6; // max byte len of a value string (object keys are shorter)
28091
28105
 
@@ -28102,14 +28116,33 @@ ${svg}
28102
28116
  return val;
28103
28117
  }
28104
28118
 
28105
- // Read and parse JSON objects from a FileReader
28106
- function parseObjects(reader, offset, cb) {
28107
- var src = ByteReader(reader, offset);
28108
- seekObjectStart(src);
28119
+ // parse data from:
28120
+ // * FeatureCollection
28121
+ // * GeometryCollection
28122
+ // * Single Feature or Geometry
28123
+ // * WS-delimited sequence of Features or geometries
28124
+ //
28125
+ function parseGeoJSON(reader, cb) {
28126
+ var src = ByteReader(reader, 0);
28127
+ var isObject = seekObjectStart(src);
28128
+ if (!isObject) {
28129
+ stop('File is not GeoJSON');
28130
+ }
28131
+ var obj = readObject(src, cb);
28132
+ if (obj.type == 'FeatureCollection' || obj.type == 'GeometryCollection') {
28133
+ return obj;
28134
+ }
28135
+ if (!obj.type) { // TODO: validate type
28136
+ stop('Invalid GeoJSON');
28137
+ }
28138
+ cb(obj);
28139
+ // try to read newline-delimited GeoJSON
28140
+ skipWS(src);
28109
28141
  while (src.peek() == LBRACE) {
28110
- cb(readObject(src));
28111
- readToken(src, COMMA);
28142
+ cb(readObject(src, cb));
28143
+ skipWS(src);
28112
28144
  }
28145
+ return null;
28113
28146
  }
28114
28147
 
28115
28148
  function parseError(msg, i) {
@@ -28166,15 +28199,26 @@ ${svg}
28166
28199
  function readArray(src) {
28167
28200
  var arr = [], c;
28168
28201
  eatChar(src, LBRACK);
28169
- c = readToken(src, RBRACK);
28202
+ c = scanForSyntaxChar(src, RBRACK);
28170
28203
  while (c != RBRACK) {
28171
28204
  src.refresh();
28172
28205
  arr.push(readArrayElement(src));
28173
- c = readAorB(src, COMMA, RBRACK);
28206
+ c = scanForAorB(src, COMMA, RBRACK);
28174
28207
  }
28175
28208
  return arr;
28176
28209
  }
28177
28210
 
28211
+ function readCollectionArray(src, cb) {
28212
+ var c;
28213
+ eatChar(src, LBRACK);
28214
+ c = scanForSyntaxChar(src, RBRACK);
28215
+ while (c != RBRACK) {
28216
+ src.refresh();
28217
+ cb(readArrayElement(src));
28218
+ c = scanForAorB(src, COMMA, RBRACK);
28219
+ }
28220
+ }
28221
+
28178
28222
  // Using this function instead of readValue() to read array elements
28179
28223
  // gives up to a 25% reduction in overall processing time when parsing
28180
28224
  // coordinate-heavy GeoJSON files.
@@ -28205,7 +28249,7 @@ ${svg}
28205
28249
  do {
28206
28250
  src.refresh(); // make make sure long arrays of numbers don't overflow
28207
28251
  arr.push(readValue(src));
28208
- } while(readAorB(src, COMMA, RBRACK) == COMMA);
28252
+ } while(scanForAorB(src, COMMA, RBRACK) == COMMA);
28209
28253
  return arr;
28210
28254
  }
28211
28255
 
@@ -28226,7 +28270,7 @@ ${svg}
28226
28270
  // Reads and returns tok if tok is the next non-whitespace byte,
28227
28271
  // else returns null.
28228
28272
  // Scans past WS chars, both before and after tok
28229
- function readToken(src, tok) {
28273
+ function scanForSyntaxChar(src, tok) {
28230
28274
  skipWS(src);
28231
28275
  var c = src.peek();
28232
28276
  if (c === tok) {
@@ -28237,7 +28281,7 @@ ${svg}
28237
28281
  return null;
28238
28282
  }
28239
28283
 
28240
- // assumes no leading WS
28284
+ // Assumes next char is the first char of a data object (not WS "," ":" "}" "]" etc)
28241
28285
  function readValue(src) {
28242
28286
  var c = src.peek();
28243
28287
  var val;
@@ -28245,14 +28289,29 @@ ${svg}
28245
28289
  else if (c == LBRACK) val = readArray(src);
28246
28290
  else if (c == DQUOTE) val = readString(src);
28247
28291
  else if (c == LBRACE) val = readObject(src);
28248
- else if (c == 110) val = eatChars(src, "null") && null;
28249
- else if (c == 116) val = eatChars(src, "true") && true;
28250
- else if (c == 102) val = eatChars(src, "false") && false;
28292
+ else if (c == 110) val = readNull(src); // "n" -> null
28293
+ else if (c == 116) val = readTrue(src); // "t" -> true
28294
+ else if (c == 102) val = readFalse(src); // "f" -> false
28251
28295
  else unexpectedCharAt(c, src.index());
28252
28296
  return val;
28253
28297
  }
28254
28298
 
28255
- function readAorB(src, a, b) {
28299
+ function readTrue(src) {
28300
+ eatChars(src, 'true');
28301
+ return true;
28302
+ }
28303
+
28304
+ function readFalse(src) {
28305
+ eatChars(src, 'false');
28306
+ return false;
28307
+ }
28308
+
28309
+ function readNull(src) {
28310
+ eatChars(src, 'null');
28311
+ return null;
28312
+ }
28313
+
28314
+ function scanForAorB(src, a, b) {
28256
28315
  skipWS(src);
28257
28316
  var c = src.getChar();
28258
28317
  if (c != a && c != b) unexpectedCharAt(c, src.index() - 1);
@@ -28260,21 +28319,30 @@ ${svg}
28260
28319
  return c;
28261
28320
  }
28262
28321
 
28263
- function readObject(src) {
28322
+
28323
+ // cb: optional callback for returning GeoJSON features or geometries
28324
+ //
28325
+ function readObject(src, cb) {
28264
28326
  var o = {};
28265
28327
  var key, c;
28266
28328
  eatChar(src, LBRACE);
28267
- c = readToken(src, RBRACE);
28329
+ c = scanForSyntaxChar(src, RBRACE);
28268
28330
  while (c != RBRACE) {
28269
28331
  src.refresh();
28270
- key = readKey(src); // use caching for faster key parsing
28332
+ key = readKeywordString(src); // optimization: use caching with object keys
28271
28333
  skipWS(src);
28272
- eatChar(src, 58);
28334
+ eatChar(src, 58); // ":"
28273
28335
  skipWS(src);
28274
- // use caching with GeoJSON "type" params
28275
- o[key] = key == 'type' && src.peek() == DQUOTE ?
28276
- readKey(src) : readValue(src);
28277
- c = readAorB(src, COMMA, RBRACE);
28336
+ if ((key == 'features' || key == 'geometries') &&
28337
+ src.peek() == LBRACK && cb) {
28338
+ readCollectionArray(src, cb);
28339
+ o[key] = null;
28340
+ } else if (key == 'type' && src.peek() == DQUOTE) {
28341
+ o[key] = readKeywordString(src); // use caching with GeoJSON "type" params
28342
+ } else {
28343
+ o[key] = readValue(src);
28344
+ }
28345
+ c = scanForAorB(src, COMMA, RBRACE);
28278
28346
  }
28279
28347
  return o;
28280
28348
  }
@@ -28287,7 +28355,7 @@ ${svg}
28287
28355
  // Uses caching to speed up parsing of repeated strings.
28288
28356
  // The caching scheme used here can give a 20% overall speed improvement
28289
28357
  // when parsing files consisting mostly of attribute data (e.g. typical Point features)
28290
- function readKey(src) {
28358
+ function readKeywordString(src) {
28291
28359
  var MAXLEN = 2000; // must be less than RESERVE
28292
28360
  var i = src.index();
28293
28361
  var cache = src.cache;
@@ -28532,21 +28600,12 @@ ${svg}
28532
28600
  // @reader: a FileReader
28533
28601
  function GeoJSONReader(reader) {
28534
28602
 
28535
- // Read objects synchronously, with callback
28536
28603
  this.readObjects = function(onObject) {
28537
- // Search first x bytes of file for features|geometries key
28538
- // 300 bytes not enough... GeoJSON files can have additional non-standard properties, e.g. 'metadata'
28539
- // var bytesToSearch = 300;
28540
- var bytesToSearch = 5000;
28541
- var start = reader.findString('"features"', bytesToSearch) ||
28542
- reader.findString('"geometries"', bytesToSearch);
28543
- // Assume single Feature or geometry if collection not found
28544
- // (this works for ndjson files too)
28545
- var offset = start ? start.offset : 0;
28546
28604
  T$1.start();
28547
- parseObjects(reader, offset, onObject);
28548
- // parseObjects_native(reader, offset, onObject);
28605
+ var val = parseGeoJSON(reader, onObject);
28606
+ // var val = parseGeoJSON_native(reader, onObject);
28549
28607
  debug('Parse GeoJSON', T$1.stop());
28608
+ return val;
28550
28609
  };
28551
28610
  }
28552
28611
 
@@ -28584,6 +28643,7 @@ ${svg}
28584
28643
  function importGeoJSONFile(fileReader, opts) {
28585
28644
  var importer = new GeoJSONParser(opts);
28586
28645
  new GeoJSONReader(fileReader).readObjects(importer.parseObject);
28646
+ // TODO: examine top-level objects, like crs
28587
28647
  return importer.done();
28588
28648
  }
28589
28649
 
@@ -28880,7 +28940,7 @@ ${svg}
28880
28940
  }
28881
28941
 
28882
28942
  return {
28883
- info: importInfo(obj.info || {}),
28943
+ info: await importInfo(obj.info || {}),
28884
28944
  layers: layers,
28885
28945
  arcs: arcs
28886
28946
  };
@@ -28920,8 +28980,10 @@ ${svg}
28920
28980
  return arcs;
28921
28981
  }
28922
28982
 
28923
- function importInfo(o) {
28983
+ async function importInfo(o) {
28924
28984
  if (o.crs_string) {
28985
+ // load external files (e.g. epsg definitions) if needed in GUI
28986
+ await initProjLibrary({crs: o.crs_string});
28925
28987
  o.crs = parseCrsString(o.crs_string);
28926
28988
  } else if (o.prj) {
28927
28989
  o.crs = parsePrj(o.prj);
@@ -29068,7 +29130,7 @@ ${svg}
29068
29130
  // don't import .dbf separately if .shp is present
29069
29131
  if (replaceFileExtension(filename, 'shp') in cache) return false;
29070
29132
  }
29071
- return type == 'text' || type == 'json' || type == 'shp' || type == 'dbf' || type == 'kml';
29133
+ return type && !isAuxiliaryInputFileType(type);
29072
29134
  });
29073
29135
  }
29074
29136
 
@@ -45616,7 +45678,7 @@ ${svg}
45616
45678
  });
45617
45679
  }
45618
45680
 
45619
- var version = "0.6.93";
45681
+ var version = "0.6.94";
45620
45682
 
45621
45683
  // Parse command line args into commands and run them
45622
45684
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.93",
3
+ "version": "0.6.94",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/mapshaper.js CHANGED
@@ -4660,11 +4660,14 @@
4660
4660
 
4661
4661
  var mproj$1 = require$1('mproj');
4662
4662
 
4663
- // A compound projection, consisting of a default projection and one or more rectangular frames
4664
- // that are projected separately and affine transformed.
4663
+ // Constructor function for a compound projection consisting of a default
4664
+ // projection and one or more rectangular frames that are projected separately
4665
+ // and affine transformed.
4665
4666
  // @mainParams: parameters for main projection, including:
4666
4667
  // proj: Proj string
4667
4668
  // bbox: lat-lon bounding box
4669
+ // Returns a mproj CRS object for the main CRS with the CRS objects of the
4670
+ // embedded projections attached.
4668
4671
  function MixedProjection(mainParams, options) {
4669
4672
  var mainFrame = initFrame(mainParams);
4670
4673
  var mainP = mainFrame.crs;
@@ -5056,6 +5059,9 @@
5056
5059
  return str in projectionAliases;
5057
5060
  }
5058
5061
 
5062
+ // str: projection string in a variety of forms accepted by the -proj command
5063
+ // (e.g. alias, EPSG:XXXX, Proj.4 string, bare Proj.4 projection name)
5064
+ // Returns a properly formatted Proj.4 string or an instantiated mproj object
5059
5065
  function getProjDefn(str) {
5060
5066
  var defn;
5061
5067
  // prepend '+proj=' to bare proj names
@@ -7701,7 +7707,7 @@
7701
7707
  if (currentUnpackr.mapsAsObjects) {
7702
7708
  let object = {};
7703
7709
  for (let i = 0; i < token; i++) {
7704
- let key = readKey$1();
7710
+ let key = readKey();
7705
7711
  if (key === '__proto__')
7706
7712
  key = '__proto_';
7707
7713
  object[key] = read();
@@ -8063,7 +8069,7 @@
8063
8069
  if (currentUnpackr.mapsAsObjects) {
8064
8070
  let object = {};
8065
8071
  for (let i = 0; i < length; i++) {
8066
- let key = readKey$1();
8072
+ let key = readKey();
8067
8073
  if (key === '__proto__')
8068
8074
  key = '__proto_';
8069
8075
  object[key] = read();
@@ -8286,7 +8292,7 @@
8286
8292
  }
8287
8293
 
8288
8294
  var keyCache = new Array(4096);
8289
- function readKey$1() {
8295
+ function readKey() {
8290
8296
  let length = src[position$1++];
8291
8297
  if (length >= 0xa0 && length < 0xc0) {
8292
8298
  // fixstr, potentially use key cache
@@ -11316,9 +11322,11 @@
11316
11322
  function guessInputFileType(file) {
11317
11323
  var ext = getFileExtension(file || '').toLowerCase(),
11318
11324
  type = null;
11319
- if (ext == 'dbf' || ext == 'shp' || ext == 'prj' || ext == 'shx' || ext == 'kml' || ext == 'cpg') {
11325
+ if (ext == 'dbf' || ext == 'shp' || ext == 'kml') {
11320
11326
  type = ext;
11321
- } else if (/json$/.test(ext)) {
11327
+ } else if (isAuxiliaryInputFileType(ext)) {
11328
+ type = ext;
11329
+ } else if (/json$/.test(ext)) { // matches topojson, geojson, json
11322
11330
  type = 'json';
11323
11331
  } else if (ext == 'csv' || ext == 'tsv' || ext == 'txt' || ext == 'tab') {
11324
11332
  type = 'text';
@@ -11328,6 +11336,11 @@
11328
11336
  return type;
11329
11337
  }
11330
11338
 
11339
+ // File types that can be imported but are not convertible to datasets
11340
+ function isAuxiliaryInputFileType(type) {
11341
+ return type == 'prj' || type == 'shx' || type == 'cpg';
11342
+ }
11343
+
11331
11344
  function guessInputContentType(content) {
11332
11345
  var type = null;
11333
11346
  if (utils.isString(content)) {
@@ -11428,6 +11441,7 @@
11428
11441
  var FileTypes = /*#__PURE__*/Object.freeze({
11429
11442
  __proto__: null,
11430
11443
  guessInputFileType: guessInputFileType,
11444
+ isAuxiliaryInputFileType: isAuxiliaryInputFileType,
11431
11445
  guessInputContentType: guessInputContentType,
11432
11446
  guessInputType: guessInputType,
11433
11447
  stringLooksLikeJSON: stringLooksLikeJSON,
@@ -28085,7 +28099,7 @@ ${svg}
28085
28099
 
28086
28100
  var EOF; // undefined is used as an EOF marker
28087
28101
 
28088
- var RESERVE = 0X1000; // RESERVE is the number of bytes to keep in read buffer
28102
+ var RESERVE = 4096; // RESERVE is the number of bytes to keep in read buffer
28089
28103
  var BUFLEN = 1e7; // buffer chunk size
28090
28104
  var MAX_STRLEN = 5e6; // max byte len of a value string (object keys are shorter)
28091
28105
 
@@ -28102,14 +28116,33 @@ ${svg}
28102
28116
  return val;
28103
28117
  }
28104
28118
 
28105
- // Read and parse JSON objects from a FileReader
28106
- function parseObjects(reader, offset, cb) {
28107
- var src = ByteReader(reader, offset);
28108
- seekObjectStart(src);
28119
+ // parse data from:
28120
+ // * FeatureCollection
28121
+ // * GeometryCollection
28122
+ // * Single Feature or Geometry
28123
+ // * WS-delimited sequence of Features or geometries
28124
+ //
28125
+ function parseGeoJSON(reader, cb) {
28126
+ var src = ByteReader(reader, 0);
28127
+ var isObject = seekObjectStart(src);
28128
+ if (!isObject) {
28129
+ stop('File is not GeoJSON');
28130
+ }
28131
+ var obj = readObject(src, cb);
28132
+ if (obj.type == 'FeatureCollection' || obj.type == 'GeometryCollection') {
28133
+ return obj;
28134
+ }
28135
+ if (!obj.type) { // TODO: validate type
28136
+ stop('Invalid GeoJSON');
28137
+ }
28138
+ cb(obj);
28139
+ // try to read newline-delimited GeoJSON
28140
+ skipWS(src);
28109
28141
  while (src.peek() == LBRACE) {
28110
- cb(readObject(src));
28111
- readToken(src, COMMA);
28142
+ cb(readObject(src, cb));
28143
+ skipWS(src);
28112
28144
  }
28145
+ return null;
28113
28146
  }
28114
28147
 
28115
28148
  function parseError(msg, i) {
@@ -28166,15 +28199,26 @@ ${svg}
28166
28199
  function readArray(src) {
28167
28200
  var arr = [], c;
28168
28201
  eatChar(src, LBRACK);
28169
- c = readToken(src, RBRACK);
28202
+ c = scanForSyntaxChar(src, RBRACK);
28170
28203
  while (c != RBRACK) {
28171
28204
  src.refresh();
28172
28205
  arr.push(readArrayElement(src));
28173
- c = readAorB(src, COMMA, RBRACK);
28206
+ c = scanForAorB(src, COMMA, RBRACK);
28174
28207
  }
28175
28208
  return arr;
28176
28209
  }
28177
28210
 
28211
+ function readCollectionArray(src, cb) {
28212
+ var c;
28213
+ eatChar(src, LBRACK);
28214
+ c = scanForSyntaxChar(src, RBRACK);
28215
+ while (c != RBRACK) {
28216
+ src.refresh();
28217
+ cb(readArrayElement(src));
28218
+ c = scanForAorB(src, COMMA, RBRACK);
28219
+ }
28220
+ }
28221
+
28178
28222
  // Using this function instead of readValue() to read array elements
28179
28223
  // gives up to a 25% reduction in overall processing time when parsing
28180
28224
  // coordinate-heavy GeoJSON files.
@@ -28205,7 +28249,7 @@ ${svg}
28205
28249
  do {
28206
28250
  src.refresh(); // make make sure long arrays of numbers don't overflow
28207
28251
  arr.push(readValue(src));
28208
- } while(readAorB(src, COMMA, RBRACK) == COMMA);
28252
+ } while(scanForAorB(src, COMMA, RBRACK) == COMMA);
28209
28253
  return arr;
28210
28254
  }
28211
28255
 
@@ -28226,7 +28270,7 @@ ${svg}
28226
28270
  // Reads and returns tok if tok is the next non-whitespace byte,
28227
28271
  // else returns null.
28228
28272
  // Scans past WS chars, both before and after tok
28229
- function readToken(src, tok) {
28273
+ function scanForSyntaxChar(src, tok) {
28230
28274
  skipWS(src);
28231
28275
  var c = src.peek();
28232
28276
  if (c === tok) {
@@ -28237,7 +28281,7 @@ ${svg}
28237
28281
  return null;
28238
28282
  }
28239
28283
 
28240
- // assumes no leading WS
28284
+ // Assumes next char is the first char of a data object (not WS "," ":" "}" "]" etc)
28241
28285
  function readValue(src) {
28242
28286
  var c = src.peek();
28243
28287
  var val;
@@ -28245,14 +28289,29 @@ ${svg}
28245
28289
  else if (c == LBRACK) val = readArray(src);
28246
28290
  else if (c == DQUOTE) val = readString(src);
28247
28291
  else if (c == LBRACE) val = readObject(src);
28248
- else if (c == 110) val = eatChars(src, "null") && null;
28249
- else if (c == 116) val = eatChars(src, "true") && true;
28250
- else if (c == 102) val = eatChars(src, "false") && false;
28292
+ else if (c == 110) val = readNull(src); // "n" -> null
28293
+ else if (c == 116) val = readTrue(src); // "t" -> true
28294
+ else if (c == 102) val = readFalse(src); // "f" -> false
28251
28295
  else unexpectedCharAt(c, src.index());
28252
28296
  return val;
28253
28297
  }
28254
28298
 
28255
- function readAorB(src, a, b) {
28299
+ function readTrue(src) {
28300
+ eatChars(src, 'true');
28301
+ return true;
28302
+ }
28303
+
28304
+ function readFalse(src) {
28305
+ eatChars(src, 'false');
28306
+ return false;
28307
+ }
28308
+
28309
+ function readNull(src) {
28310
+ eatChars(src, 'null');
28311
+ return null;
28312
+ }
28313
+
28314
+ function scanForAorB(src, a, b) {
28256
28315
  skipWS(src);
28257
28316
  var c = src.getChar();
28258
28317
  if (c != a && c != b) unexpectedCharAt(c, src.index() - 1);
@@ -28260,21 +28319,30 @@ ${svg}
28260
28319
  return c;
28261
28320
  }
28262
28321
 
28263
- function readObject(src) {
28322
+
28323
+ // cb: optional callback for returning GeoJSON features or geometries
28324
+ //
28325
+ function readObject(src, cb) {
28264
28326
  var o = {};
28265
28327
  var key, c;
28266
28328
  eatChar(src, LBRACE);
28267
- c = readToken(src, RBRACE);
28329
+ c = scanForSyntaxChar(src, RBRACE);
28268
28330
  while (c != RBRACE) {
28269
28331
  src.refresh();
28270
- key = readKey(src); // use caching for faster key parsing
28332
+ key = readKeywordString(src); // optimization: use caching with object keys
28271
28333
  skipWS(src);
28272
- eatChar(src, 58);
28334
+ eatChar(src, 58); // ":"
28273
28335
  skipWS(src);
28274
- // use caching with GeoJSON "type" params
28275
- o[key] = key == 'type' && src.peek() == DQUOTE ?
28276
- readKey(src) : readValue(src);
28277
- c = readAorB(src, COMMA, RBRACE);
28336
+ if ((key == 'features' || key == 'geometries') &&
28337
+ src.peek() == LBRACK && cb) {
28338
+ readCollectionArray(src, cb);
28339
+ o[key] = null;
28340
+ } else if (key == 'type' && src.peek() == DQUOTE) {
28341
+ o[key] = readKeywordString(src); // use caching with GeoJSON "type" params
28342
+ } else {
28343
+ o[key] = readValue(src);
28344
+ }
28345
+ c = scanForAorB(src, COMMA, RBRACE);
28278
28346
  }
28279
28347
  return o;
28280
28348
  }
@@ -28287,7 +28355,7 @@ ${svg}
28287
28355
  // Uses caching to speed up parsing of repeated strings.
28288
28356
  // The caching scheme used here can give a 20% overall speed improvement
28289
28357
  // when parsing files consisting mostly of attribute data (e.g. typical Point features)
28290
- function readKey(src) {
28358
+ function readKeywordString(src) {
28291
28359
  var MAXLEN = 2000; // must be less than RESERVE
28292
28360
  var i = src.index();
28293
28361
  var cache = src.cache;
@@ -28532,21 +28600,12 @@ ${svg}
28532
28600
  // @reader: a FileReader
28533
28601
  function GeoJSONReader(reader) {
28534
28602
 
28535
- // Read objects synchronously, with callback
28536
28603
  this.readObjects = function(onObject) {
28537
- // Search first x bytes of file for features|geometries key
28538
- // 300 bytes not enough... GeoJSON files can have additional non-standard properties, e.g. 'metadata'
28539
- // var bytesToSearch = 300;
28540
- var bytesToSearch = 5000;
28541
- var start = reader.findString('"features"', bytesToSearch) ||
28542
- reader.findString('"geometries"', bytesToSearch);
28543
- // Assume single Feature or geometry if collection not found
28544
- // (this works for ndjson files too)
28545
- var offset = start ? start.offset : 0;
28546
28604
  T$1.start();
28547
- parseObjects(reader, offset, onObject);
28548
- // parseObjects_native(reader, offset, onObject);
28605
+ var val = parseGeoJSON(reader, onObject);
28606
+ // var val = parseGeoJSON_native(reader, onObject);
28549
28607
  debug('Parse GeoJSON', T$1.stop());
28608
+ return val;
28550
28609
  };
28551
28610
  }
28552
28611
 
@@ -28584,6 +28643,7 @@ ${svg}
28584
28643
  function importGeoJSONFile(fileReader, opts) {
28585
28644
  var importer = new GeoJSONParser(opts);
28586
28645
  new GeoJSONReader(fileReader).readObjects(importer.parseObject);
28646
+ // TODO: examine top-level objects, like crs
28587
28647
  return importer.done();
28588
28648
  }
28589
28649
 
@@ -28880,7 +28940,7 @@ ${svg}
28880
28940
  }
28881
28941
 
28882
28942
  return {
28883
- info: importInfo(obj.info || {}),
28943
+ info: await importInfo(obj.info || {}),
28884
28944
  layers: layers,
28885
28945
  arcs: arcs
28886
28946
  };
@@ -28920,8 +28980,10 @@ ${svg}
28920
28980
  return arcs;
28921
28981
  }
28922
28982
 
28923
- function importInfo(o) {
28983
+ async function importInfo(o) {
28924
28984
  if (o.crs_string) {
28985
+ // load external files (e.g. epsg definitions) if needed in GUI
28986
+ await initProjLibrary({crs: o.crs_string});
28925
28987
  o.crs = parseCrsString(o.crs_string);
28926
28988
  } else if (o.prj) {
28927
28989
  o.crs = parsePrj(o.prj);
@@ -29068,7 +29130,7 @@ ${svg}
29068
29130
  // don't import .dbf separately if .shp is present
29069
29131
  if (replaceFileExtension(filename, 'shp') in cache) return false;
29070
29132
  }
29071
- return type == 'text' || type == 'json' || type == 'shp' || type == 'dbf' || type == 'kml';
29133
+ return type && !isAuxiliaryInputFileType(type);
29072
29134
  });
29073
29135
  }
29074
29136
 
@@ -45616,7 +45678,7 @@ ${svg}
45616
45678
  });
45617
45679
  }
45618
45680
 
45619
- var version = "0.6.93";
45681
+ var version = "0.6.94";
45620
45682
 
45621
45683
  // Parse command line args into commands and run them
45622
45684
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.