mapshaper 0.6.43 → 0.6.44
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/bin/mapshaper-gui +9 -2
- package/mapshaper.js +99 -32
- package/package.json +1 -1
- package/www/mapshaper-gui.js +17 -5
- package/www/mapshaper.js +99 -32
package/bin/mapshaper-gui
CHANGED
|
@@ -61,7 +61,10 @@ function startServer(port) {
|
|
|
61
61
|
http.createServer(function(request, response) {
|
|
62
62
|
var uri = url.parse(request.url).pathname;
|
|
63
63
|
clearTimeout(timeout);
|
|
64
|
-
if (uri
|
|
64
|
+
if (uri.includes('..')) {
|
|
65
|
+
// block attempts to load files outside webroot
|
|
66
|
+
serve404(response);
|
|
67
|
+
} else if (uri == '/close') {
|
|
65
68
|
// end process when page closes, unless page is immediately refreshed
|
|
66
69
|
timeout = setTimeout(function() {
|
|
67
70
|
process.exit(0);
|
|
@@ -116,10 +119,14 @@ function serveError(text, code, response) {
|
|
|
116
119
|
response.end();
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
function serve404(response) {
|
|
123
|
+
serveError("404 Not Found\n", 404, response);
|
|
124
|
+
}
|
|
125
|
+
|
|
119
126
|
function serveFile(filename, response) {
|
|
120
127
|
fs.readFile(filename, function(err, content) {
|
|
121
128
|
if (err) {
|
|
122
|
-
|
|
129
|
+
serve404(response);
|
|
123
130
|
} else {
|
|
124
131
|
serveContent(content, response, getMimeType(filename));
|
|
125
132
|
}
|
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.44";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
get default () { return utils; },
|
|
9
9
|
get getUniqueName () { return getUniqueName; },
|
|
10
10
|
get isFunction () { return isFunction; },
|
|
11
|
+
get isPromise () { return isPromise; },
|
|
11
12
|
get isObject () { return isObject; },
|
|
12
13
|
get clamp () { return clamp; },
|
|
13
14
|
get isArray () { return isArray; },
|
|
@@ -147,6 +148,10 @@
|
|
|
147
148
|
return typeof obj == 'function';
|
|
148
149
|
}
|
|
149
150
|
|
|
151
|
+
function isPromise(arg) {
|
|
152
|
+
return arg ? isFunction(arg.then) : false;
|
|
153
|
+
}
|
|
154
|
+
|
|
150
155
|
function isObject(obj) {
|
|
151
156
|
return obj === Object(obj); // via underscore
|
|
152
157
|
}
|
|
@@ -12488,7 +12493,6 @@
|
|
|
12488
12493
|
return +n.toPrecision(d);
|
|
12489
12494
|
}
|
|
12490
12495
|
|
|
12491
|
-
|
|
12492
12496
|
function roundToDigits(n, d) {
|
|
12493
12497
|
return +n.toFixed(d); // string conversion makes this slow
|
|
12494
12498
|
}
|
|
@@ -12552,6 +12556,37 @@
|
|
|
12552
12556
|
});
|
|
12553
12557
|
}
|
|
12554
12558
|
|
|
12559
|
+
const fround2 = (function() {
|
|
12560
|
+
var arr = new Float32Array(1);
|
|
12561
|
+
return function(x) {
|
|
12562
|
+
arr[0] = x;
|
|
12563
|
+
return arr[0];
|
|
12564
|
+
};
|
|
12565
|
+
})();
|
|
12566
|
+
|
|
12567
|
+
// This function rounds towards 0 (i.e. floor). TODO: round properly
|
|
12568
|
+
// @bits: number of bits to round
|
|
12569
|
+
// performance: about 3x slower than Math.fround()
|
|
12570
|
+
function getBinaryRoundingFunction(bits) {
|
|
12571
|
+
// double: sign (1) exponent (11) fraction (52)
|
|
12572
|
+
// single: sign (1) exponent (8) fraction (23)
|
|
12573
|
+
if ((bits >= 1 && bits <= 32) === false) {
|
|
12574
|
+
error('Invalid bits argument:', bits);
|
|
12575
|
+
}
|
|
12576
|
+
var isLE = require('os').endianness() == 'LE';
|
|
12577
|
+
var fp = new Float64Array(1);
|
|
12578
|
+
var leastBits = new Uint32Array(fp.buffer, isLE ? 0 : 4, 1);
|
|
12579
|
+
var mask = 2 ** 32 - 2 ** bits; // e.g. bits = 4 -> 0b11110000
|
|
12580
|
+
return function(x) {
|
|
12581
|
+
fp[0] = x;
|
|
12582
|
+
leastBits[0] = leastBits[0] & mask;
|
|
12583
|
+
return fp[0];
|
|
12584
|
+
};
|
|
12585
|
+
}
|
|
12586
|
+
|
|
12587
|
+
// "round to even" on the 23rd bit of the mantissa
|
|
12588
|
+
const fround = Math.fround || fround2;
|
|
12589
|
+
|
|
12555
12590
|
function setCoordinatePrecision(dataset, precision) {
|
|
12556
12591
|
var round = getRoundingFunction(precision);
|
|
12557
12592
|
// var dissolvePolygon, nodes;
|
|
@@ -12586,6 +12621,9 @@
|
|
|
12586
12621
|
getRoundedCoordString: getRoundedCoordString,
|
|
12587
12622
|
getRoundedCoords: getRoundedCoords,
|
|
12588
12623
|
roundPoints: roundPoints,
|
|
12624
|
+
fround2: fround2,
|
|
12625
|
+
getBinaryRoundingFunction: getBinaryRoundingFunction,
|
|
12626
|
+
fround: fround,
|
|
12589
12627
|
setCoordinatePrecision: setCoordinatePrecision
|
|
12590
12628
|
});
|
|
12591
12629
|
|
|
@@ -16458,7 +16496,8 @@
|
|
|
16458
16496
|
if (id >= 0 && id < n) {
|
|
16459
16497
|
return index[id] - 1;
|
|
16460
16498
|
} else {
|
|
16461
|
-
|
|
16499
|
+
return -1;
|
|
16500
|
+
// error('Invalid index');
|
|
16462
16501
|
}
|
|
16463
16502
|
};
|
|
16464
16503
|
}
|
|
@@ -18412,7 +18451,8 @@
|
|
|
18412
18451
|
// null values indicate the lack of a function for parsing/identifying this property
|
|
18413
18452
|
// (in which case a heuristic is used for distinguishing a string literal from an expression)
|
|
18414
18453
|
var stylePropertyTypes = {
|
|
18415
|
-
css: null,
|
|
18454
|
+
// css: null,
|
|
18455
|
+
css: 'inlinecss',
|
|
18416
18456
|
class: 'classname',
|
|
18417
18457
|
dx: 'measure',
|
|
18418
18458
|
dy: 'measure',
|
|
@@ -18599,6 +18639,8 @@
|
|
|
18599
18639
|
val = isPattern(strVal) ? strVal : null;
|
|
18600
18640
|
} else if (type == 'boolean') {
|
|
18601
18641
|
val = parseBoolean(strVal);
|
|
18642
|
+
} else if (type == 'inlinecss') {
|
|
18643
|
+
val = strVal; // TODO: validate
|
|
18602
18644
|
}
|
|
18603
18645
|
// else {
|
|
18604
18646
|
// // unknown type -- assume literal value
|
|
@@ -24696,9 +24738,9 @@ ${svg}
|
|
|
24696
24738
|
.option('class', {
|
|
24697
24739
|
describe: 'name of CSS class or classes (space-separated)'
|
|
24698
24740
|
})
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24741
|
+
.option('css', {
|
|
24742
|
+
describe: 'inline css style'
|
|
24743
|
+
})
|
|
24702
24744
|
.option('fill', {
|
|
24703
24745
|
describe: 'fill color; examples: #eee pink rgba(0, 0, 0, 0.2)'
|
|
24704
24746
|
})
|
|
@@ -41274,21 +41316,24 @@ ${svg}
|
|
|
41274
41316
|
parseConsoleCommands: parseConsoleCommands
|
|
41275
41317
|
});
|
|
41276
41318
|
|
|
41277
|
-
cmd.run = function(job, targets, opts
|
|
41319
|
+
cmd.run = async function(job, targets, opts) {
|
|
41278
41320
|
var commandStr, commands;
|
|
41279
41321
|
if (!opts.expression) {
|
|
41280
41322
|
stop("Missing expression parameter");
|
|
41281
41323
|
}
|
|
41282
41324
|
commandStr = runGlobalExpression(opts.expression, targets);
|
|
41325
|
+
// Support async functions as expressions
|
|
41326
|
+
if (utils.isPromise(commandStr)) {
|
|
41327
|
+
commandStr = await commandStr;
|
|
41328
|
+
}
|
|
41283
41329
|
if (commandStr) {
|
|
41284
41330
|
message(`command: [${commandStr}]`);
|
|
41285
41331
|
commands = parseCommands(commandStr);
|
|
41286
|
-
runParsedCommands(commands, job
|
|
41287
|
-
} else {
|
|
41288
|
-
cb(null);
|
|
41332
|
+
await utils.promisify(runParsedCommands)(commands, job);
|
|
41289
41333
|
}
|
|
41290
41334
|
};
|
|
41291
41335
|
|
|
41336
|
+
// This could return a Promise or a value or nothing
|
|
41292
41337
|
function runGlobalExpression(expression, targets) {
|
|
41293
41338
|
var ctx = getBaseContext();
|
|
41294
41339
|
var output, targetData;
|
|
@@ -42415,6 +42460,7 @@ ${svg}
|
|
|
42415
42460
|
shapes = lyr0.shapes,
|
|
42416
42461
|
index = {},
|
|
42417
42462
|
splitLayers = [],
|
|
42463
|
+
n = getFeatureCount(lyr0),
|
|
42418
42464
|
namer;
|
|
42419
42465
|
|
|
42420
42466
|
if (opts.ids) {
|
|
@@ -42423,11 +42469,18 @@ ${svg}
|
|
|
42423
42469
|
namer = getSplitNameFunction(lyr0, expression);
|
|
42424
42470
|
}
|
|
42425
42471
|
|
|
42472
|
+
// // halt if split field is missing
|
|
42426
42473
|
// if (splitField) {
|
|
42427
42474
|
// internal.requireDataField(lyr0, splitField);
|
|
42428
42475
|
// }
|
|
42429
42476
|
|
|
42430
|
-
|
|
42477
|
+
// if input layer is empty, return original layer
|
|
42478
|
+
// TODO: consider halting
|
|
42479
|
+
if (n === 0) {
|
|
42480
|
+
return [lyr0];
|
|
42481
|
+
}
|
|
42482
|
+
|
|
42483
|
+
utils.repeat(n, function(i) {
|
|
42431
42484
|
var name = namer(i),
|
|
42432
42485
|
lyr;
|
|
42433
42486
|
|
|
@@ -42450,6 +42503,7 @@ ${svg}
|
|
|
42450
42503
|
lyr.data.getRecords().push(properties[i]);
|
|
42451
42504
|
}
|
|
42452
42505
|
});
|
|
42506
|
+
|
|
42453
42507
|
return splitLayers;
|
|
42454
42508
|
};
|
|
42455
42509
|
|
|
@@ -42460,26 +42514,34 @@ ${svg}
|
|
|
42460
42514
|
};
|
|
42461
42515
|
}
|
|
42462
42516
|
|
|
42463
|
-
function
|
|
42464
|
-
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
42465
|
-
// like: split-1, split-2, ...
|
|
42466
|
-
return function(i) {
|
|
42467
|
-
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
42468
|
-
};
|
|
42469
|
-
}
|
|
42470
|
-
|
|
42471
|
-
function getSplitNameFunction(lyr, exp) {
|
|
42517
|
+
function getSplitNameFunction(lyr, arg) {
|
|
42472
42518
|
var compiled;
|
|
42473
|
-
if (!
|
|
42519
|
+
if (!arg) {
|
|
42520
|
+
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
42521
|
+
// like: split-1, split-2, ...
|
|
42522
|
+
return function(i) {
|
|
42523
|
+
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
42524
|
+
};
|
|
42525
|
+
}
|
|
42526
|
+
if (lyr.data && lyr.data.fieldExists(arg)) {
|
|
42527
|
+
// Argument is a field name
|
|
42528
|
+
return function(i) {
|
|
42529
|
+
var rec = lyr.data.getRecords()[i];
|
|
42530
|
+
return rec ? valueToLayerName(rec[arg]) : '';
|
|
42531
|
+
};
|
|
42532
|
+
}
|
|
42533
|
+
// Assume: argument is an expression
|
|
42474
42534
|
lyr = {name: lyr.name, data: lyr.data}; // remove shape info
|
|
42475
|
-
compiled = compileValueExpression(
|
|
42535
|
+
compiled = compileValueExpression(arg, lyr, null);
|
|
42476
42536
|
return function(i) {
|
|
42477
42537
|
var val = compiled(i);
|
|
42478
|
-
return
|
|
42479
|
-
// return val || val === 0 ? String(val) : '';
|
|
42538
|
+
return valueToLayerName(val);
|
|
42480
42539
|
};
|
|
42481
42540
|
}
|
|
42482
42541
|
|
|
42542
|
+
function valueToLayerName(val) {
|
|
42543
|
+
return String(val);
|
|
42544
|
+
}
|
|
42483
42545
|
|
|
42484
42546
|
// internal.getSplitKey = function(i, field, properties) {
|
|
42485
42547
|
// var rec = field && properties ? properties[i] : null;
|
|
@@ -42515,6 +42577,9 @@ ${svg}
|
|
|
42515
42577
|
|
|
42516
42578
|
cmd.svgStyle = function(lyr, dataset, opts) {
|
|
42517
42579
|
var filter;
|
|
42580
|
+
if (getFeatureCount(lyr) === 0) {
|
|
42581
|
+
return;
|
|
42582
|
+
}
|
|
42518
42583
|
if (!lyr.data) {
|
|
42519
42584
|
initDataTable(lyr);
|
|
42520
42585
|
}
|
|
@@ -43820,7 +43885,7 @@ ${svg}
|
|
|
43820
43885
|
});
|
|
43821
43886
|
|
|
43822
43887
|
} else if (name == 'run') {
|
|
43823
|
-
await
|
|
43888
|
+
await cmd.run(job, targets, opts);
|
|
43824
43889
|
|
|
43825
43890
|
} else if (name == 'scalebar') {
|
|
43826
43891
|
cmd.scalebar(job.catalog, opts);
|
|
@@ -43843,7 +43908,7 @@ ${svg}
|
|
|
43843
43908
|
|
|
43844
43909
|
} else if (name == 'snap') {
|
|
43845
43910
|
// cmd.snap(targetDataset, opts);
|
|
43846
|
-
applyCommandToEachTarget(targets, opts);
|
|
43911
|
+
applyCommandToEachTarget(cmd.snap, targets, opts);
|
|
43847
43912
|
|
|
43848
43913
|
} else if (name == 'sort') {
|
|
43849
43914
|
applyCommandToEachLayer(cmd.sortFeatures, targetLayers, arcs, opts);
|
|
@@ -44097,6 +44162,13 @@ ${svg}
|
|
|
44097
44162
|
}
|
|
44098
44163
|
});
|
|
44099
44164
|
|
|
44165
|
+
var lastCmd = commands[commands.length - 1];
|
|
44166
|
+
if (!runningInBrowser() && lastCmd.name == 'o') {
|
|
44167
|
+
// in CLI, set 'final' flag on final -o command, so the export function knows
|
|
44168
|
+
// that it can modify the output dataset in-place instead of making a copy.
|
|
44169
|
+
lastCmd.options.final = true;
|
|
44170
|
+
}
|
|
44171
|
+
|
|
44100
44172
|
var batches = divideImportCommand(commands);
|
|
44101
44173
|
utils.reduceAsync(batches, null, nextGroup, done);
|
|
44102
44174
|
|
|
@@ -44165,11 +44237,6 @@ ${svg}
|
|
|
44165
44237
|
// @done: function([error], [job])
|
|
44166
44238
|
//
|
|
44167
44239
|
function runParsedCommands(commands, job, done) {
|
|
44168
|
-
if (!runningInBrowser() && commands[commands.length-1].name == 'o') {
|
|
44169
|
-
// in CLI, set 'final' flag on final -o command, so the export function knows
|
|
44170
|
-
// that it can modify the output dataset in-place instead of making a copy.
|
|
44171
|
-
commands[commands.length-1].options.final = true;
|
|
44172
|
-
}
|
|
44173
44240
|
if (!job) job = new Job();
|
|
44174
44241
|
commands = readAndRemoveSettings(job, commands);
|
|
44175
44242
|
if (!runningInBrowser()) {
|
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
get default () { return utils; },
|
|
6
6
|
get getUniqueName () { return getUniqueName; },
|
|
7
7
|
get isFunction () { return isFunction; },
|
|
8
|
+
get isPromise () { return isPromise; },
|
|
8
9
|
get isObject () { return isObject; },
|
|
9
10
|
get clamp () { return clamp; },
|
|
10
11
|
get isArray () { return isArray; },
|
|
@@ -2157,11 +2158,18 @@
|
|
|
2157
2158
|
}
|
|
2158
2159
|
|
|
2159
2160
|
function downloadNextFile(memo, item, next) {
|
|
2160
|
-
var
|
|
2161
|
-
fetch(item.url).then(resp =>
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2161
|
+
var err;
|
|
2162
|
+
fetch(item.url).then(resp => {
|
|
2163
|
+
if (resp.status != 200) {
|
|
2164
|
+
// e.g. 404 because a URL listed in the GUI query string does not exist
|
|
2165
|
+
throw Error();
|
|
2166
|
+
}
|
|
2167
|
+
return resp.blob();
|
|
2168
|
+
}).then(blob => {
|
|
2169
|
+
if (blob) {
|
|
2170
|
+
blob.name = item.basename;
|
|
2171
|
+
memo.push(blob);
|
|
2172
|
+
}
|
|
2165
2173
|
}).catch(e => {
|
|
2166
2174
|
err = "Error loading " + item.name + ". Possible causes include: wrong URL, no network connection, server not configured for cross-domain sharing (CORS).";
|
|
2167
2175
|
}).finally(() => {
|
|
@@ -5209,6 +5217,10 @@
|
|
|
5209
5217
|
return typeof obj == 'function';
|
|
5210
5218
|
}
|
|
5211
5219
|
|
|
5220
|
+
function isPromise(arg) {
|
|
5221
|
+
return arg ? isFunction(arg.then) : false;
|
|
5222
|
+
}
|
|
5223
|
+
|
|
5212
5224
|
function isObject(obj) {
|
|
5213
5225
|
return obj === Object(obj); // via underscore
|
|
5214
5226
|
}
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.44";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
get default () { return utils; },
|
|
9
9
|
get getUniqueName () { return getUniqueName; },
|
|
10
10
|
get isFunction () { return isFunction; },
|
|
11
|
+
get isPromise () { return isPromise; },
|
|
11
12
|
get isObject () { return isObject; },
|
|
12
13
|
get clamp () { return clamp; },
|
|
13
14
|
get isArray () { return isArray; },
|
|
@@ -147,6 +148,10 @@
|
|
|
147
148
|
return typeof obj == 'function';
|
|
148
149
|
}
|
|
149
150
|
|
|
151
|
+
function isPromise(arg) {
|
|
152
|
+
return arg ? isFunction(arg.then) : false;
|
|
153
|
+
}
|
|
154
|
+
|
|
150
155
|
function isObject(obj) {
|
|
151
156
|
return obj === Object(obj); // via underscore
|
|
152
157
|
}
|
|
@@ -12488,7 +12493,6 @@
|
|
|
12488
12493
|
return +n.toPrecision(d);
|
|
12489
12494
|
}
|
|
12490
12495
|
|
|
12491
|
-
|
|
12492
12496
|
function roundToDigits(n, d) {
|
|
12493
12497
|
return +n.toFixed(d); // string conversion makes this slow
|
|
12494
12498
|
}
|
|
@@ -12552,6 +12556,37 @@
|
|
|
12552
12556
|
});
|
|
12553
12557
|
}
|
|
12554
12558
|
|
|
12559
|
+
const fround2 = (function() {
|
|
12560
|
+
var arr = new Float32Array(1);
|
|
12561
|
+
return function(x) {
|
|
12562
|
+
arr[0] = x;
|
|
12563
|
+
return arr[0];
|
|
12564
|
+
};
|
|
12565
|
+
})();
|
|
12566
|
+
|
|
12567
|
+
// This function rounds towards 0 (i.e. floor). TODO: round properly
|
|
12568
|
+
// @bits: number of bits to round
|
|
12569
|
+
// performance: about 3x slower than Math.fround()
|
|
12570
|
+
function getBinaryRoundingFunction(bits) {
|
|
12571
|
+
// double: sign (1) exponent (11) fraction (52)
|
|
12572
|
+
// single: sign (1) exponent (8) fraction (23)
|
|
12573
|
+
if ((bits >= 1 && bits <= 32) === false) {
|
|
12574
|
+
error('Invalid bits argument:', bits);
|
|
12575
|
+
}
|
|
12576
|
+
var isLE = require('os').endianness() == 'LE';
|
|
12577
|
+
var fp = new Float64Array(1);
|
|
12578
|
+
var leastBits = new Uint32Array(fp.buffer, isLE ? 0 : 4, 1);
|
|
12579
|
+
var mask = 2 ** 32 - 2 ** bits; // e.g. bits = 4 -> 0b11110000
|
|
12580
|
+
return function(x) {
|
|
12581
|
+
fp[0] = x;
|
|
12582
|
+
leastBits[0] = leastBits[0] & mask;
|
|
12583
|
+
return fp[0];
|
|
12584
|
+
};
|
|
12585
|
+
}
|
|
12586
|
+
|
|
12587
|
+
// "round to even" on the 23rd bit of the mantissa
|
|
12588
|
+
const fround = Math.fround || fround2;
|
|
12589
|
+
|
|
12555
12590
|
function setCoordinatePrecision(dataset, precision) {
|
|
12556
12591
|
var round = getRoundingFunction(precision);
|
|
12557
12592
|
// var dissolvePolygon, nodes;
|
|
@@ -12586,6 +12621,9 @@
|
|
|
12586
12621
|
getRoundedCoordString: getRoundedCoordString,
|
|
12587
12622
|
getRoundedCoords: getRoundedCoords,
|
|
12588
12623
|
roundPoints: roundPoints,
|
|
12624
|
+
fround2: fround2,
|
|
12625
|
+
getBinaryRoundingFunction: getBinaryRoundingFunction,
|
|
12626
|
+
fround: fround,
|
|
12589
12627
|
setCoordinatePrecision: setCoordinatePrecision
|
|
12590
12628
|
});
|
|
12591
12629
|
|
|
@@ -16458,7 +16496,8 @@
|
|
|
16458
16496
|
if (id >= 0 && id < n) {
|
|
16459
16497
|
return index[id] - 1;
|
|
16460
16498
|
} else {
|
|
16461
|
-
|
|
16499
|
+
return -1;
|
|
16500
|
+
// error('Invalid index');
|
|
16462
16501
|
}
|
|
16463
16502
|
};
|
|
16464
16503
|
}
|
|
@@ -18412,7 +18451,8 @@
|
|
|
18412
18451
|
// null values indicate the lack of a function for parsing/identifying this property
|
|
18413
18452
|
// (in which case a heuristic is used for distinguishing a string literal from an expression)
|
|
18414
18453
|
var stylePropertyTypes = {
|
|
18415
|
-
css: null,
|
|
18454
|
+
// css: null,
|
|
18455
|
+
css: 'inlinecss',
|
|
18416
18456
|
class: 'classname',
|
|
18417
18457
|
dx: 'measure',
|
|
18418
18458
|
dy: 'measure',
|
|
@@ -18599,6 +18639,8 @@
|
|
|
18599
18639
|
val = isPattern(strVal) ? strVal : null;
|
|
18600
18640
|
} else if (type == 'boolean') {
|
|
18601
18641
|
val = parseBoolean(strVal);
|
|
18642
|
+
} else if (type == 'inlinecss') {
|
|
18643
|
+
val = strVal; // TODO: validate
|
|
18602
18644
|
}
|
|
18603
18645
|
// else {
|
|
18604
18646
|
// // unknown type -- assume literal value
|
|
@@ -24696,9 +24738,9 @@ ${svg}
|
|
|
24696
24738
|
.option('class', {
|
|
24697
24739
|
describe: 'name of CSS class or classes (space-separated)'
|
|
24698
24740
|
})
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24741
|
+
.option('css', {
|
|
24742
|
+
describe: 'inline css style'
|
|
24743
|
+
})
|
|
24702
24744
|
.option('fill', {
|
|
24703
24745
|
describe: 'fill color; examples: #eee pink rgba(0, 0, 0, 0.2)'
|
|
24704
24746
|
})
|
|
@@ -41274,21 +41316,24 @@ ${svg}
|
|
|
41274
41316
|
parseConsoleCommands: parseConsoleCommands
|
|
41275
41317
|
});
|
|
41276
41318
|
|
|
41277
|
-
cmd.run = function(job, targets, opts
|
|
41319
|
+
cmd.run = async function(job, targets, opts) {
|
|
41278
41320
|
var commandStr, commands;
|
|
41279
41321
|
if (!opts.expression) {
|
|
41280
41322
|
stop("Missing expression parameter");
|
|
41281
41323
|
}
|
|
41282
41324
|
commandStr = runGlobalExpression(opts.expression, targets);
|
|
41325
|
+
// Support async functions as expressions
|
|
41326
|
+
if (utils.isPromise(commandStr)) {
|
|
41327
|
+
commandStr = await commandStr;
|
|
41328
|
+
}
|
|
41283
41329
|
if (commandStr) {
|
|
41284
41330
|
message(`command: [${commandStr}]`);
|
|
41285
41331
|
commands = parseCommands(commandStr);
|
|
41286
|
-
runParsedCommands(commands, job
|
|
41287
|
-
} else {
|
|
41288
|
-
cb(null);
|
|
41332
|
+
await utils.promisify(runParsedCommands)(commands, job);
|
|
41289
41333
|
}
|
|
41290
41334
|
};
|
|
41291
41335
|
|
|
41336
|
+
// This could return a Promise or a value or nothing
|
|
41292
41337
|
function runGlobalExpression(expression, targets) {
|
|
41293
41338
|
var ctx = getBaseContext();
|
|
41294
41339
|
var output, targetData;
|
|
@@ -42415,6 +42460,7 @@ ${svg}
|
|
|
42415
42460
|
shapes = lyr0.shapes,
|
|
42416
42461
|
index = {},
|
|
42417
42462
|
splitLayers = [],
|
|
42463
|
+
n = getFeatureCount(lyr0),
|
|
42418
42464
|
namer;
|
|
42419
42465
|
|
|
42420
42466
|
if (opts.ids) {
|
|
@@ -42423,11 +42469,18 @@ ${svg}
|
|
|
42423
42469
|
namer = getSplitNameFunction(lyr0, expression);
|
|
42424
42470
|
}
|
|
42425
42471
|
|
|
42472
|
+
// // halt if split field is missing
|
|
42426
42473
|
// if (splitField) {
|
|
42427
42474
|
// internal.requireDataField(lyr0, splitField);
|
|
42428
42475
|
// }
|
|
42429
42476
|
|
|
42430
|
-
|
|
42477
|
+
// if input layer is empty, return original layer
|
|
42478
|
+
// TODO: consider halting
|
|
42479
|
+
if (n === 0) {
|
|
42480
|
+
return [lyr0];
|
|
42481
|
+
}
|
|
42482
|
+
|
|
42483
|
+
utils.repeat(n, function(i) {
|
|
42431
42484
|
var name = namer(i),
|
|
42432
42485
|
lyr;
|
|
42433
42486
|
|
|
@@ -42450,6 +42503,7 @@ ${svg}
|
|
|
42450
42503
|
lyr.data.getRecords().push(properties[i]);
|
|
42451
42504
|
}
|
|
42452
42505
|
});
|
|
42506
|
+
|
|
42453
42507
|
return splitLayers;
|
|
42454
42508
|
};
|
|
42455
42509
|
|
|
@@ -42460,26 +42514,34 @@ ${svg}
|
|
|
42460
42514
|
};
|
|
42461
42515
|
}
|
|
42462
42516
|
|
|
42463
|
-
function
|
|
42464
|
-
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
42465
|
-
// like: split-1, split-2, ...
|
|
42466
|
-
return function(i) {
|
|
42467
|
-
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
42468
|
-
};
|
|
42469
|
-
}
|
|
42470
|
-
|
|
42471
|
-
function getSplitNameFunction(lyr, exp) {
|
|
42517
|
+
function getSplitNameFunction(lyr, arg) {
|
|
42472
42518
|
var compiled;
|
|
42473
|
-
if (!
|
|
42519
|
+
if (!arg) {
|
|
42520
|
+
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
42521
|
+
// like: split-1, split-2, ...
|
|
42522
|
+
return function(i) {
|
|
42523
|
+
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
42524
|
+
};
|
|
42525
|
+
}
|
|
42526
|
+
if (lyr.data && lyr.data.fieldExists(arg)) {
|
|
42527
|
+
// Argument is a field name
|
|
42528
|
+
return function(i) {
|
|
42529
|
+
var rec = lyr.data.getRecords()[i];
|
|
42530
|
+
return rec ? valueToLayerName(rec[arg]) : '';
|
|
42531
|
+
};
|
|
42532
|
+
}
|
|
42533
|
+
// Assume: argument is an expression
|
|
42474
42534
|
lyr = {name: lyr.name, data: lyr.data}; // remove shape info
|
|
42475
|
-
compiled = compileValueExpression(
|
|
42535
|
+
compiled = compileValueExpression(arg, lyr, null);
|
|
42476
42536
|
return function(i) {
|
|
42477
42537
|
var val = compiled(i);
|
|
42478
|
-
return
|
|
42479
|
-
// return val || val === 0 ? String(val) : '';
|
|
42538
|
+
return valueToLayerName(val);
|
|
42480
42539
|
};
|
|
42481
42540
|
}
|
|
42482
42541
|
|
|
42542
|
+
function valueToLayerName(val) {
|
|
42543
|
+
return String(val);
|
|
42544
|
+
}
|
|
42483
42545
|
|
|
42484
42546
|
// internal.getSplitKey = function(i, field, properties) {
|
|
42485
42547
|
// var rec = field && properties ? properties[i] : null;
|
|
@@ -42515,6 +42577,9 @@ ${svg}
|
|
|
42515
42577
|
|
|
42516
42578
|
cmd.svgStyle = function(lyr, dataset, opts) {
|
|
42517
42579
|
var filter;
|
|
42580
|
+
if (getFeatureCount(lyr) === 0) {
|
|
42581
|
+
return;
|
|
42582
|
+
}
|
|
42518
42583
|
if (!lyr.data) {
|
|
42519
42584
|
initDataTable(lyr);
|
|
42520
42585
|
}
|
|
@@ -43820,7 +43885,7 @@ ${svg}
|
|
|
43820
43885
|
});
|
|
43821
43886
|
|
|
43822
43887
|
} else if (name == 'run') {
|
|
43823
|
-
await
|
|
43888
|
+
await cmd.run(job, targets, opts);
|
|
43824
43889
|
|
|
43825
43890
|
} else if (name == 'scalebar') {
|
|
43826
43891
|
cmd.scalebar(job.catalog, opts);
|
|
@@ -43843,7 +43908,7 @@ ${svg}
|
|
|
43843
43908
|
|
|
43844
43909
|
} else if (name == 'snap') {
|
|
43845
43910
|
// cmd.snap(targetDataset, opts);
|
|
43846
|
-
applyCommandToEachTarget(targets, opts);
|
|
43911
|
+
applyCommandToEachTarget(cmd.snap, targets, opts);
|
|
43847
43912
|
|
|
43848
43913
|
} else if (name == 'sort') {
|
|
43849
43914
|
applyCommandToEachLayer(cmd.sortFeatures, targetLayers, arcs, opts);
|
|
@@ -44097,6 +44162,13 @@ ${svg}
|
|
|
44097
44162
|
}
|
|
44098
44163
|
});
|
|
44099
44164
|
|
|
44165
|
+
var lastCmd = commands[commands.length - 1];
|
|
44166
|
+
if (!runningInBrowser() && lastCmd.name == 'o') {
|
|
44167
|
+
// in CLI, set 'final' flag on final -o command, so the export function knows
|
|
44168
|
+
// that it can modify the output dataset in-place instead of making a copy.
|
|
44169
|
+
lastCmd.options.final = true;
|
|
44170
|
+
}
|
|
44171
|
+
|
|
44100
44172
|
var batches = divideImportCommand(commands);
|
|
44101
44173
|
utils.reduceAsync(batches, null, nextGroup, done);
|
|
44102
44174
|
|
|
@@ -44165,11 +44237,6 @@ ${svg}
|
|
|
44165
44237
|
// @done: function([error], [job])
|
|
44166
44238
|
//
|
|
44167
44239
|
function runParsedCommands(commands, job, done) {
|
|
44168
|
-
if (!runningInBrowser() && commands[commands.length-1].name == 'o') {
|
|
44169
|
-
// in CLI, set 'final' flag on final -o command, so the export function knows
|
|
44170
|
-
// that it can modify the output dataset in-place instead of making a copy.
|
|
44171
|
-
commands[commands.length-1].options.final = true;
|
|
44172
|
-
}
|
|
44173
44240
|
if (!job) job = new Job();
|
|
44174
44241
|
commands = readAndRemoveSettings(job, commands);
|
|
44175
44242
|
if (!runningInBrowser()) {
|