tileserver-gl-light 4.6.6 → 4.7.0

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.
@@ -11,12 +11,12 @@ import { getPublicUrl } from './utils.js';
11
11
 
12
12
  const httpTester = /^(http(s)?:)?\/\//;
13
13
 
14
- const fixUrl = (req, url, publicUrl, opt_nokey) => {
14
+ const fixUrl = (req, url, publicUrl) => {
15
15
  if (!url || typeof url !== 'string' || url.indexOf('local://') !== 0) {
16
16
  return url;
17
17
  }
18
18
  const queryParams = [];
19
- if (!opt_nokey && req.query.key) {
19
+ if (req.query.key) {
20
20
  queryParams.unshift(`key=${encodeURIComponent(req.query.key)}`);
21
21
  }
22
22
  let query = '';
@@ -42,20 +42,10 @@ export const serve_style = {
42
42
  }
43
43
  // mapbox-gl-js viewer cannot handle sprite urls with query
44
44
  if (styleJSON_.sprite) {
45
- styleJSON_.sprite = fixUrl(
46
- req,
47
- styleJSON_.sprite,
48
- item.publicUrl,
49
- false,
50
- );
45
+ styleJSON_.sprite = fixUrl(req, styleJSON_.sprite, item.publicUrl);
51
46
  }
52
47
  if (styleJSON_.glyphs) {
53
- styleJSON_.glyphs = fixUrl(
54
- req,
55
- styleJSON_.glyphs,
56
- item.publicUrl,
57
- false,
58
- );
48
+ styleJSON_.glyphs = fixUrl(req, styleJSON_.glyphs, item.publicUrl);
59
49
  }
60
50
  return res.send(styleJSON_);
61
51
  });
@@ -98,9 +88,7 @@ export const serve_style = {
98
88
 
99
89
  const validationErrors = validate(styleFileData);
100
90
  if (validationErrors.length > 0) {
101
- console.log(
102
- `The file "${params.style}" is not valid a valid style file:`,
103
- );
91
+ console.log(`The file "${params.style}" is not a valid style file:`);
104
92
  for (const err of validationErrors) {
105
93
  console.log(`${err.line}: ${err.message}`);
106
94
  }
package/src/server.js CHANGED
@@ -141,20 +141,16 @@ function start(opts) {
141
141
 
142
142
  // Load all available icons into a settings object
143
143
  startupPromises.push(
144
- new Promise((resolve) => {
145
- getFiles(paths.icons).then((files) => {
146
- paths.availableIcons = files;
147
- resolve();
148
- });
144
+ getFiles(paths.icons).then((files) => {
145
+ paths.availableIcons = files;
149
146
  }),
150
147
  );
151
148
 
152
149
  if (options.dataDecorator) {
153
150
  try {
154
- options.dataDecoratorFunc = require(path.resolve(
155
- paths.root,
156
- options.dataDecorator,
157
- ));
151
+ options.dataDecoratorFunc = require(
152
+ path.resolve(paths.root, options.dataDecorator),
153
+ );
158
154
  } catch (e) {}
159
155
  }
160
156
 
@@ -183,15 +179,15 @@ function start(opts) {
183
179
  item,
184
180
  id,
185
181
  opts.publicUrl,
186
- (StyleSourceId, protocol) => {
182
+ (styleSourceId, protocol) => {
187
183
  let dataItemId;
188
184
  for (const id of Object.keys(data)) {
189
- if (id === StyleSourceId) {
185
+ if (id === styleSourceId) {
190
186
  // Style id was found in data ids, return that id
191
187
  dataItemId = id;
192
188
  } else {
193
189
  const fileType = Object.keys(data[id])[0];
194
- if (data[id][fileType] === StyleSourceId) {
190
+ if (data[id][fileType] === styleSourceId) {
195
191
  // Style id was found in data filename, return the id that filename belong to
196
192
  dataItemId = id;
197
193
  }
@@ -203,21 +199,21 @@ function start(opts) {
203
199
  } else {
204
200
  if (!allowMoreData) {
205
201
  console.log(
206
- `ERROR: style "${item.style}" using unknown file "${StyleSourceId}"! Skipping...`,
202
+ `ERROR: style "${item.style}" using unknown file "${styleSourceId}"! Skipping...`,
207
203
  );
208
204
  return undefined;
209
205
  } else {
210
206
  let id =
211
- StyleSourceId.substr(0, StyleSourceId.lastIndexOf('.')) ||
212
- StyleSourceId;
213
- if (isValidHttpUrl(StyleSourceId)) {
207
+ styleSourceId.substr(0, styleSourceId.lastIndexOf('.')) ||
208
+ styleSourceId;
209
+ if (isValidHttpUrl(styleSourceId)) {
214
210
  id =
215
- fnv1a(StyleSourceId) + '_' + id.replace(/^.*\/(.*)$/, '$1');
211
+ fnv1a(styleSourceId) + '_' + id.replace(/^.*\/(.*)$/, '$1');
216
212
  }
217
213
  while (data[id]) id += '_'; //if the data source id already exists, add a "_" untill it doesn't
218
214
  //Add the new data source to the data array.
219
215
  data[id] = {
220
- [protocol]: StyleSourceId,
216
+ [protocol]: styleSourceId,
221
217
  };
222
218
 
223
219
  return id;
@@ -240,15 +236,15 @@ function start(opts) {
240
236
  item,
241
237
  id,
242
238
  opts.publicUrl,
243
- (StyleSourceId) => {
239
+ function dataResolver(styleSourceId) {
244
240
  let fileType;
245
241
  let inputFile;
246
242
  for (const id of Object.keys(data)) {
247
243
  fileType = Object.keys(data[id])[0];
248
- if (StyleSourceId == id) {
244
+ if (styleSourceId == id) {
249
245
  inputFile = data[id][fileType];
250
246
  break;
251
- } else if (data[id][fileType] == StyleSourceId) {
247
+ } else if (data[id][fileType] == styleSourceId) {
252
248
  inputFile = data[id][fileType];
253
249
  break;
254
250
  }
@@ -257,7 +253,7 @@ function start(opts) {
257
253
  inputFile = path.resolve(options.paths[fileType], inputFile);
258
254
  }
259
255
 
260
- return { inputfile: inputFile, filetype: fileType };
256
+ return { inputFile, fileType };
261
257
  },
262
258
  ),
263
259
  );
@@ -348,7 +344,7 @@ function start(opts) {
348
344
  result.push({
349
345
  version: styleJSON.version,
350
346
  name: styleJSON.name,
351
- id: id,
347
+ id,
352
348
  url: `${getPublicUrl(
353
349
  opts.publicUrl,
354
350
  req,
@@ -427,9 +423,8 @@ function start(opts) {
427
423
  return res.status(404).send('Not found');
428
424
  }
429
425
  }
430
- data[
431
- 'server_version'
432
- ] = `${packageJson.name} v${packageJson.version}`;
426
+ data['server_version'] =
427
+ `${packageJson.name} v${packageJson.version}`;
433
428
  data['public_url'] = opts.publicUrl || '/';
434
429
  data['is_light'] = isLight;
435
430
  data['key_query_part'] = req.query.key
@@ -635,9 +630,9 @@ function start(opts) {
635
630
  enableShutdown(server);
636
631
 
637
632
  return {
638
- app: app,
639
- server: server,
640
- startupPromise: startupPromise,
633
+ app,
634
+ server,
635
+ startupPromise,
641
636
  };
642
637
  }
643
638
 
package/src/utils.js CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  import path from 'path';
4
- import fs from 'node:fs';
4
+ import fsPromises from 'fs/promises';
5
+ import fs, { existsSync } from 'node:fs';
5
6
  import clone from 'clone';
6
7
  import glyphCompose from '@mapbox/glyph-pbf-composite';
7
8
 
@@ -139,7 +140,7 @@ const getFontPbf = (allowedFonts, fontPath, name, range, fallbacks) =>
139
140
  }
140
141
  });
141
142
 
142
- export const getFontsPbf = (
143
+ export const getFontsPbf = async (
143
144
  allowedFonts,
144
145
  fontPath,
145
146
  names,
@@ -160,7 +161,25 @@ export const getFontsPbf = (
160
161
  );
161
162
  }
162
163
 
163
- return Promise.all(queue).then((values) => glyphCompose.combine(values));
164
+ const values = await Promise.all(queue);
165
+ return glyphCompose.combine(values);
166
+ };
167
+
168
+ export const listFonts = async (fontPath) => {
169
+ const existingFonts = {};
170
+
171
+ const files = await fsPromises.readdir(fontPath);
172
+ for (const file of files) {
173
+ const stats = await fsPromises.stat(path.join(fontPath, file));
174
+ if (
175
+ stats.isDirectory() &&
176
+ existsSync(path.join(fontPath, file, '0-255.pbf'))
177
+ ) {
178
+ existingFonts[path.basename(file)] = true;
179
+ }
180
+ }
181
+
182
+ return existingFonts;
164
183
  };
165
184
 
166
185
  export const isValidHttpUrl = (string) => {
package/test/setup.js CHANGED
@@ -24,6 +24,5 @@ after(function () {
24
24
  console.log('global teardown');
25
25
  global.server.close(function () {
26
26
  console.log('Done');
27
- process.exit();
28
27
  });
29
28
  });
@@ -1,243 +0,0 @@
1
- // @class TileLayer
2
-
3
- L.TileLayer.mergeOptions({
4
- // @option keepBuffer
5
- // The amount of tiles outside the visible map area to be kept in the stitched
6
- // `TileLayer`.
7
-
8
- // @option dumpToCanvas: Boolean = true
9
- // Whether to dump loaded tiles to a `<canvas>` to prevent some rendering
10
- // artifacts. (Disabled by default in IE)
11
- dumpToCanvas: L.Browser.canvas && !L.Browser.ie,
12
- });
13
-
14
- L.TileLayer.include({
15
- _onUpdateLevel: function(z, zoom) {
16
- if (this.options.dumpToCanvas) {
17
- this._levels[z].canvas.style.zIndex =
18
- this.options.maxZoom - Math.abs(zoom - z);
19
- }
20
- },
21
-
22
- _onRemoveLevel: function(z) {
23
- if (this.options.dumpToCanvas) {
24
- L.DomUtil.remove(this._levels[z].canvas);
25
- }
26
- },
27
-
28
- _onCreateLevel: function(level) {
29
- if (this.options.dumpToCanvas) {
30
- level.canvas = L.DomUtil.create(
31
- "canvas",
32
- "leaflet-tile-container leaflet-zoom-animated",
33
- this._container
34
- );
35
- level.ctx = level.canvas.getContext("2d");
36
- this._resetCanvasSize(level);
37
- }
38
- },
39
-
40
- _removeTile: function(key) {
41
- if (this.options.dumpToCanvas) {
42
- var tile = this._tiles[key];
43
- var level = this._levels[tile.coords.z];
44
- var tileSize = this.getTileSize();
45
-
46
- if (level) {
47
- // Where in the canvas should this tile go?
48
- var offset = L.point(tile.coords.x, tile.coords.y)
49
- .subtract(level.canvasRange.min)
50
- .scaleBy(this.getTileSize());
51
-
52
- level.ctx.clearRect(offset.x, offset.y, tileSize.x, tileSize.y);
53
- }
54
- }
55
-
56
- L.GridLayer.prototype._removeTile.call(this, key);
57
- },
58
-
59
- _resetCanvasSize: function(level) {
60
- var buff = this.options.keepBuffer,
61
- pixelBounds = this._getTiledPixelBounds(this._map.getCenter()),
62
- tileRange = this._pxBoundsToTileRange(pixelBounds),
63
- tileSize = this.getTileSize();
64
-
65
- tileRange.min = tileRange.min.subtract([buff, buff]); // This adds the no-prune buffer
66
- tileRange.max = tileRange.max.add([buff + 1, buff + 1]);
67
-
68
- var pixelRange = L.bounds(
69
- tileRange.min.scaleBy(tileSize),
70
- tileRange.max.add([1, 1]).scaleBy(tileSize) // This prevents an off-by-one when checking if tiles are inside
71
- ),
72
- mustRepositionCanvas = false,
73
- neededSize = pixelRange.max.subtract(pixelRange.min);
74
-
75
- // Resize the canvas, if needed, and only to make it bigger.
76
- if (
77
- neededSize.x > level.canvas.width ||
78
- neededSize.y > level.canvas.height
79
- ) {
80
- // Resizing canvases erases the currently drawn content, I'm afraid.
81
- // To keep it, dump the pixels to another canvas, then display it on
82
- // top. This could be done with getImageData/putImageData, but that
83
- // would break for tainted canvases (in non-CORS tilesets)
84
- var oldSize = { x: level.canvas.width, y: level.canvas.height };
85
- // console.info('Resizing canvas from ', oldSize, 'to ', neededSize);
86
-
87
- var tmpCanvas = L.DomUtil.create("canvas");
88
- tmpCanvas.style.width = (tmpCanvas.width = oldSize.x) + "px";
89
- tmpCanvas.style.height = (tmpCanvas.height = oldSize.y) + "px";
90
- tmpCanvas.getContext("2d").drawImage(level.canvas, 0, 0);
91
- // var data = level.ctx.getImageData(0, 0, oldSize.x, oldSize.y);
92
-
93
- level.canvas.style.width = (level.canvas.width = neededSize.x) + "px";
94
- level.canvas.style.height = (level.canvas.height = neededSize.y) + "px";
95
- level.ctx.drawImage(tmpCanvas, 0, 0);
96
- // level.ctx.putImageData(data, 0, 0, 0, 0, oldSize.x, oldSize.y);
97
- }
98
-
99
- // Translate the canvas contents if it's moved around
100
- if (level.canvasRange) {
101
- var offset = level.canvasRange.min
102
- .subtract(tileRange.min)
103
- .scaleBy(this.getTileSize());
104
-
105
- // console.info('Offsetting by ', offset);
106
-
107
- if (!L.Browser.safari) {
108
- // By default, canvases copy things "on top of" existing pixels, but we want
109
- // this to *replace* the existing pixels when doing a drawImage() call.
110
- // This will also clear the sides, so no clearRect() calls are needed to make room
111
- // for the new tiles.
112
- level.ctx.globalCompositeOperation = "copy";
113
- level.ctx.drawImage(level.canvas, offset.x, offset.y);
114
- level.ctx.globalCompositeOperation = "source-over";
115
- } else {
116
- // Safari clears the canvas when copying from itself :-(
117
- if (!this._tmpCanvas) {
118
- var t = (this._tmpCanvas = L.DomUtil.create("canvas"));
119
- t.width = level.canvas.width;
120
- t.height = level.canvas.height;
121
- this._tmpContext = t.getContext("2d");
122
- }
123
- this._tmpContext.clearRect(
124
- 0,
125
- 0,
126
- level.canvas.width,
127
- level.canvas.height
128
- );
129
- this._tmpContext.drawImage(level.canvas, 0, 0);
130
- level.ctx.clearRect(0, 0, level.canvas.width, level.canvas.height);
131
- level.ctx.drawImage(this._tmpCanvas, offset.x, offset.y);
132
- }
133
-
134
- mustRepositionCanvas = true; // Wait until new props are set
135
- }
136
-
137
- level.canvasRange = tileRange;
138
- level.canvasPxRange = pixelRange;
139
- level.canvasOrigin = pixelRange.min;
140
-
141
- // console.log('Canvas tile range: ', level, tileRange.min, tileRange.max );
142
- // console.log('Canvas pixel range: ', pixelRange.min, pixelRange.max );
143
- // console.log('Level origin: ', level.origin );
144
-
145
- if (mustRepositionCanvas) {
146
- this._setCanvasZoomTransform(
147
- level,
148
- this._map.getCenter(),
149
- this._map.getZoom()
150
- );
151
- }
152
- },
153
-
154
- /// set transform/position of canvas, in addition to the transform/position of the individual tile container
155
- _setZoomTransform: function(level, center, zoom) {
156
- L.GridLayer.prototype._setZoomTransform.call(this, level, center, zoom);
157
- if (this.options.dumpToCanvas) {
158
- this._setCanvasZoomTransform(level, center, zoom);
159
- }
160
- },
161
-
162
- // This will get called twice:
163
- // * From _setZoomTransform
164
- // * When the canvas has shifted due to a new tile being loaded
165
- _setCanvasZoomTransform: function(level, center, zoom) {
166
- // console.log('_setCanvasZoomTransform', level, center, zoom);
167
- if (!level.canvasOrigin) {
168
- return;
169
- }
170
- var scale = this._map.getZoomScale(zoom, level.zoom),
171
- translate = level.canvasOrigin
172
- .multiplyBy(scale)
173
- .subtract(this._map._getNewPixelOrigin(center, zoom))
174
- .round();
175
-
176
- if (L.Browser.any3d) {
177
- L.DomUtil.setTransform(level.canvas, translate, scale);
178
- } else {
179
- L.DomUtil.setPosition(level.canvas, translate);
180
- }
181
- },
182
-
183
- _onOpaqueTile: function(tile) {
184
- if (!this.options.dumpToCanvas) {
185
- return;
186
- }
187
-
188
- // Guard against an NS_ERROR_NOT_AVAILABLE (or similar) exception
189
- // when a non-image-tile has been loaded (e.g. a WMS error).
190
- // Checking for tile.el.complete is not enough, as it has been
191
- // already marked as loaded and ready somehow.
192
- try {
193
- this.dumpPixels(tile.coords, tile.el);
194
- } catch (ex) {
195
- return this.fire("tileerror", {
196
- error: "Could not copy tile pixels: " + ex,
197
- tile: tile,
198
- coods: tile.coords,
199
- });
200
- }
201
-
202
- // If dumping the pixels was successful, then hide the tile.
203
- // Do not remove the tile itself, as it is needed to check if the whole
204
- // level (and its canvas) should be removed (via level.el.children.length)
205
- tile.el.style.display = "none";
206
- },
207
-
208
- // @section Extension methods
209
- // @uninheritable
210
-
211
- // @method dumpPixels(coords: Object, imageSource: CanvasImageSource): this
212
- // Dumps pixels from the given `CanvasImageSource` into the layer, into
213
- // the space for the tile represented by the `coords` tile coordinates (an object
214
- // like `{x: Number, y: Number, z: Number}`; the image source must have the
215
- // same size as the `tileSize` option for the layer. Has no effect if `dumpToCanvas`
216
- // is `false`.
217
- dumpPixels: function(coords, imageSource) {
218
- var level = this._levels[coords.z],
219
- tileSize = this.getTileSize();
220
-
221
- if (!level.canvasRange || !this.options.dumpToCanvas) {
222
- return;
223
- }
224
-
225
- // Check if the tile is inside the currently visible map bounds
226
- // There is a possible race condition when tiles are loaded after they
227
- // have been panned outside of the map.
228
- if (!level.canvasRange.contains(coords)) {
229
- this._resetCanvasSize(level);
230
- }
231
-
232
- // Where in the canvas should this tile go?
233
- var offset = L.point(coords.x, coords.y)
234
- .subtract(level.canvasRange.min)
235
- .scaleBy(this.getTileSize());
236
-
237
- level.ctx.drawImage(imageSource, offset.x, offset.y, tileSize.x, tileSize.y);
238
-
239
- // TODO: Clear the pixels of other levels' canvases where they overlap
240
- // this newly dumped tile.
241
- return this;
242
- },
243
- });