mapshaper 0.5.115 → 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 +10 -0
- package/bin/mapshaper-gui +1 -0
- package/mapshaper.js +90 -48
- package/package.json +1 -1
- package/www/elements.css +2 -2
- package/www/images/close2.png +0 -0
- package/www/index.html +9 -6
- package/www/mapshaper-gui.js +4 -7
- package/www/mapshaper.js +90 -48
- package/www/page.css +41 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
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
|
+
|
|
5
|
+
v0.5.117
|
|
6
|
+
* Support reading DBF files larger than 2GB (command line program only).
|
|
7
|
+
|
|
8
|
+
v0.5.116
|
|
9
|
+
* Prevent 0-length DBF string fields, for interoperability with PostGIS.
|
|
10
|
+
|
|
1
11
|
v0.5.115
|
|
2
12
|
* Scalebar tweaks.
|
|
3
13
|
|
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.
|
|
3
|
+
var VERSION = "0.5.118";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -16006,7 +16006,9 @@ ${svg}
|
|
|
16006
16006
|
|
|
16007
16007
|
function initStringField(info, arr, name, encoding) {
|
|
16008
16008
|
var formatter = encoding == 'ascii' ? encodeValueAsAscii : getStringWriterEncoded(encoding);
|
|
16009
|
-
|
|
16009
|
+
// Set minimum field size to 1 byte, for interoperability with PostGIS
|
|
16010
|
+
// (see https://github.com/mbloch/mapshaper/issues/541)
|
|
16011
|
+
var size = 1;
|
|
16010
16012
|
var truncated = 0;
|
|
16011
16013
|
var buffers = arr.map(function(rec) {
|
|
16012
16014
|
var strval = convertValueToString(rec[name]);
|
|
@@ -17213,7 +17215,7 @@ ${svg}
|
|
|
17213
17215
|
function guessInputFileType(file) {
|
|
17214
17216
|
var ext = getFileExtension(file || '').toLowerCase(),
|
|
17215
17217
|
type = null;
|
|
17216
|
-
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') {
|
|
17217
17219
|
type = ext;
|
|
17218
17220
|
} else if (/json$/.test(ext)) {
|
|
17219
17221
|
type = 'json';
|
|
@@ -17626,7 +17628,9 @@ ${svg}
|
|
|
17626
17628
|
binArr, buf;
|
|
17627
17629
|
|
|
17628
17630
|
this.readToBinArray = function(start, length) {
|
|
17629
|
-
if (bufSize < start + length)
|
|
17631
|
+
if (bufSize < start + length) {
|
|
17632
|
+
error("Out-of-range error");
|
|
17633
|
+
}
|
|
17630
17634
|
if (!binArr) binArr = new BinArray(src);
|
|
17631
17635
|
binArr.position(start);
|
|
17632
17636
|
return binArr;
|
|
@@ -21084,6 +21088,10 @@ ${svg}
|
|
|
21084
21088
|
parser.command('colors')
|
|
21085
21089
|
.describe('print list of color scheme names');
|
|
21086
21090
|
|
|
21091
|
+
parser.command('comment')
|
|
21092
|
+
.describe('add a comment to the sequence of commands')
|
|
21093
|
+
.flag('multi_arg');
|
|
21094
|
+
|
|
21087
21095
|
parser.command('encodings')
|
|
21088
21096
|
.describe('print list of supported text encodings (for .dbf import)');
|
|
21089
21097
|
|
|
@@ -21135,6 +21143,9 @@ ${svg}
|
|
|
21135
21143
|
// http://www.digitalpreservation.gov/formats/fdd/fdd000325.shtml
|
|
21136
21144
|
// http://www.clicketyclick.dk/databases/xbase/format/index.html
|
|
21137
21145
|
// http://www.clicketyclick.dk/databases/xbase/format/data_types.html
|
|
21146
|
+
// esri docs:
|
|
21147
|
+
// https://support.esri.com/en/technical-article/000007920
|
|
21148
|
+
// https://desktop.arcgis.com/en/arcmap/latest/manage-data/shapefiles/geoprocessing-considerations-for-shapefile-output.htm
|
|
21138
21149
|
|
|
21139
21150
|
// source: http://webhelp.esri.com/arcpad/8.0/referenceguide/index.htm#locales/task_code.htm
|
|
21140
21151
|
var languageIds = [0x01,'437',0x02,'850',0x03,'1252',0x08,'865',0x09,'437',0x0A,'850',0x0B,'437',0x0D,'437',0x0E,'850',0x0F,'437',0x10,'850',0x11,'437',0x12,'850',0x13,'932',0x14,'850',0x15,'437',0x16,'850',0x17,'865',0x18,'437',0x19,'437',0x1A,'850',0x1B,'437',0x1C,'863',0x1D,'850',0x1F,'852',0x22,'852',0x23,'852',0x24,'860',0x25,'850',0x26,'866',0x37,'850',0x40,'852',0x4D,'936',0x4E,'949',0x4F,'950',0x50,'874',0x57,'1252',0x58,'1252',0x59,'1252',0x64,'852',0x65,'866',0x66,'865',0x67,'861',0x6A,'737',0x6B,'857',0x6C,'863',0x78,'950',0x79,'949',0x7A,'936',0x7B,'932',0x7C,'874',0x86,'737',0x87,'852',0x88,'857',0xC8,'1250',0xC9,'1251',0xCA,'1254',0xCB,'1253',0xCC,'1257'];
|
|
@@ -21271,11 +21282,12 @@ ${svg}
|
|
|
21271
21282
|
// @src is a Buffer or ArrayBuffer or filename
|
|
21272
21283
|
//
|
|
21273
21284
|
function DbfReader(src, encodingArg) {
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
var
|
|
21285
|
+
var opts = {
|
|
21286
|
+
cacheSize: 0x2000000, // 32MB
|
|
21287
|
+
bufferSize: 0x400000 // 4MB
|
|
21288
|
+
};
|
|
21289
|
+
var dbfFile = utils.isString(src) ? new FileReader(src, opts) : new BufferReader(src);
|
|
21290
|
+
var header = readHeader(dbfFile);
|
|
21279
21291
|
|
|
21280
21292
|
// encoding and fields are set on first access
|
|
21281
21293
|
var fields;
|
|
@@ -21291,7 +21303,11 @@ ${svg}
|
|
|
21291
21303
|
|
|
21292
21304
|
this.getFields = getFieldNames;
|
|
21293
21305
|
|
|
21294
|
-
|
|
21306
|
+
// TODO: switch to streaming output under Node.js
|
|
21307
|
+
this.getBuffer = function() {
|
|
21308
|
+
return dbfFile.readSync(0, dbfFile.size());
|
|
21309
|
+
// return bin.buffer();
|
|
21310
|
+
};
|
|
21295
21311
|
|
|
21296
21312
|
this.deleteField = function(f) {
|
|
21297
21313
|
prepareToRead();
|
|
@@ -21332,7 +21348,10 @@ ${svg}
|
|
|
21332
21348
|
});
|
|
21333
21349
|
}
|
|
21334
21350
|
|
|
21335
|
-
function readHeader(
|
|
21351
|
+
function readHeader(reader) {
|
|
21352
|
+
// fetch enough bytes to accomodate any header
|
|
21353
|
+
var maxHeaderLen = 32 * 256 + 1; // 255 fields * fieldRecSize + headerRecSize + terminator
|
|
21354
|
+
var bin = reader.readToBinArray(0, Math.min(maxHeaderLen, reader.size()));
|
|
21336
21355
|
bin.position(0).littleEndian();
|
|
21337
21356
|
var header = {
|
|
21338
21357
|
version: bin.readInt8(),
|
|
@@ -21418,30 +21437,32 @@ ${svg}
|
|
|
21418
21437
|
return new Function('return {' + args.join(',') + '};');
|
|
21419
21438
|
}
|
|
21420
21439
|
|
|
21421
|
-
function findEofPos(bin) {
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
}
|
|
21440
|
+
// function findEofPos(bin) {
|
|
21441
|
+
// var pos = bin.size() - 1;
|
|
21442
|
+
// if (bin.peek(pos) != 0x1A) { // last byte may or may not be EOF
|
|
21443
|
+
// pos++;
|
|
21444
|
+
// }
|
|
21445
|
+
// return pos;
|
|
21446
|
+
// }
|
|
21428
21447
|
|
|
21429
21448
|
function getRecordReader() {
|
|
21430
21449
|
prepareToRead();
|
|
21431
21450
|
var readers = fields.map(getFieldReader),
|
|
21432
|
-
eofOffs = findEofPos(bin),
|
|
21433
21451
|
create = getRecordConstructor(),
|
|
21434
21452
|
values = [];
|
|
21435
21453
|
|
|
21436
21454
|
return function readRow(r) {
|
|
21437
|
-
var
|
|
21455
|
+
var bin = dbfFile.readToBinArray(getRowOffset(r), header.recordSize),
|
|
21456
|
+
rowOffs = bin.position(),
|
|
21438
21457
|
fieldOffs, field;
|
|
21458
|
+
if (bin.bytesLeft() < header.recordSize ||
|
|
21459
|
+
bin.bytesLeft() == header.recordSize && bin.peek(bin.size() - 1) == 0x1A) {
|
|
21460
|
+
// check for observed data error: last data byte contains EOF
|
|
21461
|
+
stop('Invalid DBF file: encountered end-of-file while reading data');
|
|
21462
|
+
}
|
|
21439
21463
|
for (var c=0, cols=fields.length; c<cols; c++) {
|
|
21440
21464
|
field = fields[c];
|
|
21441
|
-
fieldOffs =
|
|
21442
|
-
if (fieldOffs + field.size > eofOffs) {
|
|
21443
|
-
stop('Invalid DBF file: encountered end-of-file while reading data');
|
|
21444
|
-
}
|
|
21465
|
+
fieldOffs = rowOffs + field.columnOffset;
|
|
21445
21466
|
bin.position(fieldOffs);
|
|
21446
21467
|
values[c] = readers[c](bin, field.size);
|
|
21447
21468
|
}
|
|
@@ -21499,11 +21520,12 @@ ${svg}
|
|
|
21499
21520
|
|
|
21500
21521
|
// Show a sample of decoded text if non-ascii-range text has been found
|
|
21501
21522
|
if (encoding && samples.length > 0) {
|
|
21523
|
+
msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
|
|
21524
|
+
message(msg);
|
|
21502
21525
|
msg = decodeSamples(encoding, samples);
|
|
21503
21526
|
msg = formatStringsAsGrid(msg.split('\n'));
|
|
21504
21527
|
msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
|
|
21505
|
-
msg
|
|
21506
|
-
message(msg);
|
|
21528
|
+
verbose(msg);
|
|
21507
21529
|
}
|
|
21508
21530
|
return encoding;
|
|
21509
21531
|
}
|
|
@@ -21531,14 +21553,17 @@ ${svg}
|
|
|
21531
21553
|
var maxSamples = 50;
|
|
21532
21554
|
var buf = utils.createBuffer(256);
|
|
21533
21555
|
var index = {};
|
|
21534
|
-
var f, chars, sample, hash;
|
|
21556
|
+
var f, chars, sample, hash, bin, rowOffs;
|
|
21535
21557
|
// include non-ascii field names, if any
|
|
21536
21558
|
samples = getNonAsciiHeaders();
|
|
21537
21559
|
for (var r=0; r<rows; r++) {
|
|
21560
|
+
bin = dbfFile.readToBinArray(getRowOffset(r), header.recordSize);
|
|
21561
|
+
rowOffs = bin.position();
|
|
21538
21562
|
for (var c=0; c<cols; c++) {
|
|
21539
21563
|
if (samples.length >= maxSamples) break;
|
|
21540
21564
|
f = stringFields[c];
|
|
21541
|
-
bin.position(getRowOffset(r) + f.columnOffset);
|
|
21565
|
+
// bin.position(getRowOffset(r) + f.columnOffset);
|
|
21566
|
+
bin.position(rowOffs + f.columnOffset);
|
|
21542
21567
|
chars = readStringBytes(bin, f.size, buf);
|
|
21543
21568
|
if (chars > 0 && bufferContainsHighBit(buf, chars)) {
|
|
21544
21569
|
sample = utils.createBuffer(buf.slice(0, chars)); //
|
|
@@ -21554,9 +21579,9 @@ ${svg}
|
|
|
21554
21579
|
}
|
|
21555
21580
|
}
|
|
21556
21581
|
|
|
21557
|
-
function importDbfTable(
|
|
21582
|
+
function importDbfTable(src, o) {
|
|
21558
21583
|
var opts = o || {};
|
|
21559
|
-
return new ShapefileTable(
|
|
21584
|
+
return new ShapefileTable(src, opts.encoding);
|
|
21560
21585
|
}
|
|
21561
21586
|
|
|
21562
21587
|
// Implements the DataTable api for DBF file data.
|
|
@@ -21565,8 +21590,8 @@ ${svg}
|
|
|
21565
21590
|
// just the shapes and exporting in Shapefile format.
|
|
21566
21591
|
// TODO: consider accepting just the filename, so buffer doesn't consume memory needlessly.
|
|
21567
21592
|
//
|
|
21568
|
-
function ShapefileTable(
|
|
21569
|
-
var reader = new DbfReader(
|
|
21593
|
+
function ShapefileTable(src, encoding) {
|
|
21594
|
+
var reader = new DbfReader(src, encoding),
|
|
21570
21595
|
altered = false,
|
|
21571
21596
|
table;
|
|
21572
21597
|
|
|
@@ -21575,15 +21600,23 @@ ${svg}
|
|
|
21575
21600
|
// export DBF records on first table access
|
|
21576
21601
|
table = new DataTable(reader.readRows());
|
|
21577
21602
|
reader = null;
|
|
21578
|
-
|
|
21603
|
+
src = null; // null out references to DBF data for g.c.
|
|
21579
21604
|
}
|
|
21580
21605
|
return table;
|
|
21581
21606
|
}
|
|
21582
21607
|
|
|
21583
21608
|
this.exportAsDbf = function(opts) {
|
|
21584
|
-
// export original dbf bytes if possible
|
|
21609
|
+
// export original dbf bytes if possible
|
|
21610
|
+
// (e.g. if the data attributes haven't changed)
|
|
21585
21611
|
var useOriginal = !!reader && !altered && !opts.field_order && !opts.encoding;
|
|
21586
|
-
if (useOriginal)
|
|
21612
|
+
if (useOriginal) {
|
|
21613
|
+
try {
|
|
21614
|
+
// Maximum Buffer in current Node.js is 2GB
|
|
21615
|
+
// We fall back to import-export if getBuffer() fails.
|
|
21616
|
+
// This may produce a buffer that does not exceed the maximum size.
|
|
21617
|
+
return reader.getBuffer();
|
|
21618
|
+
} catch(e) {}
|
|
21619
|
+
}
|
|
21587
21620
|
return Dbf.exportRecords(getTable().getRecords(), opts.encoding, opts.field_order);
|
|
21588
21621
|
};
|
|
21589
21622
|
|
|
@@ -23584,6 +23617,10 @@ ${svg}
|
|
|
23584
23617
|
if (obj.prj) {
|
|
23585
23618
|
dataset.info.prj = obj.prj.content;
|
|
23586
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
|
+
}
|
|
23587
23624
|
return dataset;
|
|
23588
23625
|
}
|
|
23589
23626
|
|
|
@@ -23593,7 +23630,7 @@ ${svg}
|
|
|
23593
23630
|
if (input.cpg && !opts.encoding) {
|
|
23594
23631
|
opts.encoding = input.cpg.content;
|
|
23595
23632
|
}
|
|
23596
|
-
table = importDbfTable(input.dbf.content, opts);
|
|
23633
|
+
table = importDbfTable(input.dbf.content || input.dbf.filename, opts);
|
|
23597
23634
|
return {
|
|
23598
23635
|
info: {},
|
|
23599
23636
|
layers: [{data: table}]
|
|
@@ -23691,18 +23728,10 @@ ${svg}
|
|
|
23691
23728
|
content;
|
|
23692
23729
|
|
|
23693
23730
|
cli.checkFileExists(path, cache);
|
|
23694
|
-
if (fileType == 'shp' && !cached) {
|
|
23695
|
-
//
|
|
23731
|
+
if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf') && !cached) {
|
|
23732
|
+
// these file types are read incrementally
|
|
23696
23733
|
content = null;
|
|
23697
23734
|
|
|
23698
|
-
} else if (fileType == 'json' && !cached) {
|
|
23699
|
-
// postpone reading of JSON files, to support incremental parsing
|
|
23700
|
-
content = null;
|
|
23701
|
-
|
|
23702
|
-
} else if (fileType == 'text' && !cached) {
|
|
23703
|
-
// content = cli.readFile(path); // read from buffer
|
|
23704
|
-
content = null; // read from file, to support largest files (see mapshaper-delim-import.js)
|
|
23705
|
-
|
|
23706
23735
|
} else if (fileType && isSupportedBinaryInputType(path)) {
|
|
23707
23736
|
content = cli.readFile(path, null, cache);
|
|
23708
23737
|
if (utils.isString(content)) {
|
|
@@ -23759,7 +23788,11 @@ ${svg}
|
|
|
23759
23788
|
obj.shx = {filename: shxPath, content: cli.readFile(shxPath, null, cache)};
|
|
23760
23789
|
}
|
|
23761
23790
|
if (!obj.dbf && cli.isFile(dbfPath, cache)) {
|
|
23762
|
-
obj.dbf = {filename: dbfPath, content: cli.readFile(dbfPath, null, cache)};
|
|
23791
|
+
// obj.dbf = {filename: dbfPath, content: cli.readFile(dbfPath, null, cache)};
|
|
23792
|
+
obj.dbf = {
|
|
23793
|
+
filename: dbfPath,
|
|
23794
|
+
content: (cache && (dbfPath in cache)) ? cli.readFile(dbfPath, null, cache) : null
|
|
23795
|
+
};
|
|
23763
23796
|
}
|
|
23764
23797
|
if (obj.dbf && cli.isFile(cpgPath, cache)) {
|
|
23765
23798
|
obj.cpg = {filename: cpgPath, content: cli.readFile(cpgPath, 'utf-8', cache).trim()};
|
|
@@ -24037,6 +24070,7 @@ ${svg}
|
|
|
24037
24070
|
clearStash(); // prevent errors from overwriting stash
|
|
24038
24071
|
stashVar('current_command', cmd.name);
|
|
24039
24072
|
stashVar('DEBUG', job.settings.DEBUG || cmd.debug);
|
|
24073
|
+
stashVar('VERBOSE', job.settings.VERBOSE || cmd.verbose);
|
|
24040
24074
|
stashVar('QUIET', job.settings.QUIET || cmd.quiet);
|
|
24041
24075
|
stashVar('defs', job.defs);
|
|
24042
24076
|
stashVar('input_files', job.input_files);
|
|
@@ -30463,6 +30497,9 @@ ${svg}
|
|
|
30463
30497
|
targetDataset.arcs = mergedDataset.arcs;
|
|
30464
30498
|
// dissolve clip layer shapes (to remove overlaps and other topological issues
|
|
30465
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);
|
|
30466
30503
|
clipLyr = dissolvePolygonLayer2(clipLyr, mergedDataset, {quiet: true, silent: true});
|
|
30467
30504
|
|
|
30468
30505
|
} else {
|
|
@@ -30864,6 +30901,8 @@ ${svg}
|
|
|
30864
30901
|
getColorizerFunction: getColorizerFunction
|
|
30865
30902
|
});
|
|
30866
30903
|
|
|
30904
|
+
cmd.comment = function() {}; // no-op, so -comment doesn't trigger a parsing error
|
|
30905
|
+
|
|
30867
30906
|
function expressionUsesGeoJSON(exp) {
|
|
30868
30907
|
return exp.includes('this.geojson');
|
|
30869
30908
|
}
|
|
@@ -39778,7 +39817,7 @@ ${svg}
|
|
|
39778
39817
|
function commandAcceptsEmptyTarget(name) {
|
|
39779
39818
|
return name == 'graticule' || name == 'i' || name == 'help' ||
|
|
39780
39819
|
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39781
|
-
name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
|
|
39820
|
+
name == 'include' || name == 'print' || name == 'comment' || name == 'if' || name == 'elif' ||
|
|
39782
39821
|
name == 'else' || name == 'endif';
|
|
39783
39822
|
}
|
|
39784
39823
|
|
|
@@ -39886,6 +39925,9 @@ ${svg}
|
|
|
39886
39925
|
} else if (name == 'colorizer') {
|
|
39887
39926
|
outputLayers = cmd.colorizer(opts);
|
|
39888
39927
|
|
|
39928
|
+
} else if (name == 'comment') {
|
|
39929
|
+
// no-op
|
|
39930
|
+
|
|
39889
39931
|
} else if (name == 'dashlines') {
|
|
39890
39932
|
applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
|
|
39891
39933
|
|
package/package.json
CHANGED
package/www/elements.css
CHANGED
|
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
|
-
<
|
|
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="
|
|
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
|
-
<
|
|
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
|
-
|
|
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 -->
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -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('.
|
|
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('.
|
|
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('.
|
|
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.
|
|
3
|
+
var VERSION = "0.5.118";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -16006,7 +16006,9 @@ ${svg}
|
|
|
16006
16006
|
|
|
16007
16007
|
function initStringField(info, arr, name, encoding) {
|
|
16008
16008
|
var formatter = encoding == 'ascii' ? encodeValueAsAscii : getStringWriterEncoded(encoding);
|
|
16009
|
-
|
|
16009
|
+
// Set minimum field size to 1 byte, for interoperability with PostGIS
|
|
16010
|
+
// (see https://github.com/mbloch/mapshaper/issues/541)
|
|
16011
|
+
var size = 1;
|
|
16010
16012
|
var truncated = 0;
|
|
16011
16013
|
var buffers = arr.map(function(rec) {
|
|
16012
16014
|
var strval = convertValueToString(rec[name]);
|
|
@@ -17213,7 +17215,7 @@ ${svg}
|
|
|
17213
17215
|
function guessInputFileType(file) {
|
|
17214
17216
|
var ext = getFileExtension(file || '').toLowerCase(),
|
|
17215
17217
|
type = null;
|
|
17216
|
-
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') {
|
|
17217
17219
|
type = ext;
|
|
17218
17220
|
} else if (/json$/.test(ext)) {
|
|
17219
17221
|
type = 'json';
|
|
@@ -17626,7 +17628,9 @@ ${svg}
|
|
|
17626
17628
|
binArr, buf;
|
|
17627
17629
|
|
|
17628
17630
|
this.readToBinArray = function(start, length) {
|
|
17629
|
-
if (bufSize < start + length)
|
|
17631
|
+
if (bufSize < start + length) {
|
|
17632
|
+
error("Out-of-range error");
|
|
17633
|
+
}
|
|
17630
17634
|
if (!binArr) binArr = new BinArray(src);
|
|
17631
17635
|
binArr.position(start);
|
|
17632
17636
|
return binArr;
|
|
@@ -21084,6 +21088,10 @@ ${svg}
|
|
|
21084
21088
|
parser.command('colors')
|
|
21085
21089
|
.describe('print list of color scheme names');
|
|
21086
21090
|
|
|
21091
|
+
parser.command('comment')
|
|
21092
|
+
.describe('add a comment to the sequence of commands')
|
|
21093
|
+
.flag('multi_arg');
|
|
21094
|
+
|
|
21087
21095
|
parser.command('encodings')
|
|
21088
21096
|
.describe('print list of supported text encodings (for .dbf import)');
|
|
21089
21097
|
|
|
@@ -21135,6 +21143,9 @@ ${svg}
|
|
|
21135
21143
|
// http://www.digitalpreservation.gov/formats/fdd/fdd000325.shtml
|
|
21136
21144
|
// http://www.clicketyclick.dk/databases/xbase/format/index.html
|
|
21137
21145
|
// http://www.clicketyclick.dk/databases/xbase/format/data_types.html
|
|
21146
|
+
// esri docs:
|
|
21147
|
+
// https://support.esri.com/en/technical-article/000007920
|
|
21148
|
+
// https://desktop.arcgis.com/en/arcmap/latest/manage-data/shapefiles/geoprocessing-considerations-for-shapefile-output.htm
|
|
21138
21149
|
|
|
21139
21150
|
// source: http://webhelp.esri.com/arcpad/8.0/referenceguide/index.htm#locales/task_code.htm
|
|
21140
21151
|
var languageIds = [0x01,'437',0x02,'850',0x03,'1252',0x08,'865',0x09,'437',0x0A,'850',0x0B,'437',0x0D,'437',0x0E,'850',0x0F,'437',0x10,'850',0x11,'437',0x12,'850',0x13,'932',0x14,'850',0x15,'437',0x16,'850',0x17,'865',0x18,'437',0x19,'437',0x1A,'850',0x1B,'437',0x1C,'863',0x1D,'850',0x1F,'852',0x22,'852',0x23,'852',0x24,'860',0x25,'850',0x26,'866',0x37,'850',0x40,'852',0x4D,'936',0x4E,'949',0x4F,'950',0x50,'874',0x57,'1252',0x58,'1252',0x59,'1252',0x64,'852',0x65,'866',0x66,'865',0x67,'861',0x6A,'737',0x6B,'857',0x6C,'863',0x78,'950',0x79,'949',0x7A,'936',0x7B,'932',0x7C,'874',0x86,'737',0x87,'852',0x88,'857',0xC8,'1250',0xC9,'1251',0xCA,'1254',0xCB,'1253',0xCC,'1257'];
|
|
@@ -21271,11 +21282,12 @@ ${svg}
|
|
|
21271
21282
|
// @src is a Buffer or ArrayBuffer or filename
|
|
21272
21283
|
//
|
|
21273
21284
|
function DbfReader(src, encodingArg) {
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
var
|
|
21285
|
+
var opts = {
|
|
21286
|
+
cacheSize: 0x2000000, // 32MB
|
|
21287
|
+
bufferSize: 0x400000 // 4MB
|
|
21288
|
+
};
|
|
21289
|
+
var dbfFile = utils.isString(src) ? new FileReader(src, opts) : new BufferReader(src);
|
|
21290
|
+
var header = readHeader(dbfFile);
|
|
21279
21291
|
|
|
21280
21292
|
// encoding and fields are set on first access
|
|
21281
21293
|
var fields;
|
|
@@ -21291,7 +21303,11 @@ ${svg}
|
|
|
21291
21303
|
|
|
21292
21304
|
this.getFields = getFieldNames;
|
|
21293
21305
|
|
|
21294
|
-
|
|
21306
|
+
// TODO: switch to streaming output under Node.js
|
|
21307
|
+
this.getBuffer = function() {
|
|
21308
|
+
return dbfFile.readSync(0, dbfFile.size());
|
|
21309
|
+
// return bin.buffer();
|
|
21310
|
+
};
|
|
21295
21311
|
|
|
21296
21312
|
this.deleteField = function(f) {
|
|
21297
21313
|
prepareToRead();
|
|
@@ -21332,7 +21348,10 @@ ${svg}
|
|
|
21332
21348
|
});
|
|
21333
21349
|
}
|
|
21334
21350
|
|
|
21335
|
-
function readHeader(
|
|
21351
|
+
function readHeader(reader) {
|
|
21352
|
+
// fetch enough bytes to accomodate any header
|
|
21353
|
+
var maxHeaderLen = 32 * 256 + 1; // 255 fields * fieldRecSize + headerRecSize + terminator
|
|
21354
|
+
var bin = reader.readToBinArray(0, Math.min(maxHeaderLen, reader.size()));
|
|
21336
21355
|
bin.position(0).littleEndian();
|
|
21337
21356
|
var header = {
|
|
21338
21357
|
version: bin.readInt8(),
|
|
@@ -21418,30 +21437,32 @@ ${svg}
|
|
|
21418
21437
|
return new Function('return {' + args.join(',') + '};');
|
|
21419
21438
|
}
|
|
21420
21439
|
|
|
21421
|
-
function findEofPos(bin) {
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
}
|
|
21440
|
+
// function findEofPos(bin) {
|
|
21441
|
+
// var pos = bin.size() - 1;
|
|
21442
|
+
// if (bin.peek(pos) != 0x1A) { // last byte may or may not be EOF
|
|
21443
|
+
// pos++;
|
|
21444
|
+
// }
|
|
21445
|
+
// return pos;
|
|
21446
|
+
// }
|
|
21428
21447
|
|
|
21429
21448
|
function getRecordReader() {
|
|
21430
21449
|
prepareToRead();
|
|
21431
21450
|
var readers = fields.map(getFieldReader),
|
|
21432
|
-
eofOffs = findEofPos(bin),
|
|
21433
21451
|
create = getRecordConstructor(),
|
|
21434
21452
|
values = [];
|
|
21435
21453
|
|
|
21436
21454
|
return function readRow(r) {
|
|
21437
|
-
var
|
|
21455
|
+
var bin = dbfFile.readToBinArray(getRowOffset(r), header.recordSize),
|
|
21456
|
+
rowOffs = bin.position(),
|
|
21438
21457
|
fieldOffs, field;
|
|
21458
|
+
if (bin.bytesLeft() < header.recordSize ||
|
|
21459
|
+
bin.bytesLeft() == header.recordSize && bin.peek(bin.size() - 1) == 0x1A) {
|
|
21460
|
+
// check for observed data error: last data byte contains EOF
|
|
21461
|
+
stop('Invalid DBF file: encountered end-of-file while reading data');
|
|
21462
|
+
}
|
|
21439
21463
|
for (var c=0, cols=fields.length; c<cols; c++) {
|
|
21440
21464
|
field = fields[c];
|
|
21441
|
-
fieldOffs =
|
|
21442
|
-
if (fieldOffs + field.size > eofOffs) {
|
|
21443
|
-
stop('Invalid DBF file: encountered end-of-file while reading data');
|
|
21444
|
-
}
|
|
21465
|
+
fieldOffs = rowOffs + field.columnOffset;
|
|
21445
21466
|
bin.position(fieldOffs);
|
|
21446
21467
|
values[c] = readers[c](bin, field.size);
|
|
21447
21468
|
}
|
|
@@ -21499,11 +21520,12 @@ ${svg}
|
|
|
21499
21520
|
|
|
21500
21521
|
// Show a sample of decoded text if non-ascii-range text has been found
|
|
21501
21522
|
if (encoding && samples.length > 0) {
|
|
21523
|
+
msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
|
|
21524
|
+
message(msg);
|
|
21502
21525
|
msg = decodeSamples(encoding, samples);
|
|
21503
21526
|
msg = formatStringsAsGrid(msg.split('\n'));
|
|
21504
21527
|
msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
|
|
21505
|
-
msg
|
|
21506
|
-
message(msg);
|
|
21528
|
+
verbose(msg);
|
|
21507
21529
|
}
|
|
21508
21530
|
return encoding;
|
|
21509
21531
|
}
|
|
@@ -21531,14 +21553,17 @@ ${svg}
|
|
|
21531
21553
|
var maxSamples = 50;
|
|
21532
21554
|
var buf = utils.createBuffer(256);
|
|
21533
21555
|
var index = {};
|
|
21534
|
-
var f, chars, sample, hash;
|
|
21556
|
+
var f, chars, sample, hash, bin, rowOffs;
|
|
21535
21557
|
// include non-ascii field names, if any
|
|
21536
21558
|
samples = getNonAsciiHeaders();
|
|
21537
21559
|
for (var r=0; r<rows; r++) {
|
|
21560
|
+
bin = dbfFile.readToBinArray(getRowOffset(r), header.recordSize);
|
|
21561
|
+
rowOffs = bin.position();
|
|
21538
21562
|
for (var c=0; c<cols; c++) {
|
|
21539
21563
|
if (samples.length >= maxSamples) break;
|
|
21540
21564
|
f = stringFields[c];
|
|
21541
|
-
bin.position(getRowOffset(r) + f.columnOffset);
|
|
21565
|
+
// bin.position(getRowOffset(r) + f.columnOffset);
|
|
21566
|
+
bin.position(rowOffs + f.columnOffset);
|
|
21542
21567
|
chars = readStringBytes(bin, f.size, buf);
|
|
21543
21568
|
if (chars > 0 && bufferContainsHighBit(buf, chars)) {
|
|
21544
21569
|
sample = utils.createBuffer(buf.slice(0, chars)); //
|
|
@@ -21554,9 +21579,9 @@ ${svg}
|
|
|
21554
21579
|
}
|
|
21555
21580
|
}
|
|
21556
21581
|
|
|
21557
|
-
function importDbfTable(
|
|
21582
|
+
function importDbfTable(src, o) {
|
|
21558
21583
|
var opts = o || {};
|
|
21559
|
-
return new ShapefileTable(
|
|
21584
|
+
return new ShapefileTable(src, opts.encoding);
|
|
21560
21585
|
}
|
|
21561
21586
|
|
|
21562
21587
|
// Implements the DataTable api for DBF file data.
|
|
@@ -21565,8 +21590,8 @@ ${svg}
|
|
|
21565
21590
|
// just the shapes and exporting in Shapefile format.
|
|
21566
21591
|
// TODO: consider accepting just the filename, so buffer doesn't consume memory needlessly.
|
|
21567
21592
|
//
|
|
21568
|
-
function ShapefileTable(
|
|
21569
|
-
var reader = new DbfReader(
|
|
21593
|
+
function ShapefileTable(src, encoding) {
|
|
21594
|
+
var reader = new DbfReader(src, encoding),
|
|
21570
21595
|
altered = false,
|
|
21571
21596
|
table;
|
|
21572
21597
|
|
|
@@ -21575,15 +21600,23 @@ ${svg}
|
|
|
21575
21600
|
// export DBF records on first table access
|
|
21576
21601
|
table = new DataTable(reader.readRows());
|
|
21577
21602
|
reader = null;
|
|
21578
|
-
|
|
21603
|
+
src = null; // null out references to DBF data for g.c.
|
|
21579
21604
|
}
|
|
21580
21605
|
return table;
|
|
21581
21606
|
}
|
|
21582
21607
|
|
|
21583
21608
|
this.exportAsDbf = function(opts) {
|
|
21584
|
-
// export original dbf bytes if possible
|
|
21609
|
+
// export original dbf bytes if possible
|
|
21610
|
+
// (e.g. if the data attributes haven't changed)
|
|
21585
21611
|
var useOriginal = !!reader && !altered && !opts.field_order && !opts.encoding;
|
|
21586
|
-
if (useOriginal)
|
|
21612
|
+
if (useOriginal) {
|
|
21613
|
+
try {
|
|
21614
|
+
// Maximum Buffer in current Node.js is 2GB
|
|
21615
|
+
// We fall back to import-export if getBuffer() fails.
|
|
21616
|
+
// This may produce a buffer that does not exceed the maximum size.
|
|
21617
|
+
return reader.getBuffer();
|
|
21618
|
+
} catch(e) {}
|
|
21619
|
+
}
|
|
21587
21620
|
return Dbf.exportRecords(getTable().getRecords(), opts.encoding, opts.field_order);
|
|
21588
21621
|
};
|
|
21589
21622
|
|
|
@@ -23584,6 +23617,10 @@ ${svg}
|
|
|
23584
23617
|
if (obj.prj) {
|
|
23585
23618
|
dataset.info.prj = obj.prj.content;
|
|
23586
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
|
+
}
|
|
23587
23624
|
return dataset;
|
|
23588
23625
|
}
|
|
23589
23626
|
|
|
@@ -23593,7 +23630,7 @@ ${svg}
|
|
|
23593
23630
|
if (input.cpg && !opts.encoding) {
|
|
23594
23631
|
opts.encoding = input.cpg.content;
|
|
23595
23632
|
}
|
|
23596
|
-
table = importDbfTable(input.dbf.content, opts);
|
|
23633
|
+
table = importDbfTable(input.dbf.content || input.dbf.filename, opts);
|
|
23597
23634
|
return {
|
|
23598
23635
|
info: {},
|
|
23599
23636
|
layers: [{data: table}]
|
|
@@ -23691,18 +23728,10 @@ ${svg}
|
|
|
23691
23728
|
content;
|
|
23692
23729
|
|
|
23693
23730
|
cli.checkFileExists(path, cache);
|
|
23694
|
-
if (fileType == 'shp' && !cached) {
|
|
23695
|
-
//
|
|
23731
|
+
if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf') && !cached) {
|
|
23732
|
+
// these file types are read incrementally
|
|
23696
23733
|
content = null;
|
|
23697
23734
|
|
|
23698
|
-
} else if (fileType == 'json' && !cached) {
|
|
23699
|
-
// postpone reading of JSON files, to support incremental parsing
|
|
23700
|
-
content = null;
|
|
23701
|
-
|
|
23702
|
-
} else if (fileType == 'text' && !cached) {
|
|
23703
|
-
// content = cli.readFile(path); // read from buffer
|
|
23704
|
-
content = null; // read from file, to support largest files (see mapshaper-delim-import.js)
|
|
23705
|
-
|
|
23706
23735
|
} else if (fileType && isSupportedBinaryInputType(path)) {
|
|
23707
23736
|
content = cli.readFile(path, null, cache);
|
|
23708
23737
|
if (utils.isString(content)) {
|
|
@@ -23759,7 +23788,11 @@ ${svg}
|
|
|
23759
23788
|
obj.shx = {filename: shxPath, content: cli.readFile(shxPath, null, cache)};
|
|
23760
23789
|
}
|
|
23761
23790
|
if (!obj.dbf && cli.isFile(dbfPath, cache)) {
|
|
23762
|
-
obj.dbf = {filename: dbfPath, content: cli.readFile(dbfPath, null, cache)};
|
|
23791
|
+
// obj.dbf = {filename: dbfPath, content: cli.readFile(dbfPath, null, cache)};
|
|
23792
|
+
obj.dbf = {
|
|
23793
|
+
filename: dbfPath,
|
|
23794
|
+
content: (cache && (dbfPath in cache)) ? cli.readFile(dbfPath, null, cache) : null
|
|
23795
|
+
};
|
|
23763
23796
|
}
|
|
23764
23797
|
if (obj.dbf && cli.isFile(cpgPath, cache)) {
|
|
23765
23798
|
obj.cpg = {filename: cpgPath, content: cli.readFile(cpgPath, 'utf-8', cache).trim()};
|
|
@@ -24037,6 +24070,7 @@ ${svg}
|
|
|
24037
24070
|
clearStash(); // prevent errors from overwriting stash
|
|
24038
24071
|
stashVar('current_command', cmd.name);
|
|
24039
24072
|
stashVar('DEBUG', job.settings.DEBUG || cmd.debug);
|
|
24073
|
+
stashVar('VERBOSE', job.settings.VERBOSE || cmd.verbose);
|
|
24040
24074
|
stashVar('QUIET', job.settings.QUIET || cmd.quiet);
|
|
24041
24075
|
stashVar('defs', job.defs);
|
|
24042
24076
|
stashVar('input_files', job.input_files);
|
|
@@ -30463,6 +30497,9 @@ ${svg}
|
|
|
30463
30497
|
targetDataset.arcs = mergedDataset.arcs;
|
|
30464
30498
|
// dissolve clip layer shapes (to remove overlaps and other topological issues
|
|
30465
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);
|
|
30466
30503
|
clipLyr = dissolvePolygonLayer2(clipLyr, mergedDataset, {quiet: true, silent: true});
|
|
30467
30504
|
|
|
30468
30505
|
} else {
|
|
@@ -30864,6 +30901,8 @@ ${svg}
|
|
|
30864
30901
|
getColorizerFunction: getColorizerFunction
|
|
30865
30902
|
});
|
|
30866
30903
|
|
|
30904
|
+
cmd.comment = function() {}; // no-op, so -comment doesn't trigger a parsing error
|
|
30905
|
+
|
|
30867
30906
|
function expressionUsesGeoJSON(exp) {
|
|
30868
30907
|
return exp.includes('this.geojson');
|
|
30869
30908
|
}
|
|
@@ -39778,7 +39817,7 @@ ${svg}
|
|
|
39778
39817
|
function commandAcceptsEmptyTarget(name) {
|
|
39779
39818
|
return name == 'graticule' || name == 'i' || name == 'help' ||
|
|
39780
39819
|
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39781
|
-
name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
|
|
39820
|
+
name == 'include' || name == 'print' || name == 'comment' || name == 'if' || name == 'elif' ||
|
|
39782
39821
|
name == 'else' || name == 'endif';
|
|
39783
39822
|
}
|
|
39784
39823
|
|
|
@@ -39886,6 +39925,9 @@ ${svg}
|
|
|
39886
39925
|
} else if (name == 'colorizer') {
|
|
39887
39926
|
outputLayers = cmd.colorizer(opts);
|
|
39888
39927
|
|
|
39928
|
+
} else if (name == 'comment') {
|
|
39929
|
+
// no-op
|
|
39930
|
+
|
|
39889
39931
|
} else if (name == 'dashlines') {
|
|
39890
39932
|
applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
|
|
39891
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:
|
|
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
|
|
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:
|
|
476
|
+
font-size: 19px;
|
|
477
|
+
line-height: 1.1;
|
|
476
478
|
padding: 0;
|
|
477
|
-
margin: 0 0 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:
|
|
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:
|
|
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
|
-
|
|
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
|
}
|