mapshaper 0.5.65 → 0.5.69
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 +14 -0
- package/mapshaper.js +125 -42
- package/package.json +3 -2
- package/www/elements.css +1 -1
- package/www/mapshaper-gui.js +196 -134
- package/www/mapshaper.js +125 -42
- package/www/page.css +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
v0.5.69
|
|
2
|
+
* Added undocumented -ignore command.
|
|
3
|
+
* Bug fix
|
|
4
|
+
|
|
5
|
+
v0.5.68
|
|
6
|
+
* Bug fix
|
|
7
|
+
|
|
8
|
+
v0.5.67
|
|
9
|
+
* Bug fix
|
|
10
|
+
|
|
11
|
+
v0.5.66
|
|
12
|
+
* Improve interactive selection.
|
|
13
|
+
* Added undocumented -define command.
|
|
14
|
+
|
|
1
15
|
v0.5.65
|
|
2
16
|
* Web UI zoom buttons respond to variable-length clicks.
|
|
3
17
|
* Bug fixes
|
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.68";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -1167,6 +1167,10 @@
|
|
|
1167
1167
|
throw new UserError(formatLogArgs(arguments));
|
|
1168
1168
|
};
|
|
1169
1169
|
|
|
1170
|
+
var _interrupt = function() {
|
|
1171
|
+
throw new NonFatalError(formatLogArgs(arguments));
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1170
1174
|
var _message = function() {
|
|
1171
1175
|
logArgs(arguments);
|
|
1172
1176
|
};
|
|
@@ -1185,10 +1189,14 @@
|
|
|
1185
1189
|
}
|
|
1186
1190
|
|
|
1187
1191
|
// Handle an error caused by invalid input or misuse of API
|
|
1188
|
-
function stop
|
|
1192
|
+
function stop() {
|
|
1189
1193
|
_stop.apply(null, utils.toArray(arguments));
|
|
1190
1194
|
}
|
|
1191
1195
|
|
|
1196
|
+
function interrupt() {
|
|
1197
|
+
_interrupt.apply(null, utils.toArray(arguments));
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1192
1200
|
// Print a status message
|
|
1193
1201
|
function message() {
|
|
1194
1202
|
_message.apply(null, messageArgs(arguments));
|
|
@@ -1228,7 +1236,9 @@
|
|
|
1228
1236
|
if (utils.isString(err)) {
|
|
1229
1237
|
err = new UserError(err);
|
|
1230
1238
|
}
|
|
1231
|
-
if (err.name == '
|
|
1239
|
+
if (err.name == 'NonFatalError') {
|
|
1240
|
+
console.error(messageArgs([err.message]).join(' '));
|
|
1241
|
+
} else if (err.name == 'UserError') {
|
|
1232
1242
|
msg = err.message;
|
|
1233
1243
|
if (!/Error/.test(msg)) {
|
|
1234
1244
|
msg = "Error: " + msg;
|
|
@@ -1248,6 +1258,12 @@
|
|
|
1248
1258
|
return err;
|
|
1249
1259
|
}
|
|
1250
1260
|
|
|
1261
|
+
function NonFatalError(msg) {
|
|
1262
|
+
var err = new Error(msg);
|
|
1263
|
+
err.name = 'NonFatalError';
|
|
1264
|
+
return err;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1251
1267
|
function formatColumns(arr, alignments) {
|
|
1252
1268
|
var widths = arr.reduce(function(memo, line) {
|
|
1253
1269
|
return line.map(function(str, i) {
|
|
@@ -1308,6 +1324,7 @@
|
|
|
1308
1324
|
loggingEnabled: loggingEnabled,
|
|
1309
1325
|
error: error,
|
|
1310
1326
|
stop: stop,
|
|
1327
|
+
interrupt: interrupt,
|
|
1311
1328
|
message: message,
|
|
1312
1329
|
setLoggingFunctions: setLoggingFunctions,
|
|
1313
1330
|
print: print,
|
|
@@ -1315,6 +1332,7 @@
|
|
|
1315
1332
|
debug: debug,
|
|
1316
1333
|
printError: printError,
|
|
1317
1334
|
UserError: UserError,
|
|
1335
|
+
NonFatalError: NonFatalError,
|
|
1318
1336
|
formatColumns: formatColumns,
|
|
1319
1337
|
formatStringsAsGrid: formatStringsAsGrid,
|
|
1320
1338
|
formatLogArgs: formatLogArgs,
|
|
@@ -9035,7 +9053,8 @@
|
|
|
9035
9053
|
var i = s.indexOf('.');
|
|
9036
9054
|
return hasDot ? i > -1 : i == -1;
|
|
9037
9055
|
};
|
|
9038
|
-
|
|
9056
|
+
var vars = utils.uniq(matches.filter(f));
|
|
9057
|
+
return vars;
|
|
9039
9058
|
}
|
|
9040
9059
|
|
|
9041
9060
|
// Return array of objects with properties assigned via dot notation
|
|
@@ -9100,23 +9119,24 @@
|
|
|
9100
9119
|
}
|
|
9101
9120
|
|
|
9102
9121
|
function getExpressionContext(lyr, mixins, opts) {
|
|
9122
|
+
var defs = getStateVar('defs');
|
|
9103
9123
|
var env = getBaseContext();
|
|
9104
9124
|
var ctx = {};
|
|
9105
9125
|
var fields = lyr.data ? lyr.data.getFields() : [];
|
|
9106
9126
|
opts = opts || {};
|
|
9107
9127
|
addUtils(env); // mix in round(), sprintf(), etc.
|
|
9108
|
-
if (
|
|
9128
|
+
if (fields.length > 0) {
|
|
9109
9129
|
// default to null values, so assignments to missing data properties
|
|
9110
9130
|
// are applied to the data record, not the global object
|
|
9111
9131
|
nullifyUnsetProperties(fields, env);
|
|
9112
9132
|
}
|
|
9113
9133
|
// Add global 'defs' to the expression context
|
|
9114
|
-
mixins = utils.defaults(mixins || {},
|
|
9134
|
+
mixins = utils.defaults(mixins || {}, defs);
|
|
9135
|
+
// also add defs as 'global' object
|
|
9136
|
+
env.global = defs;
|
|
9115
9137
|
Object.keys(mixins).forEach(function(key) {
|
|
9116
9138
|
// Catch name collisions between data fields and user-defined functions
|
|
9117
9139
|
var d = Object.getOwnPropertyDescriptor(mixins, key);
|
|
9118
|
-
if (key in env) {
|
|
9119
|
-
}
|
|
9120
9140
|
if (d.get) {
|
|
9121
9141
|
// copy accessor function from mixins to context
|
|
9122
9142
|
Object.defineProperty(ctx, key, {get: d.get}); // copy getter function to context
|
|
@@ -11465,13 +11485,22 @@
|
|
|
11465
11485
|
var T = {
|
|
11466
11486
|
stack: [],
|
|
11467
11487
|
start: function() {
|
|
11468
|
-
T.stack.push(
|
|
11488
|
+
T.stack.push(Date.now());
|
|
11469
11489
|
},
|
|
11470
11490
|
stop: function() {
|
|
11471
|
-
return (
|
|
11491
|
+
return (Date.now() - T.stack.pop()) + 'ms';
|
|
11472
11492
|
}
|
|
11473
11493
|
};
|
|
11474
11494
|
|
|
11495
|
+
function tick(msg) {
|
|
11496
|
+
var now = Date.now();
|
|
11497
|
+
var elapsed = tickTime ? ' - ' + (now - tickTime) + 'ms' : '';
|
|
11498
|
+
tickTime = now;
|
|
11499
|
+
console.log((msg || '') + elapsed);
|
|
11500
|
+
}
|
|
11501
|
+
|
|
11502
|
+
var tickTime = 0;
|
|
11503
|
+
|
|
11475
11504
|
// Create a mosaic layer from a dataset (useful for debugging commands like -clean
|
|
11476
11505
|
// that create a mosaic as an intermediate data structure)
|
|
11477
11506
|
// Create additional layers if the "debug" flag is present
|
|
@@ -14295,7 +14324,7 @@
|
|
|
14295
14324
|
joinStr = obj.tag == 'text' || obj.tag == 'tspan' ? '' : '\n';
|
|
14296
14325
|
svg += '>' + joinStr;
|
|
14297
14326
|
if (obj.value) {
|
|
14298
|
-
svg += obj.value;
|
|
14327
|
+
svg += stringEscape(obj.value);
|
|
14299
14328
|
}
|
|
14300
14329
|
if (obj.children) {
|
|
14301
14330
|
svg += obj.children.map(stringify).join(joinStr);
|
|
@@ -14318,8 +14347,13 @@
|
|
|
14318
14347
|
"'": '''
|
|
14319
14348
|
};
|
|
14320
14349
|
function stringEscape(s) {
|
|
14321
|
-
return String(s).replace(rxp, function(
|
|
14322
|
-
|
|
14350
|
+
return String(s).replace(rxp, function(match, i) {
|
|
14351
|
+
var entity = map[match];
|
|
14352
|
+
// don't replace & with &
|
|
14353
|
+
if (match == '&' && s.substr(i, entity.length) == entity) {
|
|
14354
|
+
return '&';
|
|
14355
|
+
}
|
|
14356
|
+
return entity;
|
|
14323
14357
|
});
|
|
14324
14358
|
}
|
|
14325
14359
|
|
|
@@ -17129,7 +17163,7 @@ ${svg}
|
|
|
17129
17163
|
c = buf[i];
|
|
17130
17164
|
if (c == DQUOTE) {
|
|
17131
17165
|
inQuotedText = !inQuotedText;
|
|
17132
|
-
} else if (c == CR || c == LF) {
|
|
17166
|
+
} else if ((c == CR || c == LF) && !inQuotedText) {
|
|
17133
17167
|
if (c == CR && i + 1 < bufLen && buf[i + 1] == LF) {
|
|
17134
17168
|
// first half of CRLF pair: advance one byte
|
|
17135
17169
|
i++;
|
|
@@ -17223,6 +17257,7 @@ ${svg}
|
|
|
17223
17257
|
getRowConverter: getRowConverter,
|
|
17224
17258
|
parseDelimHeaderSection: parseDelimHeaderSection,
|
|
17225
17259
|
getDelimFieldFilter: getDelimFieldFilter,
|
|
17260
|
+
readLinesAsString: readLinesAsString,
|
|
17226
17261
|
parseDelimText: parseDelimText
|
|
17227
17262
|
});
|
|
17228
17263
|
|
|
@@ -18404,6 +18439,9 @@ ${svg}
|
|
|
18404
18439
|
type: 'strings',
|
|
18405
18440
|
describe: '[CSV] comma-sep. list of fields to import'
|
|
18406
18441
|
})
|
|
18442
|
+
// .option('csv-comment', {
|
|
18443
|
+
// describe: '[CSV] comment line character(s)'
|
|
18444
|
+
// })
|
|
18407
18445
|
.option('decimal-comma', {
|
|
18408
18446
|
type: 'flag',
|
|
18409
18447
|
describe: '[CSV] import numbers formatted like 1.000,01 or 1 000,01'
|
|
@@ -19153,6 +19191,14 @@ ${svg}
|
|
|
19153
19191
|
.option('target', targetOpt)
|
|
19154
19192
|
.option('no-replace', noReplaceOpt);
|
|
19155
19193
|
|
|
19194
|
+
parser.command('ignore')
|
|
19195
|
+
// .describe('stop processing if a condition is met')
|
|
19196
|
+
.option('empty', {
|
|
19197
|
+
describe: 'ignore empty files',
|
|
19198
|
+
type: 'flag'
|
|
19199
|
+
})
|
|
19200
|
+
.option('target', targetOpt);
|
|
19201
|
+
|
|
19156
19202
|
parser.command('inlay')
|
|
19157
19203
|
.describe('inscribe a polygon layer inside another polygon layer')
|
|
19158
19204
|
.option('source', {
|
|
@@ -20419,7 +20465,7 @@ ${svg}
|
|
|
20419
20465
|
function findStringEncoding() {
|
|
20420
20466
|
var ldid = header.ldid,
|
|
20421
20467
|
codepage = lookupCodePage(ldid),
|
|
20422
|
-
samples = getNonAsciiSamples(
|
|
20468
|
+
samples = getNonAsciiSamples(),
|
|
20423
20469
|
only7bit = samples.length === 0,
|
|
20424
20470
|
encoding, msg;
|
|
20425
20471
|
|
|
@@ -20464,21 +20510,25 @@ ${svg}
|
|
|
20464
20510
|
return arr;
|
|
20465
20511
|
}
|
|
20466
20512
|
|
|
20467
|
-
// Return
|
|
20513
|
+
// Return an array of buffers containing text samples
|
|
20468
20514
|
// with at least one byte outside the 7-bit ascii range.
|
|
20469
|
-
function getNonAsciiSamples(
|
|
20515
|
+
function getNonAsciiSamples() {
|
|
20470
20516
|
var samples = [];
|
|
20471
20517
|
var stringFields = header.fields.filter(function(f) {
|
|
20472
20518
|
return f.type == 'C';
|
|
20473
20519
|
});
|
|
20520
|
+
var cols = stringFields.length;
|
|
20521
|
+
// don't scan all the rows in large files (slow)
|
|
20522
|
+
var rows = Math.min(header.recordCount, 10000);
|
|
20523
|
+
var maxSamples = 50;
|
|
20474
20524
|
var buf = utils.createBuffer(256);
|
|
20475
20525
|
var index = {};
|
|
20476
20526
|
var f, chars, sample, hash;
|
|
20477
20527
|
// include non-ascii field names, if any
|
|
20478
20528
|
samples = getNonAsciiHeaders();
|
|
20479
|
-
for (var r=0
|
|
20480
|
-
for (var c=0
|
|
20481
|
-
if (samples.length >=
|
|
20529
|
+
for (var r=0; r<rows; r++) {
|
|
20530
|
+
for (var c=0; c<cols; c++) {
|
|
20531
|
+
if (samples.length >= maxSamples) break;
|
|
20482
20532
|
f = stringFields[c];
|
|
20483
20533
|
bin.position(getRowOffset(r) + f.columnOffset);
|
|
20484
20534
|
chars = readStringBytes(bin, f.size, buf);
|
|
@@ -29661,7 +29711,7 @@ ${svg}
|
|
|
29661
29711
|
stop('Missing an assignment expression');
|
|
29662
29712
|
}
|
|
29663
29713
|
var defs = getStateVar('defs');
|
|
29664
|
-
var compiled = compileFeatureExpression(opts.expression, {}, null, {});
|
|
29714
|
+
var compiled = compileFeatureExpression(opts.expression, {}, null, {no_warn: true});
|
|
29665
29715
|
var result = compiled(null, defs);
|
|
29666
29716
|
};
|
|
29667
29717
|
|
|
@@ -33263,6 +33313,12 @@ ${svg}
|
|
|
33263
33313
|
};
|
|
33264
33314
|
}
|
|
33265
33315
|
|
|
33316
|
+
cmd.ignore = function(targetLayer, dataset, opts) {
|
|
33317
|
+
if (opts.empty && layerIsEmpty(targetLayer)) {
|
|
33318
|
+
interrupt('Layer is empty, stopping processing');
|
|
33319
|
+
}
|
|
33320
|
+
};
|
|
33321
|
+
|
|
33266
33322
|
cmd.include = function(opts) {
|
|
33267
33323
|
var content, obj, context;
|
|
33268
33324
|
// TODO: handle web context
|
|
@@ -37688,6 +37744,9 @@ ${svg}
|
|
|
37688
37744
|
outputLayers = targetDataset.layers; // kludge to allow layer naming below
|
|
37689
37745
|
}
|
|
37690
37746
|
|
|
37747
|
+
} else if (name == 'ignore') {
|
|
37748
|
+
applyCommandToEachLayer(cmd.ignore, targetLayers, targetDataset, opts);
|
|
37749
|
+
|
|
37691
37750
|
} else if (name == 'include') {
|
|
37692
37751
|
cmd.include(opts);
|
|
37693
37752
|
|
|
@@ -38058,6 +38117,7 @@ ${svg}
|
|
|
38058
38117
|
cmd.options.output = outputArr;
|
|
38059
38118
|
}
|
|
38060
38119
|
});
|
|
38120
|
+
|
|
38061
38121
|
runParsedCommands(commands, null, callback);
|
|
38062
38122
|
}
|
|
38063
38123
|
|
|
@@ -38118,10 +38178,6 @@ ${svg}
|
|
|
38118
38178
|
error("Changed in v0.4: runParsedCommands() takes a Catalog object");
|
|
38119
38179
|
}
|
|
38120
38180
|
|
|
38121
|
-
if (!utils.isFunction(done)) {
|
|
38122
|
-
error("Missing a callback function");
|
|
38123
|
-
}
|
|
38124
|
-
|
|
38125
38181
|
if (!utils.isArray(commands)) {
|
|
38126
38182
|
error("Expected an array of parsed commands");
|
|
38127
38183
|
}
|
|
@@ -38142,18 +38198,25 @@ ${svg}
|
|
|
38142
38198
|
// that it can modify the output dataset in-place instead of making a copy.
|
|
38143
38199
|
commands[commands.length-1].options.final = true;
|
|
38144
38200
|
}
|
|
38145
|
-
commands = divideImportCommand(commands);
|
|
38146
|
-
utils.reduceAsync(commands, catalog, nextCommand, done);
|
|
38147
38201
|
|
|
38148
|
-
|
|
38149
|
-
|
|
38150
|
-
|
|
38151
|
-
|
|
38152
|
-
|
|
38202
|
+
var groups = divideImportCommand(commands);
|
|
38203
|
+
if (groups.length == 1) {
|
|
38204
|
+
// run a simple sequence of commands (input files are not batched)
|
|
38205
|
+
return runParsedCommands2(commands, catalog, done);
|
|
38206
|
+
}
|
|
38207
|
+
|
|
38208
|
+
// run duplicated commands (i.e. batch mode)
|
|
38209
|
+
utils.reduceAsync(groups, catalog, nextGroup, done);
|
|
38210
|
+
|
|
38211
|
+
function nextGroup(catalog, commands, next) {
|
|
38212
|
+
runParsedCommands2(commands, catalog, function(err, catalog) {
|
|
38213
|
+
err = filterError(err);
|
|
38214
|
+
next(err, catalog);
|
|
38215
|
+
});
|
|
38153
38216
|
}
|
|
38154
38217
|
|
|
38155
38218
|
function done(err, catalog) {
|
|
38156
|
-
|
|
38219
|
+
err = filterError(err);
|
|
38157
38220
|
cb(err, catalog);
|
|
38158
38221
|
setStateVar('current_command', null);
|
|
38159
38222
|
setStateVar('verbose', false);
|
|
@@ -38161,11 +38224,31 @@ ${svg}
|
|
|
38161
38224
|
}
|
|
38162
38225
|
}
|
|
38163
38226
|
|
|
38227
|
+
function filterError(err) {
|
|
38228
|
+
if (err) printError(err);
|
|
38229
|
+
if (err && err.name == 'NonFatalError') {
|
|
38230
|
+
return null;
|
|
38231
|
+
}
|
|
38232
|
+
return err;
|
|
38233
|
+
}
|
|
38234
|
+
|
|
38235
|
+
function runParsedCommands2(commands, catalog, cb) {
|
|
38236
|
+
utils.reduceAsync(commands, catalog, nextCommand, cb);
|
|
38237
|
+
|
|
38238
|
+
function nextCommand(catalog, cmd, next) {
|
|
38239
|
+
setStateVar('current_command', cmd.name); // for log msgs
|
|
38240
|
+
setStateVar('verbose', !!cmd.options.verbose);
|
|
38241
|
+
setStateVar('debug', !!cmd.options.debug);
|
|
38242
|
+
runCommand(cmd, catalog, next);
|
|
38243
|
+
}
|
|
38244
|
+
}
|
|
38245
|
+
|
|
38246
|
+
|
|
38164
38247
|
// If an initial import command indicates that several input files should be
|
|
38165
38248
|
// processed separately, then duplicate the sequence of commands to run
|
|
38166
38249
|
// once for each input file
|
|
38167
38250
|
// @commands Array of parsed commands
|
|
38168
|
-
// Returns:
|
|
38251
|
+
// Returns: Array of one or more sequences of parsed commands
|
|
38169
38252
|
//
|
|
38170
38253
|
function divideImportCommand(commands) {
|
|
38171
38254
|
var firstCmd = commands[0],
|
|
@@ -38173,23 +38256,23 @@ ${svg}
|
|
|
38173
38256
|
|
|
38174
38257
|
if (firstCmd.name != 'i' || opts.stdin || opts.merge_files ||
|
|
38175
38258
|
opts.combine_files || !opts.files || opts.files.length < 2) {
|
|
38176
|
-
return commands;
|
|
38259
|
+
return [commands];
|
|
38177
38260
|
}
|
|
38178
38261
|
|
|
38179
|
-
return
|
|
38180
|
-
var
|
|
38262
|
+
return opts.files.map(function(file) {
|
|
38263
|
+
var group = [{
|
|
38181
38264
|
name: 'i',
|
|
38182
38265
|
options: utils.defaults({
|
|
38183
38266
|
files:[file],
|
|
38184
38267
|
replace: true // kludge to replace data catalog
|
|
38185
38268
|
}, opts)
|
|
38186
|
-
};
|
|
38187
|
-
|
|
38188
|
-
|
|
38189
|
-
|
|
38190
|
-
}, []);
|
|
38269
|
+
}];
|
|
38270
|
+
group.push.apply(group, commands.slice(1));
|
|
38271
|
+
return group;
|
|
38272
|
+
});
|
|
38191
38273
|
}
|
|
38192
38274
|
|
|
38275
|
+
|
|
38193
38276
|
function printStartupMessages() {
|
|
38194
38277
|
// print heap memory message if running with a custom amount
|
|
38195
38278
|
var rxp = /^--max-old-space-size=([0-9]+)$/;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.69",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"commander": "^5.1.0",
|
|
44
44
|
"cookies": "^0.8.0",
|
|
45
|
-
"d3-
|
|
45
|
+
"d3-color": "2.0.0",
|
|
46
|
+
"d3-scale-chromatic": "2.0.0",
|
|
46
47
|
"delaunator": "^5.0.0",
|
|
47
48
|
"flatbush": "^3.2.1",
|
|
48
49
|
"geokdbush": "^1.1.0",
|