mapshaper 0.6.14 → 0.6.15

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.
@@ -392,7 +392,7 @@
392
392
  function readEntry(entry) {
393
393
  var filename = entry.filename,
394
394
  isValid = !entry.directory && GUI.isReadableFileType(filename) &&
395
- !/^__MACOSX/.test(filename); // ignore "resource-force" files
395
+ !/^__MACOSX/.test(filename); // ignore "resource-fork" files
396
396
  if (isValid) {
397
397
  entry.getData(new zip.BlobWriter(), function(file) {
398
398
  file.name = filename; // Give the Blob a name, like a File object
@@ -1420,12 +1420,14 @@
1420
1420
  async function expandFiles(files) {
1421
1421
  var files2 = [], expanded;
1422
1422
  for (var f of files) {
1423
- if (internal.isZipFile(f.name) || /\.kmz$/.test(f.name)) {
1423
+ if (internal.isZipFile(f.name)) {
1424
1424
  expanded = await readZipFile(f);
1425
- files2 = files2.concat(expanded);
1425
+ } else if (internal.isKmzFile(f.name)) {
1426
+ expanded = await readKmzFile(f);
1426
1427
  } else {
1427
- files2.push(f);
1428
+ expanded = [f];
1428
1429
  }
1430
+ files2 = files2.concat(expanded);
1429
1431
  }
1430
1432
  return files2;
1431
1433
  }
@@ -1582,6 +1584,15 @@
1582
1584
  });
1583
1585
  }
1584
1586
 
1587
+ async function readKmzFile(file) {
1588
+ var files = await readZipFile(file);
1589
+ var name = files[0] && files[0].name;
1590
+ if (name == 'doc.kml') {
1591
+ files[0].name = internal.replaceFileExtension(file.name, 'kml');
1592
+ }
1593
+ return files;
1594
+ }
1595
+
1585
1596
  async function readZipFile(file) {
1586
1597
  var files = [];
1587
1598
  await wait(35); // pause a beat so status message can display
@@ -3392,7 +3403,7 @@
3392
3403
  }
3393
3404
 
3394
3405
  function initFormatMenu() {
3395
- var defaults = ['shapefile', 'geojson', 'topojson', 'json', 'dsv', 'svg'];
3406
+ var defaults = ['shapefile', 'geojson', 'topojson', 'json', 'dsv', 'kml', 'svg'];
3396
3407
  var formats = utils$1.uniq(defaults.concat(getInputFormats()));
3397
3408
  var items = formats.map(function(fmt) {
3398
3409
  return utils$1.format('<div><label><input type="radio" name="format" value="%s"' +
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.14";
3
+ var VERSION = "0.6.15";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -5560,7 +5560,9 @@
5560
5560
  len = _nn[absId];
5561
5561
  if (nth < 0) nth = len + nth;
5562
5562
  if (absId != arcId) nth = len - nth - 1;
5563
- if (nth < 0 || nth >= len) error("[ArcCollection] out-of-range vertex id");
5563
+ if (nth < 0 || nth >= len) {
5564
+ error("[ArcCollection] out-of-range vertex id");
5565
+ }
5564
5566
  return _ii[absId] + nth;
5565
5567
  };
5566
5568
 
@@ -7198,8 +7200,12 @@
7198
7200
  return /\.zip$/i.test(file);
7199
7201
  }
7200
7202
 
7203
+ function isKmzFile(file) {
7204
+ return /\.kmz$/i.test(file);
7205
+ }
7206
+
7201
7207
  function isSupportedOutputFormat(fmt) {
7202
- var types = ['geojson', 'topojson', 'json', 'dsv', 'dbf', 'shapefile', 'svg'];
7208
+ var types = ['geojson', 'topojson', 'json', 'dsv', 'dbf', 'shapefile', 'svg', 'kml'];
7203
7209
  return types.indexOf(fmt) > -1;
7204
7210
  }
7205
7211
 
@@ -7210,6 +7216,8 @@
7210
7216
  json: 'JSON records',
7211
7217
  dsv: 'CSV',
7212
7218
  dbf: 'DBF',
7219
+ kml: 'KML',
7220
+ kmz: 'KMZ',
7213
7221
  shapefile: 'Shapefile',
7214
7222
  svg: 'SVG'
7215
7223
  }[fmt] || '';
@@ -7223,7 +7231,7 @@
7223
7231
 
7224
7232
  // Detect extensions of some unsupported file types, for cmd line validation
7225
7233
  function filenameIsUnsupportedOutputType(file) {
7226
- var rxp = /\.(shx|prj|xls|xlsx|gdb|sbn|sbx|xml|kml)$/i;
7234
+ var rxp = /\.(shx|prj|xls|xlsx|gdb|sbn|sbx|xml)$/i;
7227
7235
  return rxp.test(file);
7228
7236
  }
7229
7237
 
@@ -7236,6 +7244,7 @@
7236
7244
  stringLooksLikeKML: stringLooksLikeKML,
7237
7245
  couldBeDsvFile: couldBeDsvFile,
7238
7246
  isZipFile: isZipFile,
7247
+ isKmzFile: isKmzFile,
7239
7248
  isSupportedOutputFormat: isSupportedOutputFormat,
7240
7249
  getFormatName: getFormatName,
7241
7250
  isSupportedBinaryInputType: isSupportedBinaryInputType,
@@ -7265,7 +7274,7 @@
7265
7274
  // don't import .dbf separately if .shp is present
7266
7275
  if (replaceFileExtension(file, 'shp') in cache) return false;
7267
7276
  }
7268
- return type == 'text' || type == 'json' || type == 'shp' || type == 'dbf';
7277
+ return type == 'text' || type == 'json' || type == 'shp' || type == 'dbf' || type == 'kml';
7269
7278
  });
7270
7279
  }
7271
7280
 
@@ -7306,6 +7315,13 @@
7306
7315
  return ss && ss.isFile() || false;
7307
7316
  };
7308
7317
 
7318
+ cli.checkCommandEnv = function(cname) {
7319
+ var blocked = ['i', 'include', 'require', 'external'];
7320
+ if (runningInBrowser() && blocked.includes(cname)) {
7321
+ stop('The -' + cname + ' command cannot be run in the browser');
7322
+ }
7323
+ };
7324
+
7309
7325
  // cli.fileSize = function(path) {
7310
7326
  // var ss = cli.statSync(path);
7311
7327
  // return ss && ss.size || 0;
@@ -8226,55 +8242,71 @@
8226
8242
  getFormattedStringify: getFormattedStringify
8227
8243
  });
8228
8244
 
8229
- // Return id of rightmost connected arc in relation to @arcId
8230
- // Return @arcId if no arcs can be found
8231
- function getRightmostArc(arcId, nodes, filter) {
8232
- var ids = nodes.getConnectedArcs(arcId);
8245
+ function isValidArc(arcId, arcs) {
8246
+ // check for arcs with no vertices
8247
+ // TODO: also check for other kinds of degenerate arcs
8248
+ // (e.g. collapsed arcs consisting of identical points)
8249
+ return arcs.getArcLength(arcId) > 1;
8250
+ }
8251
+
8252
+ // Return id of rightmost connected arc in relation to @fromArcId
8253
+ // Return @fromArcId if no arcs can be found
8254
+ function getRightmostArc(fromArcId, nodes, filter) {
8255
+ var arcs = nodes.arcs,
8256
+ coords = arcs.getVertexData(),
8257
+ xx = coords.xx,
8258
+ yy = coords.yy,
8259
+ ids = nodes.getConnectedArcs(fromArcId),
8260
+ toArcId = fromArcId; // initialize to fromArcId -- an error condition
8261
+
8233
8262
  if (filter) {
8234
8263
  ids = ids.filter(filter);
8235
8264
  }
8236
- if (ids.length === 0) {
8237
- return arcId; // error condition, handled by caller
8265
+
8266
+ if (!isValidArc(fromArcId, arcs) || ids.length === 0) {
8267
+ return fromArcId;
8238
8268
  }
8239
- return getRighmostArc2(arcId, ids, nodes.arcs);
8240
- }
8241
8269
 
8242
- function getRighmostArc2 (fromId, ids, arcs) {
8243
- var coords = arcs.getVertexData(),
8244
- xx = coords.xx,
8245
- yy = coords.yy,
8246
- inode = arcs.indexOfVertex(fromId, -1),
8270
+ var inode = arcs.indexOfVertex(fromArcId, -1),
8247
8271
  nodeX = xx[inode],
8248
8272
  nodeY = yy[inode],
8249
- ifrom = arcs.indexOfVertex(fromId, -2),
8273
+ ifrom = arcs.indexOfVertex(fromArcId, -2),
8250
8274
  fromX = xx[ifrom],
8251
8275
  fromY = yy[ifrom],
8252
- toId = fromId, // initialize to from-arc -- an error
8253
8276
  ito, candId, icand, code, j;
8254
8277
 
8255
8278
  /*if (x == ax && y == ay) {
8256
8279
  error("Duplicate point error");
8257
8280
  }*/
8258
- if (ids.length > 0) {
8259
- toId = ids[0];
8260
- ito = arcs.indexOfVertex(toId, -2);
8261
- }
8262
8281
 
8263
- for (j=1; j<ids.length; j++) {
8282
+
8283
+ for (j=0; j<ids.length; j++) {
8264
8284
  candId = ids[j];
8285
+ if (!isValidArc(candId, arcs)) {
8286
+ // skip empty arcs
8287
+ continue;
8288
+ }
8265
8289
  icand = arcs.indexOfVertex(candId, -2);
8290
+
8291
+ if (toArcId == fromArcId) {
8292
+ // first valid candidate
8293
+ ito = icand;
8294
+ toArcId = candId;
8295
+ continue;
8296
+ }
8297
+
8266
8298
  code = chooseRighthandPath(fromX, fromY, nodeX, nodeY, xx[ito], yy[ito], xx[icand], yy[icand]);
8267
- // code = internal.chooseRighthandPath(0, 0, nodeX - fromX, nodeY - fromY, xx[ito] - fromX, yy[ito] - fromY, xx[icand] - fromX, yy[icand] - fromY);
8268
8299
  if (code == 2) {
8269
- toId = candId;
8270
8300
  ito = icand;
8301
+ toArcId = candId;
8271
8302
  }
8272
8303
  }
8273
- if (toId == fromId) {
8304
+
8305
+ if (toArcId == fromArcId) {
8274
8306
  // This shouldn't occur, assuming that other arcs are present
8275
8307
  error("Pathfinder error");
8276
8308
  }
8277
- return toId;
8309
+ return toArcId;
8278
8310
  }
8279
8311
 
8280
8312
  function chooseRighthandPath2(fromX, fromY, nodeX, nodeY, ax, ay, bx, by) {
@@ -8473,11 +8505,19 @@
8473
8505
  return ~getRightmostArc(prevId, nodes, testArc);
8474
8506
  }
8475
8507
 
8508
+ function isEmptyArc(id) {
8509
+ return nodes.arcs.getArcLength(id) > 1 === false;
8510
+ }
8511
+
8476
8512
  return function(startId) {
8477
8513
  var path = [],
8478
8514
  nextId, msg,
8479
8515
  candId = startId;
8480
8516
 
8517
+ if (isEmptyArc(startId)) {
8518
+ return null;
8519
+ }
8520
+
8481
8521
  do {
8482
8522
  if (useRoute(candId)) {
8483
8523
  path.push(candId);
@@ -15766,6 +15806,22 @@ ${svg}
15766
15806
  layerHasLabels: layerHasLabels
15767
15807
  });
15768
15808
 
15809
+ // import { isKmzFile } from '../io/mapshaper-file-types';
15810
+
15811
+ function exportKML(dataset, opts) {
15812
+ var toKML = require("@placemarkio/tokml").toKML;
15813
+ var geojsonOpts = Object.assign({combine_layers: true, geojson_type: 'FeatureCollection'}, opts);
15814
+ var geojson = exportDatasetAsGeoJSON(dataset, geojsonOpts);
15815
+ var kml = toKML(geojson);
15816
+ // TODO: add KMZ output
15817
+ // var useKmz = opts.file && isKmzFile(opts.file);
15818
+ var ofile = opts.file || getOutputFileBase(dataset) + '.kml';
15819
+ return [{
15820
+ content: kml,
15821
+ filename: ofile
15822
+ }];
15823
+ }
15824
+
15769
15825
  function buffersAreIdentical(a, b) {
15770
15826
  var alen = BinArray.bufferSize(a);
15771
15827
  var blen = BinArray.bufferSize(b);
@@ -17513,7 +17569,7 @@ ${svg}
17513
17569
  function exportDatasets(datasets, opts) {
17514
17570
  var format = getOutputFormat(datasets[0], opts);
17515
17571
  var files;
17516
- if (format == 'svg' || format == 'topojson' || format == 'geojson' && opts.combine_layers) {
17572
+ if (format == 'kml' || format == 'svg' || format == 'topojson' || format == 'geojson' && opts.combine_layers) {
17517
17573
  // multi-layer formats: combine multiple datasets into one
17518
17574
  if (datasets.length > 1) {
17519
17575
  datasets = [mergeDatasetsForExport(datasets)];
@@ -17567,8 +17623,8 @@ ${svg}
17567
17623
  }, dataset);
17568
17624
 
17569
17625
  // Adjust layer names, so they can be used as output file names
17570
- // (except for multi-layer formats TopoJSON and SVG)
17571
- if (opts.file && outFmt != 'topojson' && outFmt != 'svg') {
17626
+ // (except for multi-layer formats TopoJSON, SVG, KML)
17627
+ if (opts.file && outFmt != 'topojson' && outFmt != 'svg'&& outFmt != 'kml') {
17572
17628
  dataset.layers.forEach(function(lyr) {
17573
17629
  lyr.name = getFileBase(opts.file);
17574
17630
  });
@@ -17613,7 +17669,8 @@ ${svg}
17613
17669
  dsv: exportDelim,
17614
17670
  dbf: exportDbf,
17615
17671
  json: exportJSON,
17616
- svg: exportSVG
17672
+ svg: exportSVG,
17673
+ kml: exportKML
17617
17674
  };
17618
17675
 
17619
17676
 
@@ -23795,32 +23852,81 @@ ${svg}
23795
23852
  });
23796
23853
 
23797
23854
  cmd.importFiles = function(opts) {
23798
- var files = opts.files || [],
23799
- dataset;
23855
+ var files = opts.files || [];
23856
+ var dataset;
23800
23857
 
23858
+ cli.checkCommandEnv('i');
23801
23859
  if (opts.stdin) {
23802
23860
  return importFile('/dev/stdin', opts);
23803
23861
  }
23804
23862
 
23863
+
23805
23864
  if (files.length > 0 === false) {
23806
23865
  stop('Missing input file(s)');
23807
23866
  }
23808
23867
 
23809
23868
  verbose("Importing: " + files.join(' '));
23810
- if (files.length == 1 && /\.zip/i.test(files[0])) {
23811
- dataset = importZipFile(files[0], opts);
23812
- } else if (files.length == 1) {
23869
+
23870
+ // copy opts, so parameters can be modified within this command
23871
+ opts = Object.assign({}, opts);
23872
+ opts.input = Object.assign({}, opts.input); // make sure we have a cache
23873
+
23874
+ files = expandFiles(files, opts.input);
23875
+
23876
+ if (files.length === 0) {
23877
+ stop('Missing importable files');
23878
+ }
23879
+
23880
+ if (files.length == 1) {
23813
23881
  dataset = importFile(files[0], opts);
23814
- } else if (opts.merge_files) {
23815
- // TODO: deprecate and remove this option (use -merge-layers cmd instead)
23816
- dataset = importFilesTogether(files, opts);
23817
- dataset.layers = cmd.mergeLayers(dataset.layers);
23818
23882
  } else {
23819
23883
  dataset = importFilesTogether(files, opts);
23820
23884
  }
23885
+
23886
+ if (opts.merge_files && files.length > 1) {
23887
+ // TODO: deprecate and remove this option (use -merge-layers cmd instead)
23888
+ dataset.layers = cmd.mergeLayers(dataset.layers);
23889
+ }
23821
23890
  return dataset;
23822
23891
  };
23823
23892
 
23893
+ function expandFiles(files, cache) {
23894
+ var files2 = [];
23895
+ files.forEach(function(file) {
23896
+ var expanded;
23897
+ if (isZipFile(file)) {
23898
+ expanded = expandZipFile(file, cache);
23899
+ } else if (isKmzFile(file)) {
23900
+ expanded = expandKmzFile(file, cache);
23901
+ } else {
23902
+ expanded = [file]; // ordinary file, no change
23903
+ }
23904
+ files2 = files2.concat(expanded);
23905
+ });
23906
+ return files2;
23907
+ }
23908
+
23909
+ function expandKmzFile(file, cache) {
23910
+ var files = expandZipFile(file, cache);
23911
+ var name = replaceFileExtension(parseLocalPath(file).filename, 'kml');
23912
+ if (files[0] == 'doc.kml') {
23913
+ files[0] = name;
23914
+ cache[name] = cache['doc.kml'];
23915
+ }
23916
+ return files;
23917
+ }
23918
+
23919
+ function expandZipFile(file, cache) {
23920
+ var input;
23921
+ if (file in cache) {
23922
+ input = cache[file];
23923
+ } else {
23924
+ input = file;
23925
+ cli.checkFileExists(file);
23926
+ }
23927
+ return extractFiles(input, cache);
23928
+ }
23929
+
23824
23930
  // Let the web UI replace importFile() with a browser-friendly version
23825
23931
  function replaceImportFile(func) {
23826
23932
  _importFile = func;
@@ -23839,6 +23945,7 @@ ${svg}
23839
23945
  content;
23840
23946
 
23841
23947
  cli.checkFileExists(path, cache);
23948
+
23842
23949
  if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf') && !cached) {
23843
23950
  // these file types are read incrementally
23844
23951
  content = null;
@@ -23861,6 +23968,7 @@ ${svg}
23861
23968
  stop('Unrecognized file type:', path);
23862
23969
  }
23863
23970
  // TODO: consider using a temp file, to support incremental reading
23971
+ // read to buffer, even for string-based types (to support larger input files)
23864
23972
  content = require('zlib').gunzipSync(cli.readFile(pathgz));
23865
23973
 
23866
23974
  } else { // type can't be inferred from filename -- try reading as text
@@ -23899,8 +24007,8 @@ ${svg}
23899
24007
  input = path;
23900
24008
  }
23901
24009
  var files = extractFiles(input, cache);
23902
- var zipOpts = Object.assign({}, opts, {input: cache});
23903
- return importFilesTogether(files, zipOpts);
24010
+ var zipOpts = Object.assign({}, opts, {input: cache, files: files});
24011
+ return cmd.importFiles(zipOpts);
23904
24012
  }
23905
24013
 
23906
24014
  // Import multiple files to a single dataset
@@ -28547,15 +28655,15 @@ ${svg}
28547
28655
  var brighter = 1 / darker;
28548
28656
 
28549
28657
  var reI = "\\s*([+-]?\\d+)\\s*",
28550
- reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
28551
- reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
28658
+ reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",
28659
+ reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
28552
28660
  reHex = /^#([0-9a-f]{3,8})$/,
28553
- reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
28554
- reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
28555
- reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
28556
- reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
28557
- reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
28558
- reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
28661
+ reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`),
28662
+ reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`),
28663
+ reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`),
28664
+ reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`),
28665
+ reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`),
28666
+ reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`);
28559
28667
 
28560
28668
  var named = {
28561
28669
  aliceblue: 0xf0f8ff,
@@ -28709,14 +28817,15 @@ ${svg}
28709
28817
  };
28710
28818
 
28711
28819
  define(Color, color, {
28712
- copy: function(channels) {
28820
+ copy(channels) {
28713
28821
  return Object.assign(new this.constructor, this, channels);
28714
28822
  },
28715
- displayable: function() {
28823
+ displayable() {
28716
28824
  return this.rgb().displayable();
28717
28825
  },
28718
28826
  hex: color_formatHex, // Deprecated! Use color.formatHex.
28719
28827
  formatHex: color_formatHex,
28828
+ formatHex8: color_formatHex8,
28720
28829
  formatHsl: color_formatHsl,
28721
28830
  formatRgb: color_formatRgb,
28722
28831
  toString: color_formatRgb
@@ -28726,6 +28835,10 @@ ${svg}
28726
28835
  return this.rgb().formatHex();
28727
28836
  }
28728
28837
 
28838
+ function color_formatHex8() {
28839
+ return this.rgb().formatHex8();
28840
+ }
28841
+
28729
28842
  function color_formatHsl() {
28730
28843
  return hslConvert(this).formatHsl();
28731
28844
  }
@@ -28781,18 +28894,21 @@ ${svg}
28781
28894
  }
28782
28895
 
28783
28896
  define(Rgb, rgb$1, extend(Color, {
28784
- brighter: function(k) {
28897
+ brighter(k) {
28785
28898
  k = k == null ? brighter : Math.pow(brighter, k);
28786
28899
  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
28787
28900
  },
28788
- darker: function(k) {
28901
+ darker(k) {
28789
28902
  k = k == null ? darker : Math.pow(darker, k);
28790
28903
  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
28791
28904
  },
28792
- rgb: function() {
28905
+ rgb() {
28793
28906
  return this;
28794
28907
  },
28795
- displayable: function() {
28908
+ clamp() {
28909
+ return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));
28910
+ },
28911
+ displayable() {
28796
28912
  return (-0.5 <= this.r && this.r < 255.5)
28797
28913
  && (-0.5 <= this.g && this.g < 255.5)
28798
28914
  && (-0.5 <= this.b && this.b < 255.5)
@@ -28800,25 +28916,34 @@ ${svg}
28800
28916
  },
28801
28917
  hex: rgb_formatHex, // Deprecated! Use color.formatHex.
28802
28918
  formatHex: rgb_formatHex,
28919
+ formatHex8: rgb_formatHex8,
28803
28920
  formatRgb: rgb_formatRgb,
28804
28921
  toString: rgb_formatRgb
28805
28922
  }));
28806
28923
 
28807
28924
  function rgb_formatHex() {
28808
- return "#" + hex(this.r) + hex(this.g) + hex(this.b);
28925
+ return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;
28926
+ }
28927
+
28928
+ function rgb_formatHex8() {
28929
+ return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;
28809
28930
  }
28810
28931
 
28811
28932
  function rgb_formatRgb() {
28812
- var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
28813
- return (a === 1 ? "rgb(" : "rgba(")
28814
- + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
28815
- + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
28816
- + Math.max(0, Math.min(255, Math.round(this.b) || 0))
28817
- + (a === 1 ? ")" : ", " + a + ")");
28933
+ const a = clampa(this.opacity);
28934
+ return `${a === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? ")" : `, ${a})`}`;
28935
+ }
28936
+
28937
+ function clampa(opacity) {
28938
+ return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity));
28939
+ }
28940
+
28941
+ function clampi(value) {
28942
+ return Math.max(0, Math.min(255, Math.round(value) || 0));
28818
28943
  }
28819
28944
 
28820
28945
  function hex(value) {
28821
- value = Math.max(0, Math.min(255, Math.round(value) || 0));
28946
+ value = clampi(value);
28822
28947
  return (value < 16 ? "0" : "") + value.toString(16);
28823
28948
  }
28824
28949
 
@@ -28867,15 +28992,15 @@ ${svg}
28867
28992
  }
28868
28993
 
28869
28994
  define(Hsl, hsl$2, extend(Color, {
28870
- brighter: function(k) {
28995
+ brighter(k) {
28871
28996
  k = k == null ? brighter : Math.pow(brighter, k);
28872
28997
  return new Hsl(this.h, this.s, this.l * k, this.opacity);
28873
28998
  },
28874
- darker: function(k) {
28999
+ darker(k) {
28875
29000
  k = k == null ? darker : Math.pow(darker, k);
28876
29001
  return new Hsl(this.h, this.s, this.l * k, this.opacity);
28877
29002
  },
28878
- rgb: function() {
29003
+ rgb() {
28879
29004
  var h = this.h % 360 + (this.h < 0) * 360,
28880
29005
  s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
28881
29006
  l = this.l,
@@ -28888,21 +29013,29 @@ ${svg}
28888
29013
  this.opacity
28889
29014
  );
28890
29015
  },
28891
- displayable: function() {
29016
+ clamp() {
29017
+ return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));
29018
+ },
29019
+ displayable() {
28892
29020
  return (0 <= this.s && this.s <= 1 || isNaN(this.s))
28893
29021
  && (0 <= this.l && this.l <= 1)
28894
29022
  && (0 <= this.opacity && this.opacity <= 1);
28895
29023
  },
28896
- formatHsl: function() {
28897
- var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
28898
- return (a === 1 ? "hsl(" : "hsla(")
28899
- + (this.h || 0) + ", "
28900
- + (this.s || 0) * 100 + "%, "
28901
- + (this.l || 0) * 100 + "%"
28902
- + (a === 1 ? ")" : ", " + a + ")");
29024
+ formatHsl() {
29025
+ const a = clampa(this.opacity);
29026
+ return `${a === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ")" : `, ${a})`}`;
28903
29027
  }
28904
29028
  }));
28905
29029
 
29030
+ function clamph(value) {
29031
+ value = (value || 0) % 360;
29032
+ return value < 0 ? value + 360 : value;
29033
+ }
29034
+
29035
+ function clampt(value) {
29036
+ return Math.max(0, Math.min(1, value || 0));
29037
+ }
29038
+
28906
29039
  /* From FvD 13.37, CSS Color Module Level 3 */
28907
29040
  function hsl2rgb(h, m1, m2) {
28908
29041
  return (h < 60 ? m1 + (m2 - m1) * h / 60
@@ -28955,13 +29088,13 @@ ${svg}
28955
29088
  }
28956
29089
 
28957
29090
  define(Lab, lab$1, extend(Color, {
28958
- brighter: function(k) {
29091
+ brighter(k) {
28959
29092
  return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
28960
29093
  },
28961
- darker: function(k) {
29094
+ darker(k) {
28962
29095
  return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
28963
29096
  },
28964
- rgb: function() {
29097
+ rgb() {
28965
29098
  var y = (this.l + 16) / 116,
28966
29099
  x = isNaN(this.a) ? y : y + this.a / 500,
28967
29100
  z = isNaN(this.b) ? y : y - this.b / 200;
@@ -29023,13 +29156,13 @@ ${svg}
29023
29156
  }
29024
29157
 
29025
29158
  define(Hcl, hcl$2, extend(Color, {
29026
- brighter: function(k) {
29159
+ brighter(k) {
29027
29160
  return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
29028
29161
  },
29029
- darker: function(k) {
29162
+ darker(k) {
29030
29163
  return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
29031
29164
  },
29032
- rgb: function() {
29165
+ rgb() {
29033
29166
  return hcl2lab(this).rgb();
29034
29167
  }
29035
29168
  }));
@@ -29069,15 +29202,15 @@ ${svg}
29069
29202
  }
29070
29203
 
29071
29204
  define(Cubehelix, cubehelix$3, extend(Color, {
29072
- brighter: function(k) {
29205
+ brighter(k) {
29073
29206
  k = k == null ? brighter : Math.pow(brighter, k);
29074
29207
  return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
29075
29208
  },
29076
- darker: function(k) {
29209
+ darker(k) {
29077
29210
  k = k == null ? darker : Math.pow(darker, k);
29078
29211
  return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
29079
29212
  },
29080
- rgb: function() {
29213
+ rgb() {
29081
29214
  var h = isNaN(this.h) ? 0 : (this.h + 120) * radians,
29082
29215
  l = +this.l,
29083
29216
  a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
@@ -39434,12 +39567,12 @@ ${svg}
39434
39567
  var parser = getOptionParser();
39435
39568
  // support multiline string of commands pasted into console
39436
39569
  str = str.split(/\n+/g).map(function(str) {
39437
- var match = /^[a-z][\w-]*/.exec(str = str.trim());
39570
+ var match = /^[a-z][\w-]*/i.exec(str = str.trim());
39438
39571
  //if (match && parser.isCommandName(match[0])) {
39439
39572
  if (match) {
39440
39573
  // add hyphen prefix to bare command
39441
- // also add hyphen to non-command strings, for a better error message
39442
- // ("unsupported command" instead of "The -i command cannot be run in the browser")
39574
+ // also add hyphen to non-command strings, for a better error message
39575
+ // ("unsupported command" instead of "The -i command cannot be run in the browser")
39443
39576
  str = '-' + str;
39444
39577
  }
39445
39578
  return str;
@@ -39449,15 +39582,10 @@ ${svg}
39449
39582
 
39450
39583
  // Parse a command line string for the browser console
39451
39584
  function parseConsoleCommands(raw) {
39452
- var blocked = ['i', 'include', 'require', 'external'];
39453
39585
  var str = standardizeConsoleCommands(raw);
39454
- var parsed;
39455
- parsed = parseCommands(str);
39586
+ var parsed = parseCommands(str);
39456
39587
  parsed.forEach(function(cmd) {
39457
- var i = blocked.indexOf(cmd.name);
39458
- if (i > -1) {
39459
- stop("The -" + blocked[i] + " command cannot be run in the browser");
39460
- }
39588
+ cli.checkCommandEnv(cmd.name);
39461
39589
  });
39462
39590
  return parsed;
39463
39591
  }