mapshaper 0.7.18 → 0.7.19

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/mapshaper.js CHANGED
@@ -19880,7 +19880,7 @@
19880
19880
  function exportSVG(dataset, opts) {
19881
19881
  var namespace = 'xmlns="http://www.w3.org/2000/svg"';
19882
19882
  var defs = [];
19883
- var frame, svg, layers, metadataJSON;
19883
+ var frame, svg, layers, metadataJSON, files, svgFile;
19884
19884
  var style = '';
19885
19885
 
19886
19886
  // kludge for map keys
@@ -19901,6 +19901,8 @@
19901
19901
  // use invert_y: 0 setting for screen coordinates and geojson polygon generation
19902
19902
  // use 1px default margin so typical strokes don't get cut off on the sides
19903
19903
  opts = Object.assign({invert_y: true, margin: "1"}, opts);
19904
+ opts.svg_image_files = [];
19905
+ opts.svg_file_base = getSvgFileBase(dataset, opts);
19904
19906
  frame = getFrameData(dataset, opts);
19905
19907
  fitDatasetToFrame(dataset, frame);
19906
19908
  setCoordinatePrecision(dataset, opts.precision || 0.01);
@@ -19953,10 +19955,17 @@
19953
19955
  ${svg}
19954
19956
  </svg>`;
19955
19957
  svg = utils.format(template, frame.width, frame.height, 0, 0, frame.width, frame.height);
19956
- return [{
19958
+ svgFile = {
19957
19959
  content: svg,
19958
19960
  filename: opts.file || getOutputFileBase(dataset) + '.svg'
19959
- }];
19961
+ };
19962
+ files = [svgFile].concat(opts.svg_image_files);
19963
+ return files;
19964
+ }
19965
+
19966
+ function getSvgFileBase(dataset, opts) {
19967
+ var file = opts.file || getOutputFileBase(dataset) + '.svg';
19968
+ return file.replace(/\.svg$/i, '');
19960
19969
  }
19961
19970
 
19962
19971
  function getMetadataBlock(metadataJSON, viewBox) {
@@ -20047,7 +20056,9 @@ ${svg}
20047
20056
  layerObj.children = [];
20048
20057
  return layerObj;
20049
20058
  }
20050
- href = encodeRasterPreview(rendered.preview, opts);
20059
+ href = opts.linked_images ?
20060
+ exportLinkedRasterPreview(rendered.preview, opts) :
20061
+ encodeRasterPreview(rendered.preview, opts);
20051
20062
  layerObj.children = [{
20052
20063
  tag: 'image',
20053
20064
  properties: {
@@ -20121,6 +20132,30 @@ ${svg}
20121
20132
  return 'data:image/' + format + ';base64,' + data;
20122
20133
  }
20123
20134
 
20135
+ function exportLinkedRasterPreview(preview, opts) {
20136
+ var format = getSvgRasterFormat(preview, opts);
20137
+ var data = format == 'png' ? encodePng(preview) : encodeJpeg(preview, opts);
20138
+ var ext = format == 'jpeg' ? 'jpg' : format;
20139
+ var filename = opts.svg_file_base + '-image-' + (opts.svg_image_files.length + 1) + '.' + ext;
20140
+ opts.svg_image_files.push({
20141
+ filename: filename,
20142
+ content: base64ToBytes(data)
20143
+ });
20144
+ return filename;
20145
+ }
20146
+
20147
+ function base64ToBytes(str) {
20148
+ if (typeof Buffer != 'undefined') {
20149
+ return Buffer.from(str, 'base64');
20150
+ }
20151
+ var bin = atob(str);
20152
+ var bytes = new Uint8Array(bin.length);
20153
+ for (var i = 0; i < bin.length; i++) {
20154
+ bytes[i] = bin.charCodeAt(i);
20155
+ }
20156
+ return bytes;
20157
+ }
20158
+
20124
20159
  function getSvgRasterFormat(preview, opts) {
20125
20160
  var fmt = opts.svg_raster_format || opts.raster_format || null;
20126
20161
  if (fmt) return fmt == 'jpg' ? 'jpeg' : fmt;
@@ -20136,11 +20171,11 @@ ${svg}
20136
20171
  }
20137
20172
 
20138
20173
  function encodeJpeg(preview, opts) {
20174
+ var quality = getJpegQuality(opts);
20139
20175
  if (runningInBrowser() && typeof document != 'undefined') {
20140
- return encodeWithCanvas(preview, 'image/jpeg', opts.svg_raster_quality || 0.85);
20176
+ return encodeWithCanvas(preview, 'image/jpeg', quality / 100);
20141
20177
  }
20142
20178
  var jpeg = require$1('jpeg-js');
20143
- var quality = Math.round((opts.svg_raster_quality || 0.85) * 100);
20144
20179
  return Buffer.from(jpeg.encode({
20145
20180
  data: Buffer.from(preview.pixels),
20146
20181
  width: preview.width,
@@ -20148,6 +20183,14 @@ ${svg}
20148
20183
  }, quality).data).toString('base64');
20149
20184
  }
20150
20185
 
20186
+ function getJpegQuality(opts) {
20187
+ var quality = opts.jpeg_quality == null ? 85 : opts.jpeg_quality;
20188
+ if ((quality >= 1 && quality <= 100) === false) {
20189
+ stop$1('jpeg-quality= option should be a number from 1 to 100');
20190
+ }
20191
+ return Math.round(quality);
20192
+ }
20193
+
20151
20194
  function encodePng(preview) {
20152
20195
  if (runningInBrowser() && typeof document != 'undefined') {
20153
20196
  return encodeWithCanvas(preview, 'image/png');
@@ -29002,6 +29045,10 @@ ${svg}
29002
29045
  if ('topojson_precision' in o && o.topojson_precision > 0 === false) {
29003
29046
  error('topojson-precision= option should be a positive number');
29004
29047
  }
29048
+
29049
+ if ('jpeg_quality' in o && (o.jpeg_quality >= 1 && o.jpeg_quality <= 100) === false) {
29050
+ error('jpeg-quality= option should be a number from 1 to 100');
29051
+ }
29005
29052
  }
29006
29053
 
29007
29054
  var assignmentRxp = /^([a-z0-9_+-]+)=(?!=)(.*)$/i; // exclude ==
@@ -30408,6 +30455,14 @@ ${svg}
30408
30455
  describe: '[SVG] raster pixels per SVG pixel (default is 1)',
30409
30456
  type: 'number'
30410
30457
  })
30458
+ .option('linked-images', {
30459
+ describe: '[SVG] link raster images as external files',
30460
+ type: 'flag'
30461
+ })
30462
+ .option('jpeg-quality', {
30463
+ describe: '[SVG] JPEG quality for raster images, 1-100 (default is 85)',
30464
+ type: 'number'
30465
+ })
30411
30466
  .option('fit-extent', {
30412
30467
  describe: '[SVG] layer to use for the map extent'
30413
30468
  })
@@ -31432,6 +31487,10 @@ ${svg}
31432
31487
  .option('nodata-color', {
31433
31488
  describe: '[raster] color for uncovered pixels after reprojection'
31434
31489
  })
31490
+ .option('background', {
31491
+ describe: '[raster] alias for nodata-color',
31492
+ alias_to: 'nodata-color'
31493
+ })
31435
31494
  .option('resampling', {
31436
31495
  describe: '[raster] nearest or bilinear (default is bilinear)'
31437
31496
  })
@@ -51110,7 +51169,7 @@ ${svg}
51110
51169
  bbox = opts.output_bbox || opts.outputBbox || getProjectedMeshBBox(mesh);
51111
51170
  if (!bbox) stop$1('Unable to project raster layer');
51112
51171
  outSize = getOutputGridSize(grid, bbox, opts);
51113
- outGrid = createProjectedRasterGrid(grid, bbox, outSize.width, outSize.height, opts);
51172
+ outGrid = createProjectedRasterGrid(grid, raster, bbox, outSize.width, outSize.height, opts);
51114
51173
  timeStart(timing, 'rasterize');
51115
51174
  rasterizeProjectedMesh(grid, outGrid, mesh, getRasterProjectionSampleMethod(raster, opts));
51116
51175
  timeEnd(timing, 'rasterize');
@@ -51379,13 +51438,13 @@ ${svg}
51379
51438
  return xmin < Infinity && xmax > xmin && ymax > ymin ? [xmin, ymin, xmax, ymax] : null;
51380
51439
  }
51381
51440
 
51382
- function createProjectedRasterGrid(grid, bbox, widthArg, heightArg, opts) {
51441
+ function createProjectedRasterGrid(grid, raster, bbox, widthArg, heightArg, opts) {
51383
51442
  var width = widthArg || grid.width;
51384
51443
  var height = heightArg || grid.height;
51385
- var bands = getOutputBandCount(grid, opts);
51444
+ var bands = getOutputBandCount(grid, raster, opts);
51386
51445
  var samples = new grid.samples.constructor(width * height * bands);
51387
51446
  var coverage = new Uint8Array(width * height);
51388
- fillProjectedRasterSamples(samples, bands, grid, opts || {});
51447
+ fillProjectedRasterSamples(samples, bands, grid, raster, opts || {});
51389
51448
  return Object.assign({}, grid, {
51390
51449
  width: width,
51391
51450
  height: height,
@@ -51422,13 +51481,13 @@ ${svg}
51422
51481
  return {width: width, height: height};
51423
51482
  }
51424
51483
 
51425
- function getOutputBandCount(grid, opts) {
51426
- var color = getNoDataColor(opts);
51484
+ function getOutputBandCount(grid, raster, opts) {
51485
+ var color = getNoDataColor(raster, opts);
51427
51486
  return color && color.a === 0 && grid.bands > 1 && grid.bands < 4 ? 4 : grid.bands;
51428
51487
  }
51429
51488
 
51430
- function fillProjectedRasterSamples(samples, bands, grid, opts) {
51431
- var color = getNoDataColor(opts);
51489
+ function fillProjectedRasterSamples(samples, bands, grid, raster, opts) {
51490
+ var color = getNoDataColor(raster, opts);
51432
51491
  var noData = grid.nodata;
51433
51492
  if (color) {
51434
51493
  fillProjectedRasterColor(samples, bands, color);
@@ -51438,10 +51497,12 @@ ${svg}
51438
51497
  samples.fill(noData);
51439
51498
  }
51440
51499
 
51441
- function getNoDataColor(opts) {
51500
+ function getNoDataColor(raster, opts) {
51442
51501
  var arg = opts.nodata_color || opts.nodataColor;
51443
51502
  var color;
51444
- if (arg == null || arg === '') return null;
51503
+ if (arg == null || arg === '') {
51504
+ return rasterAppearsCategorical(raster) ? null : {r: 255, g: 255, b: 255, a: 1};
51505
+ }
51445
51506
  if (String(arg).toLowerCase() == 'transparent') {
51446
51507
  return {r: 0, g: 0, b: 0, a: 0};
51447
51508
  }
@@ -58269,7 +58330,7 @@ ${svg}
58269
58330
  });
58270
58331
  }
58271
58332
 
58272
- var version = "0.7.18";
58333
+ var version = "0.7.19";
58273
58334
 
58274
58335
  // Parse command line args into commands and run them
58275
58336
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.7.18",
3
+ "version": "0.7.19",
4
4
  "description": "A tool for editing geospatial data for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
package/www/index.html CHANGED
@@ -375,8 +375,8 @@ encoding=big5</span>. Click to see all options.</div></div></div>
375
375
  </div>
376
376
  <div class="mshp-main-map main-area map-area">
377
377
  <div class="intersection-display">
378
- <span class="intersection-count">0 line intersections</span>
379
- <div class="repair-btn text-btn colored-text">Repair</div>
378
+ <span class="intersection-count">0 line intersections</span>&nbsp;
379
+ <span class="repair-btn text-btn colored-text">repair</span>
380
380
  </div>
381
381
  <div class="basemap-overlay-buttons basemap-buttons"></div>
382
382
  <div class="map-layers"></div>
@@ -15074,6 +15074,7 @@
15074
15074
  }
15075
15075
 
15076
15076
  function updateControls() {
15077
+ syncTargetLayer();
15077
15078
  var geom = targetLayer && targetLayer.geometry_type;
15078
15079
  var manualIds = getSelectionIds();
15079
15080
  if (!targetLayer) return;
@@ -15159,6 +15160,7 @@
15159
15160
 
15160
15161
  function runStyleCommand(styles, opts) {
15161
15162
  var parts = ['-style'];
15163
+ syncTargetLayer();
15162
15164
  var ids = getTargetIds();
15163
15165
  if (!gui.console || !targetLayer || ids.length === 0) return;
15164
15166
  if (!opts || !opts.preservePreset) {
@@ -15187,6 +15189,7 @@
15187
15189
 
15188
15190
  function applyRandomFillColors() {
15189
15191
  var cmd = '-classify colors=random non-adjacent';
15192
+ syncTargetLayer();
15190
15193
  if (!gui.console || !targetLayer || targetLayer.geometry_type != 'polygon') return;
15191
15194
  if (getActiveLayer() != targetLayer) {
15192
15195
  cmd += ' target=' + internal.formatOptionValue(internal.getLayerTargetId(gui.model, targetLayer));
@@ -15250,6 +15253,7 @@
15250
15253
 
15251
15254
  function clearLayerStyle() {
15252
15255
  var parts = ['-style clear'];
15256
+ syncTargetLayer();
15253
15257
  if (!gui.console || !targetLayer) return;
15254
15258
  presetControl.clearSelection();
15255
15259
  addTargetOption(parts);
@@ -15335,6 +15339,17 @@
15335
15339
  return active && active.layer;
15336
15340
  }
15337
15341
 
15342
+ function syncTargetLayer() {
15343
+ var lyr = getActiveLayer();
15344
+ if (lyr == targetLayer) return;
15345
+ if (layerCanBeStyled(lyr)) {
15346
+ targetLayer = lyr;
15347
+ if (hit) hit.clearSelection();
15348
+ } else {
15349
+ targetLayer = null;
15350
+ }
15351
+ }
15352
+
15338
15353
  function closePanel() {
15339
15354
  turnOff();
15340
15355
  if (gui.interaction.getMode() == 'line_style' || gui.interaction.getMode() == 'polygon_style') {
@@ -15654,6 +15669,7 @@
15654
15669
  }
15655
15670
 
15656
15671
  function updateControls() {
15672
+ syncTargetLayer();
15657
15673
  var representation = getPointRepresentation();
15658
15674
  updateCreateLabelsButton();
15659
15675
  title.text(representation == 'circle' ? 'Circle styles' : 'Point symbols');
@@ -15798,6 +15814,7 @@
15798
15814
  }
15799
15815
 
15800
15816
  function runStyleCommand(args, title) {
15817
+ syncTargetLayer();
15801
15818
  var ids = getTargetIds();
15802
15819
  var parts = ['-style'].concat(args);
15803
15820
  if (!targetLayer || ids.length === 0) return;
@@ -16001,6 +16018,17 @@
16001
16018
  return active && active.layer;
16002
16019
  }
16003
16020
 
16021
+ function syncTargetLayer() {
16022
+ var lyr = getActiveLayer();
16023
+ if (lyr == targetLayer) return;
16024
+ if (layerCanBeStyled(lyr)) {
16025
+ targetLayer = lyr;
16026
+ if (hit) hit.clearSelection();
16027
+ } else {
16028
+ targetLayer = null;
16029
+ }
16030
+ }
16031
+
16004
16032
  function modelSelectLayer(lyr, dataset) {
16005
16033
  if (lyr) lyr.hidden = false;
16006
16034
  gui.model.selectLayer(lyr, dataset);
package/www/mapshaper.js CHANGED
@@ -19880,7 +19880,7 @@
19880
19880
  function exportSVG(dataset, opts) {
19881
19881
  var namespace = 'xmlns="http://www.w3.org/2000/svg"';
19882
19882
  var defs = [];
19883
- var frame, svg, layers, metadataJSON;
19883
+ var frame, svg, layers, metadataJSON, files, svgFile;
19884
19884
  var style = '';
19885
19885
 
19886
19886
  // kludge for map keys
@@ -19901,6 +19901,8 @@
19901
19901
  // use invert_y: 0 setting for screen coordinates and geojson polygon generation
19902
19902
  // use 1px default margin so typical strokes don't get cut off on the sides
19903
19903
  opts = Object.assign({invert_y: true, margin: "1"}, opts);
19904
+ opts.svg_image_files = [];
19905
+ opts.svg_file_base = getSvgFileBase(dataset, opts);
19904
19906
  frame = getFrameData(dataset, opts);
19905
19907
  fitDatasetToFrame(dataset, frame);
19906
19908
  setCoordinatePrecision(dataset, opts.precision || 0.01);
@@ -19953,10 +19955,17 @@
19953
19955
  ${svg}
19954
19956
  </svg>`;
19955
19957
  svg = utils.format(template, frame.width, frame.height, 0, 0, frame.width, frame.height);
19956
- return [{
19958
+ svgFile = {
19957
19959
  content: svg,
19958
19960
  filename: opts.file || getOutputFileBase(dataset) + '.svg'
19959
- }];
19961
+ };
19962
+ files = [svgFile].concat(opts.svg_image_files);
19963
+ return files;
19964
+ }
19965
+
19966
+ function getSvgFileBase(dataset, opts) {
19967
+ var file = opts.file || getOutputFileBase(dataset) + '.svg';
19968
+ return file.replace(/\.svg$/i, '');
19960
19969
  }
19961
19970
 
19962
19971
  function getMetadataBlock(metadataJSON, viewBox) {
@@ -20047,7 +20056,9 @@ ${svg}
20047
20056
  layerObj.children = [];
20048
20057
  return layerObj;
20049
20058
  }
20050
- href = encodeRasterPreview(rendered.preview, opts);
20059
+ href = opts.linked_images ?
20060
+ exportLinkedRasterPreview(rendered.preview, opts) :
20061
+ encodeRasterPreview(rendered.preview, opts);
20051
20062
  layerObj.children = [{
20052
20063
  tag: 'image',
20053
20064
  properties: {
@@ -20121,6 +20132,30 @@ ${svg}
20121
20132
  return 'data:image/' + format + ';base64,' + data;
20122
20133
  }
20123
20134
 
20135
+ function exportLinkedRasterPreview(preview, opts) {
20136
+ var format = getSvgRasterFormat(preview, opts);
20137
+ var data = format == 'png' ? encodePng(preview) : encodeJpeg(preview, opts);
20138
+ var ext = format == 'jpeg' ? 'jpg' : format;
20139
+ var filename = opts.svg_file_base + '-image-' + (opts.svg_image_files.length + 1) + '.' + ext;
20140
+ opts.svg_image_files.push({
20141
+ filename: filename,
20142
+ content: base64ToBytes(data)
20143
+ });
20144
+ return filename;
20145
+ }
20146
+
20147
+ function base64ToBytes(str) {
20148
+ if (typeof Buffer != 'undefined') {
20149
+ return Buffer.from(str, 'base64');
20150
+ }
20151
+ var bin = atob(str);
20152
+ var bytes = new Uint8Array(bin.length);
20153
+ for (var i = 0; i < bin.length; i++) {
20154
+ bytes[i] = bin.charCodeAt(i);
20155
+ }
20156
+ return bytes;
20157
+ }
20158
+
20124
20159
  function getSvgRasterFormat(preview, opts) {
20125
20160
  var fmt = opts.svg_raster_format || opts.raster_format || null;
20126
20161
  if (fmt) return fmt == 'jpg' ? 'jpeg' : fmt;
@@ -20136,11 +20171,11 @@ ${svg}
20136
20171
  }
20137
20172
 
20138
20173
  function encodeJpeg(preview, opts) {
20174
+ var quality = getJpegQuality(opts);
20139
20175
  if (runningInBrowser() && typeof document != 'undefined') {
20140
- return encodeWithCanvas(preview, 'image/jpeg', opts.svg_raster_quality || 0.85);
20176
+ return encodeWithCanvas(preview, 'image/jpeg', quality / 100);
20141
20177
  }
20142
20178
  var jpeg = require$1('jpeg-js');
20143
- var quality = Math.round((opts.svg_raster_quality || 0.85) * 100);
20144
20179
  return Buffer.from(jpeg.encode({
20145
20180
  data: Buffer.from(preview.pixels),
20146
20181
  width: preview.width,
@@ -20148,6 +20183,14 @@ ${svg}
20148
20183
  }, quality).data).toString('base64');
20149
20184
  }
20150
20185
 
20186
+ function getJpegQuality(opts) {
20187
+ var quality = opts.jpeg_quality == null ? 85 : opts.jpeg_quality;
20188
+ if ((quality >= 1 && quality <= 100) === false) {
20189
+ stop$1('jpeg-quality= option should be a number from 1 to 100');
20190
+ }
20191
+ return Math.round(quality);
20192
+ }
20193
+
20151
20194
  function encodePng(preview) {
20152
20195
  if (runningInBrowser() && typeof document != 'undefined') {
20153
20196
  return encodeWithCanvas(preview, 'image/png');
@@ -29002,6 +29045,10 @@ ${svg}
29002
29045
  if ('topojson_precision' in o && o.topojson_precision > 0 === false) {
29003
29046
  error('topojson-precision= option should be a positive number');
29004
29047
  }
29048
+
29049
+ if ('jpeg_quality' in o && (o.jpeg_quality >= 1 && o.jpeg_quality <= 100) === false) {
29050
+ error('jpeg-quality= option should be a number from 1 to 100');
29051
+ }
29005
29052
  }
29006
29053
 
29007
29054
  var assignmentRxp = /^([a-z0-9_+-]+)=(?!=)(.*)$/i; // exclude ==
@@ -30408,6 +30455,14 @@ ${svg}
30408
30455
  describe: '[SVG] raster pixels per SVG pixel (default is 1)',
30409
30456
  type: 'number'
30410
30457
  })
30458
+ .option('linked-images', {
30459
+ describe: '[SVG] link raster images as external files',
30460
+ type: 'flag'
30461
+ })
30462
+ .option('jpeg-quality', {
30463
+ describe: '[SVG] JPEG quality for raster images, 1-100 (default is 85)',
30464
+ type: 'number'
30465
+ })
30411
30466
  .option('fit-extent', {
30412
30467
  describe: '[SVG] layer to use for the map extent'
30413
30468
  })
@@ -31432,6 +31487,10 @@ ${svg}
31432
31487
  .option('nodata-color', {
31433
31488
  describe: '[raster] color for uncovered pixels after reprojection'
31434
31489
  })
31490
+ .option('background', {
31491
+ describe: '[raster] alias for nodata-color',
31492
+ alias_to: 'nodata-color'
31493
+ })
31435
31494
  .option('resampling', {
31436
31495
  describe: '[raster] nearest or bilinear (default is bilinear)'
31437
31496
  })
@@ -51110,7 +51169,7 @@ ${svg}
51110
51169
  bbox = opts.output_bbox || opts.outputBbox || getProjectedMeshBBox(mesh);
51111
51170
  if (!bbox) stop$1('Unable to project raster layer');
51112
51171
  outSize = getOutputGridSize(grid, bbox, opts);
51113
- outGrid = createProjectedRasterGrid(grid, bbox, outSize.width, outSize.height, opts);
51172
+ outGrid = createProjectedRasterGrid(grid, raster, bbox, outSize.width, outSize.height, opts);
51114
51173
  timeStart(timing, 'rasterize');
51115
51174
  rasterizeProjectedMesh(grid, outGrid, mesh, getRasterProjectionSampleMethod(raster, opts));
51116
51175
  timeEnd(timing, 'rasterize');
@@ -51379,13 +51438,13 @@ ${svg}
51379
51438
  return xmin < Infinity && xmax > xmin && ymax > ymin ? [xmin, ymin, xmax, ymax] : null;
51380
51439
  }
51381
51440
 
51382
- function createProjectedRasterGrid(grid, bbox, widthArg, heightArg, opts) {
51441
+ function createProjectedRasterGrid(grid, raster, bbox, widthArg, heightArg, opts) {
51383
51442
  var width = widthArg || grid.width;
51384
51443
  var height = heightArg || grid.height;
51385
- var bands = getOutputBandCount(grid, opts);
51444
+ var bands = getOutputBandCount(grid, raster, opts);
51386
51445
  var samples = new grid.samples.constructor(width * height * bands);
51387
51446
  var coverage = new Uint8Array(width * height);
51388
- fillProjectedRasterSamples(samples, bands, grid, opts || {});
51447
+ fillProjectedRasterSamples(samples, bands, grid, raster, opts || {});
51389
51448
  return Object.assign({}, grid, {
51390
51449
  width: width,
51391
51450
  height: height,
@@ -51422,13 +51481,13 @@ ${svg}
51422
51481
  return {width: width, height: height};
51423
51482
  }
51424
51483
 
51425
- function getOutputBandCount(grid, opts) {
51426
- var color = getNoDataColor(opts);
51484
+ function getOutputBandCount(grid, raster, opts) {
51485
+ var color = getNoDataColor(raster, opts);
51427
51486
  return color && color.a === 0 && grid.bands > 1 && grid.bands < 4 ? 4 : grid.bands;
51428
51487
  }
51429
51488
 
51430
- function fillProjectedRasterSamples(samples, bands, grid, opts) {
51431
- var color = getNoDataColor(opts);
51489
+ function fillProjectedRasterSamples(samples, bands, grid, raster, opts) {
51490
+ var color = getNoDataColor(raster, opts);
51432
51491
  var noData = grid.nodata;
51433
51492
  if (color) {
51434
51493
  fillProjectedRasterColor(samples, bands, color);
@@ -51438,10 +51497,12 @@ ${svg}
51438
51497
  samples.fill(noData);
51439
51498
  }
51440
51499
 
51441
- function getNoDataColor(opts) {
51500
+ function getNoDataColor(raster, opts) {
51442
51501
  var arg = opts.nodata_color || opts.nodataColor;
51443
51502
  var color;
51444
- if (arg == null || arg === '') return null;
51503
+ if (arg == null || arg === '') {
51504
+ return rasterAppearsCategorical(raster) ? null : {r: 255, g: 255, b: 255, a: 1};
51505
+ }
51445
51506
  if (String(arg).toLowerCase() == 'transparent') {
51446
51507
  return {r: 0, g: 0, b: 0, a: 0};
51447
51508
  }
@@ -58269,7 +58330,7 @@ ${svg}
58269
58330
  });
58270
58331
  }
58271
58332
 
58272
- var version = "0.7.18";
58333
+ var version = "0.7.19";
58273
58334
 
58274
58335
  // Parse command line args into commands and run them
58275
58336
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/www/page.css CHANGED
@@ -18,7 +18,7 @@
18
18
  --xlt-theme-col: #f4f8f9;
19
19
  --accent-col: #ffa; /* yellow logo text */
20
20
  --theme-col: #1385B7; /* blue header / btn col */
21
- --dk-theme-col: #1A6A96; /* btn hover col */
21
+ --dk-theme-col: #196d8e; /* #1A6A96; btn hover col */
22
22
  --lt-theme-col: #e6f7ff;
23
23
  --colored-text: #10699b;
24
24
  --normal-text: #333;
@@ -671,7 +671,7 @@ textarea:focus {
671
671
  min-width: 230px;
672
672
  word-wrap: break-word;
673
673
  text-align: left;
674
- margin-top: 12px;
674
+ margin-top: 16px;
675
675
  padding: 14px 16px 13px 18px;
676
676
  vertical-align: top;
677
677
  display: inline-block;
@@ -874,7 +874,7 @@ body.sidebar-resizing .sidebar-resize-handle::before,
874
874
 
875
875
  .sidebar-tabs {
876
876
  position: absolute;
877
- top: 85px; /* below line intersection repair link */
877
+ top: 66px; /* below line intersection repair link */
878
878
  left: 0;
879
879
  z-index: 40;
880
880
  pointer-events: auto;
@@ -882,6 +882,7 @@ body.sidebar-resizing .sidebar-resize-handle::before,
882
882
 
883
883
  body.sidebar-open .sidebar-tabs {
884
884
  left: var(--left-sidebar-width);
885
+ margin-left: -1.5px;
885
886
  }
886
887
 
887
888
  body.sidebar-tabs-over-popup .sidebar-tabs {
@@ -902,12 +903,17 @@ body.sidebar-tabs-over-popup .sidebar-tabs {
902
903
  pointer-events: auto;
903
904
  }
904
905
 
905
- .sidebar-tab:hover,
906
+ .sidebar-tab:hover {
907
+ background-color: var(--dk-theme-col);
908
+ }
909
+
906
910
  body.layers-open .layer-tab,
907
911
  body.console-open .console-tab {
908
- background-color: #1A6A96;
912
+ background-color: black;
909
913
  }
910
914
 
915
+
916
+
911
917
  .console-window {
912
918
  pointer-events: auto;
913
919
  background-color: black;
@@ -1109,7 +1115,6 @@ body.simplify .layer-control-btn {
1109
1115
  .layer-control .info-box {
1110
1116
  padding: 0;
1111
1117
  pointer-events: none;
1112
- background-color: transparent;
1113
1118
  }
1114
1119
 
1115
1120
  .layer-control div.info-box-scrolled {
@@ -2512,8 +2517,8 @@ body.dragging-color-picker * {
2512
2517
  cursor: pointer;
2513
2518
  }
2514
2519
 
2515
- .label-style-selection-row .label-editing-clear:hover {
2516
- color: black;
2520
+ .label-style-selection-row .label-editing-clear:hover,
2521
+ .repair-btn:hover {
2517
2522
  text-decoration: underline;
2518
2523
  }
2519
2524