tileserver-gl-light 4.0.0 → 4.1.1

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.
@@ -1,37 +1,33 @@
1
1
  'use strict';
2
2
 
3
- const advancedPool = require('advanced-pool');
4
- const fs = require('fs');
5
- const path = require('path');
6
- const url = require('url');
7
- const util = require('util');
8
- const zlib = require('zlib');
9
-
10
- // sharp has to be required before node-canvas
11
- // see https://github.com/lovell/sharp/issues/371
12
- const sharp = require('sharp');
13
-
14
- const { createCanvas } = require('canvas');
15
-
16
- const clone = require('clone');
17
- const Color = require('color');
18
- const express = require('express');
19
- const mercator = new (require('@mapbox/sphericalmercator'))();
20
- const mbgl = require('@maplibre/maplibre-gl-native');
21
- const MBTiles = require('@mapbox/mbtiles');
22
- const proj4 = require('proj4');
23
- const request = require('request');
24
-
25
- const utils = require('./utils');
3
+ import advancedPool from 'advanced-pool';
4
+ import fs from 'node:fs';
5
+ import path from 'path';
6
+ import url from 'url';
7
+ import util from 'util';
8
+ import zlib from 'zlib';
9
+ import sharp from 'sharp'; // sharp has to be required before node-canvas. see https://github.com/lovell/sharp/issues/371
10
+ import pkg from 'canvas';
11
+ import clone from 'clone';
12
+ import Color from 'color';
13
+ import express from 'express';
14
+ import SphericalMercator from '@mapbox/sphericalmercator';
15
+ import mlgl from '@maplibre/maplibre-gl-native';
16
+ import MBTiles from '@mapbox/mbtiles';
17
+ import proj4 from 'proj4';
18
+ import request from 'request';
19
+ import {getFontsPbf, getTileUrls, fixTileJSONCenter} from './utils.js';
26
20
 
27
21
  const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+\.?\\d+)';
28
22
  const httpTester = /^(http(s)?:)?\/\//;
29
23
 
30
- const getScale = scale => (scale || '@1x').slice(1, 2) | 0;
24
+ const {createCanvas} = pkg;
25
+ const mercator = new SphericalMercator();
26
+ const getScale = (scale) => (scale || '@1x').slice(1, 2) | 0;
31
27
 
32
- mbgl.on('message', e => {
28
+ mlgl.on('message', (e) => {
33
29
  if (e.severity === 'WARNING' || e.severity === 'ERROR') {
34
- console.log('mbgl:', e);
30
+ console.log('mlgl:', e);
35
31
  }
36
32
  });
37
33
 
@@ -54,14 +50,14 @@ const cachedEmptyResponses = {
54
50
  };
55
51
 
56
52
  /**
57
- * Create an appropriate mbgl response for http errors.
53
+ * Create an appropriate mlgl response for http errors.
58
54
  * @param {string} format The format (a sharp format or 'pbf').
59
55
  * @param {string} color The background color (or empty string for transparent).
60
- * @param {Function} callback The mbgl callback.
56
+ * @param {Function} callback The mlgl callback.
61
57
  */
62
58
  function createEmptyResponse(format, color, callback) {
63
59
  if (!format || format === 'pbf') {
64
- callback(null, { data: cachedEmptyResponses[''] });
60
+ callback(null, {data: cachedEmptyResponses['']});
65
61
  return;
66
62
  }
67
63
 
@@ -75,7 +71,7 @@ function createEmptyResponse(format, color, callback) {
75
71
  const cacheKey = `${format},${color}`;
76
72
  const data = cachedEmptyResponses[cacheKey];
77
73
  if (data) {
78
- callback(null, { data: data });
74
+ callback(null, {data: data});
79
75
  return;
80
76
  }
81
77
 
@@ -93,7 +89,7 @@ function createEmptyResponse(format, color, callback) {
93
89
  if (!err) {
94
90
  cachedEmptyResponses[cacheKey] = buffer;
95
91
  }
96
- callback(null, { data: buffer });
92
+ callback(null, {data: buffer});
97
93
  });
98
94
  }
99
95
 
@@ -119,7 +115,7 @@ const extractPathFromQuery = (query, transformer) => {
119
115
  };
120
116
 
121
117
  const renderOverlay = (z, x, y, bearing, pitch, w, h, scale,
122
- path, query) => {
118
+ path, query) => {
123
119
  if (!path || path.length < 2) {
124
120
  return null;
125
121
  }
@@ -179,14 +175,14 @@ const calcZForBBox = (bbox, w, h, query) => {
179
175
  const padding = query.padding !== undefined ?
180
176
  parseFloat(query.padding) : 0.1;
181
177
 
182
- const minCorner = mercator.px([bbox[0], bbox[3]], z),
183
- maxCorner = mercator.px([bbox[2], bbox[1]], z);
178
+ const minCorner = mercator.px([bbox[0], bbox[3]], z);
179
+ const maxCorner = mercator.px([bbox[2], bbox[1]], z);
184
180
  const w_ = w / (1 + 2 * padding);
185
181
  const h_ = h / (1 + 2 * padding);
186
182
 
187
183
  z -= Math.max(
188
- Math.log((maxCorner[0] - minCorner[0]) / w_),
189
- Math.log((maxCorner[1] - minCorner[1]) / h_)
184
+ Math.log((maxCorner[0] - minCorner[0]) / w_),
185
+ Math.log((maxCorner[1] - minCorner[1]) / h_)
190
186
  ) / Math.LN2;
191
187
 
192
188
  z = Math.max(Math.log(Math.max(w, h) / 256) / Math.LN2, Math.min(25, z));
@@ -197,7 +193,7 @@ const calcZForBBox = (bbox, w, h, query) => {
197
193
  const existingFonts = {};
198
194
  let maxScaleFactor = 2;
199
195
 
200
- module.exports = {
196
+ export const serve_rendered = {
201
197
  init: (options, repo) => {
202
198
  const fontListingPromise = new Promise((resolve, reject) => {
203
199
  fs.readdir(options.paths.fonts, (err, files) => {
@@ -253,9 +249,9 @@ module.exports = {
253
249
  pool = item.map.renderers_static[scale];
254
250
  }
255
251
  pool.acquire((err, renderer) => {
256
- const mbglZ = Math.max(0, z - 1);
252
+ const mlglZ = Math.max(0, z - 1);
257
253
  const params = {
258
- zoom: mbglZ,
254
+ zoom: mlglZ,
259
255
  center: [lon, lat],
260
256
  bearing: bearing,
261
257
  pitch: pitch,
@@ -282,9 +278,9 @@ module.exports = {
282
278
 
283
279
  // Fix semi-transparent outlines on raw, premultiplied input
284
280
  // https://github.com/maptiler/tileserver-gl/issues/350#issuecomment-477857040
285
- for (var i = 0; i < data.length; i += 4) {
286
- var alpha = data[i + 3];
287
- var norm = alpha / 255;
281
+ for (let i = 0; i < data.length; i += 4) {
282
+ const alpha = data[i + 3];
283
+ const norm = alpha / 255;
288
284
  if (alpha === 0) {
289
285
  data[i] = 0;
290
286
  data[i + 1] = 0;
@@ -305,9 +301,11 @@ module.exports = {
305
301
  });
306
302
 
307
303
  if (z > 2 && tileMargin > 0) {
304
+ const [_, y] = mercator.px(params.center, z);
305
+ let yoffset = Math.max(Math.min(0, y - 128 - tileMargin), y + 128 + tileMargin - Math.pow(2, z + 8));
308
306
  image.extract({
309
307
  left: tileMargin * scale,
310
- top: tileMargin * scale,
308
+ top: (tileMargin + yoffset) * scale,
311
309
  width: width * scale,
312
310
  height: height * scale
313
311
  });
@@ -319,7 +317,7 @@ module.exports = {
319
317
  }
320
318
 
321
319
  if (opt_overlay) {
322
- image.composite([{ input: opt_overlay }]);
320
+ image.composite([{input: opt_overlay}]);
323
321
  }
324
322
  if (item.watermark) {
325
323
  const canvas = createCanvas(scale * width, scale * height);
@@ -332,17 +330,17 @@ module.exports = {
332
330
  ctx.fillStyle = 'rgba(0,0,0,.4)';
333
331
  ctx.fillText(item.watermark, 5, height - 5);
334
332
 
335
- image.composite([{ input: canvas.toBuffer() }]);
333
+ image.composite([{input: canvas.toBuffer()}]);
336
334
  }
337
335
 
338
336
  const formatQuality = (options.formatQuality || {})[format];
339
337
 
340
338
  if (format === 'png') {
341
- image.png({ adaptiveFiltering: false });
339
+ image.png({adaptiveFiltering: false});
342
340
  } else if (format === 'jpeg') {
343
- image.jpeg({ quality: formatQuality || 80 });
341
+ image.jpeg({quality: formatQuality || 80});
344
342
  } else if (format === 'webp') {
345
- image.webp({ quality: formatQuality || 90 });
343
+ image.webp({quality: formatQuality || 90});
346
344
  }
347
345
  image.toBuffer((err, buffer, info) => {
348
346
  if (!buffer) {
@@ -365,18 +363,18 @@ module.exports = {
365
363
  return res.sendStatus(404);
366
364
  }
367
365
 
368
- const modifiedSince = req.get('if-modified-since'), cc = req.get('cache-control');
366
+ const modifiedSince = req.get('if-modified-since'); const cc = req.get('cache-control');
369
367
  if (modifiedSince && (!cc || cc.indexOf('no-cache') === -1)) {
370
368
  if (new Date(item.lastModified) <= new Date(modifiedSince)) {
371
369
  return res.sendStatus(304);
372
370
  }
373
371
  }
374
372
 
375
- const z = req.params.z | 0,
376
- x = req.params.x | 0,
377
- y = req.params.y | 0,
378
- scale = getScale(req.params.scale),
379
- format = req.params.format;
373
+ const z = req.params.z | 0;
374
+ const x = req.params.x | 0;
375
+ const y = req.params.y | 0;
376
+ const scale = getScale(req.params.scale);
377
+ const format = req.params.format;
380
378
  if (z < 0 || x < 0 || y < 0 ||
381
379
  z > 22 || x >= Math.pow(2, z) || y >= Math.pow(2, z)) {
382
380
  return res.status(404).send('Out of bounds');
@@ -395,8 +393,8 @@ module.exports = {
395
393
 
396
394
  const centerPattern =
397
395
  util.format(':x(%s),:y(%s),:z(%s)(@:bearing(%s)(,:pitch(%s))?)?',
398
- FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN,
399
- FLOAT_PATTERN, FLOAT_PATTERN);
396
+ FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN,
397
+ FLOAT_PATTERN, FLOAT_PATTERN);
400
398
 
401
399
  app.get(util.format(staticPattern, centerPattern), (req, res, next) => {
402
400
  const item = repo[req.params.id];
@@ -404,15 +402,15 @@ module.exports = {
404
402
  return res.sendStatus(404);
405
403
  }
406
404
  const raw = req.params.raw;
407
- let z = +req.params.z,
408
- x = +req.params.x,
409
- y = +req.params.y,
410
- bearing = +(req.params.bearing || '0'),
411
- pitch = +(req.params.pitch || '0'),
412
- w = req.params.width | 0,
413
- h = req.params.height | 0,
414
- scale = getScale(req.params.scale),
415
- format = req.params.format;
405
+ const z = +req.params.z;
406
+ let x = +req.params.x;
407
+ let y = +req.params.y;
408
+ const bearing = +(req.params.bearing || '0');
409
+ const pitch = +(req.params.pitch || '0');
410
+ const w = req.params.width | 0;
411
+ const h = req.params.height | 0;
412
+ const scale = getScale(req.params.scale);
413
+ const format = req.params.format;
416
414
 
417
415
  if (z < 0) {
418
416
  return res.status(404).send('Invalid zoom');
@@ -439,8 +437,7 @@ module.exports = {
439
437
  return res.sendStatus(404);
440
438
  }
441
439
  const raw = req.params.raw;
442
- const bbox = [+req.params.minx, +req.params.miny,
443
- +req.params.maxx, +req.params.maxy];
440
+ const bbox = [+req.params.minx, +req.params.miny, +req.params.maxx, +req.params.maxy];
444
441
  let center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
445
442
 
446
443
  const transformer = raw ?
@@ -456,30 +453,31 @@ module.exports = {
456
453
  center = transformer(center);
457
454
  }
458
455
 
459
- const w = req.params.width | 0,
460
- h = req.params.height | 0,
461
- scale = getScale(req.params.scale),
462
- format = req.params.format;
456
+ const w = req.params.width | 0;
457
+ const h = req.params.height | 0;
458
+ const scale = getScale(req.params.scale);
459
+ const format = req.params.format;
463
460
 
464
- const z = calcZForBBox(bbox, w, h, req.query),
465
- x = center[0],
466
- y = center[1],
467
- bearing = 0,
468
- pitch = 0;
461
+ const z = calcZForBBox(bbox, w, h, req.query);
462
+ const x = center[0];
463
+ const y = center[1];
464
+ const bearing = 0;
465
+ const pitch = 0;
469
466
 
470
467
  const path = extractPathFromQuery(req.query, transformer);
471
468
  const overlay = renderOverlay(z, x, y, bearing, pitch, w, h, scale, path, req.query);
469
+
472
470
  return respondImage(item, z, x, y, bearing, pitch, w, h, scale, format, res, next, overlay, 'static');
473
471
  };
474
472
 
475
473
  const boundsPattern =
476
474
  util.format(':minx(%s),:miny(%s),:maxx(%s),:maxy(%s)',
477
- FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN);
475
+ FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN, FLOAT_PATTERN);
478
476
 
479
477
  app.get(util.format(staticPattern, boundsPattern), serveBounds);
480
478
 
481
479
  app.get('/:id/static/', (req, res, next) => {
482
- for (let key in req.query) {
480
+ for (const key in req.query) {
483
481
  req.query[key.toLowerCase()] = req.query[key];
484
482
  }
485
483
  req.params.raw = true;
@@ -508,12 +506,12 @@ module.exports = {
508
506
  return res.sendStatus(404);
509
507
  }
510
508
  const raw = req.params.raw;
511
- const w = req.params.width | 0,
512
- h = req.params.height | 0,
513
- bearing = 0,
514
- pitch = 0,
515
- scale = getScale(req.params.scale),
516
- format = req.params.format;
509
+ const w = req.params.width | 0;
510
+ const h = req.params.height | 0;
511
+ const bearing = 0;
512
+ const pitch = 0;
513
+ const scale = getScale(req.params.scale);
514
+ const format = req.params.format;
517
515
 
518
516
  const transformer = raw ?
519
517
  mercator.inverse.bind(mercator) : item.dataProjWGStoInternalWGS;
@@ -533,12 +531,12 @@ module.exports = {
533
531
 
534
532
  const bbox_ = mercator.convert(bbox, '900913');
535
533
  const center = mercator.inverse(
536
- [(bbox_[0] + bbox_[2]) / 2, (bbox_[1] + bbox_[3]) / 2]
534
+ [(bbox_[0] + bbox_[2]) / 2, (bbox_[1] + bbox_[3]) / 2]
537
535
  );
538
536
 
539
- const z = calcZForBBox(bbox, w, h, req.query),
540
- x = center[0],
541
- y = center[1];
537
+ const z = calcZForBBox(bbox, w, h, req.query);
538
+ const x = center[0];
539
+ const y = center[1];
542
540
 
543
541
  const overlay = renderOverlay(z, x, y, bearing, pitch, w, h, scale, path, req.query);
544
542
 
@@ -552,8 +550,8 @@ module.exports = {
552
550
  return res.sendStatus(404);
553
551
  }
554
552
  const info = clone(item.tileJSON);
555
- info.tiles = utils.getTileUrls(req, info.tiles,
556
- `styles/${req.params.id}`, info.format, item.publicUrl);
553
+ info.tiles = getTileUrls(req, info.tiles,
554
+ `styles/${req.params.id}`, info.format, item.publicUrl);
557
555
  return res.send(info);
558
556
  });
559
557
 
@@ -569,38 +567,38 @@ module.exports = {
569
567
  let styleJSON;
570
568
  const createPool = (ratio, mode, min, max) => {
571
569
  const createRenderer = (ratio, createCallback) => {
572
- const renderer = new mbgl.Map({
570
+ const renderer = new mlgl.Map({
573
571
  mode: mode,
574
572
  ratio: ratio,
575
573
  request: (req, callback) => {
576
574
  const protocol = req.url.split(':')[0];
577
- //console.log('Handling request:', req);
575
+ // console.log('Handling request:', req);
578
576
  if (protocol === 'sprites') {
579
577
  const dir = options.paths[protocol];
580
578
  const file = unescape(req.url).substring(protocol.length + 3);
581
579
  fs.readFile(path.join(dir, file), (err, data) => {
582
- callback(err, { data: data });
580
+ callback(err, {data: data});
583
581
  });
584
582
  } else if (protocol === 'fonts') {
585
583
  const parts = req.url.split('/');
586
584
  const fontstack = unescape(parts[2]);
587
585
  const range = parts[3].split('.')[0];
588
- utils.getFontsPbf(
589
- null, options.paths[protocol], fontstack, range, existingFonts
590
- ).then(concated => {
591
- callback(null, { data: concated });
592
- }, err => {
593
- callback(err, { data: null });
586
+ getFontsPbf(
587
+ null, options.paths[protocol], fontstack, range, existingFonts
588
+ ).then((concated) => {
589
+ callback(null, {data: concated});
590
+ }, (err) => {
591
+ callback(err, {data: null});
594
592
  });
595
593
  } else if (protocol === 'mbtiles') {
596
594
  const parts = req.url.split('/');
597
595
  const sourceId = parts[2];
598
596
  const source = map.sources[sourceId];
599
597
  const sourceInfo = styleJSON.sources[sourceId];
600
- const z = parts[3] | 0,
601
- x = parts[4] | 0,
602
- y = parts[5].split('.')[0] | 0,
603
- format = parts[5].split('.')[1];
598
+ const z = parts[3] | 0;
599
+ const x = parts[4] | 0;
600
+ const y = parts[5].split('.')[0] | 0;
601
+ const format = parts[5].split('.')[1];
604
602
  source.getTile(z, x, y, (err, data, headers) => {
605
603
  if (err) {
606
604
  if (options.verbose) console.log('MBTiles error, serving empty', err);
@@ -617,11 +615,11 @@ module.exports = {
617
615
  try {
618
616
  response.data = zlib.unzipSync(data);
619
617
  } catch (err) {
620
- console.log("Skipping incorrect header for tile mbtiles://%s/%s/%s/%s.pbf", id, z, x, y);
618
+ console.log('Skipping incorrect header for tile mbtiles://%s/%s/%s/%s.pbf', id, z, x, y);
621
619
  }
622
620
  if (options.dataDecoratorFunc) {
623
621
  response.data = options.dataDecoratorFunc(
624
- sourceId, 'data', response.data, z, x, y);
622
+ sourceId, 'data', response.data, z, x, y);
625
623
  }
626
624
  } else {
627
625
  response.data = data;
@@ -668,7 +666,7 @@ module.exports = {
668
666
  min: min,
669
667
  max: max,
670
668
  create: createRenderer.bind(null, ratio),
671
- destroy: renderer => {
669
+ destroy: (renderer) => {
672
670
  renderer.release();
673
671
  }
674
672
  });
@@ -686,8 +684,8 @@ module.exports = {
686
684
  if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
687
685
  styleJSON.sprite = 'sprites://' +
688
686
  styleJSON.sprite
689
- .replace('{style}', path.basename(styleFile, '.json'))
690
- .replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleJSONPath)));
687
+ .replace('{style}', path.basename(styleFile, '.json'))
688
+ .replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleJSONPath)));
691
689
  }
692
690
  if (styleJSON.glyphs && !httpTester.test(styleJSON.glyphs)) {
693
691
  styleJSON.glyphs = `fonts://${styleJSON.glyphs}`;
@@ -718,9 +716,9 @@ module.exports = {
718
716
  const attributionOverride = params.tilejson && params.tilejson.attribution;
719
717
  Object.assign(tileJSON, params.tilejson || {});
720
718
  tileJSON.tiles = params.domains || options.domains;
721
- utils.fixTileJSONCenter(tileJSON);
719
+ fixTileJSONCenter(tileJSON);
722
720
 
723
- repo[id] = {
721
+ const repoobj = {
724
722
  tileJSON,
725
723
  publicUrl,
726
724
  map,
@@ -728,6 +726,7 @@ module.exports = {
728
726
  lastModified: new Date().toUTCString(),
729
727
  watermark: params.watermark || options.watermark
730
728
  };
729
+ repo[id] = repoobj;
731
730
 
732
731
  const queue = [];
733
732
  for (const name of Object.keys(styleJSON.sources)) {
@@ -761,18 +760,18 @@ module.exports = {
761
760
  if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
762
761
  throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
763
762
  }
764
- map.sources[name] = new MBTiles(mbtilesFile, err => {
763
+ map.sources[name] = new MBTiles(mbtilesFile + '?mode=ro', err => {
765
764
  map.sources[name].getInfo((err, info) => {
766
765
  if (err) {
767
766
  console.error(err);
768
767
  return;
769
768
  }
770
769
 
771
- if (!repo[id].dataProjWGStoInternalWGS && info.proj4) {
770
+ if (!repoobj.dataProjWGStoInternalWGS && info.proj4) {
772
771
  // how to do this for multiple sources with different proj4 defs?
773
772
  const to3857 = proj4('EPSG:3857');
774
773
  const toDataProj = proj4(info.proj4);
775
- repo[id].dataProjWGStoInternalWGS = xy => to3857.inverse(toDataProj.forward(xy));
774
+ repoobj.dataProjWGStoInternalWGS = (xy) => to3857.inverse(toDataProj.forward(xy));
776
775
  }
777
776
 
778
777
  const type = source.type;
@@ -790,10 +789,12 @@ module.exports = {
790
789
 
791
790
  if (!attributionOverride &&
792
791
  source.attribution && source.attribution.length > 0) {
793
- if (tileJSON.attribution.length > 0) {
794
- tileJSON.attribution += '; ';
792
+ if (!tileJSON.attribution.includes(source.attribution)) {
793
+ if (tileJSON.attribution.length > 0) {
794
+ tileJSON.attribution += ' | ';
795
+ }
796
+ tileJSON.attribution += source.attribution;
795
797
  }
796
- tileJSON.attribution += source.attribution;
797
798
  }
798
799
  resolve();
799
800
  });
@@ -819,15 +820,15 @@ module.exports = {
819
820
  return Promise.all([renderersReadyPromise]);
820
821
  },
821
822
  remove: (repo, id) => {
822
- let item = repo[id];
823
+ const item = repo[id];
823
824
  if (item) {
824
- item.map.renderers.forEach(pool => {
825
+ item.map.renderers.forEach((pool) => {
825
826
  pool.close();
826
827
  });
827
- item.map.renderers_static.forEach(pool => {
828
+ item.map.renderers_static.forEach((pool) => {
828
829
  pool.close();
829
830
  });
830
831
  }
831
832
  delete repo[id];
832
- },
833
+ }
833
834
  };
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- const path = require('path');
4
- const fs = require('fs');
3
+ import path from 'path';
4
+ import fs from 'node:fs';
5
5
 
6
- const clone = require('clone');
7
- const express = require('express');
6
+ import clone from 'clone';
7
+ import express from 'express';
8
8
  import {validate} from '@maplibre/maplibre-gl-style-spec';
9
9
 
10
- const utils = require('./utils');
10
+ import {getPublicUrl} from './utils.js';
11
11
 
12
12
  const httpTester = /^(http(s)?:)?\/\//;
13
13
 
@@ -24,10 +24,10 @@ const fixUrl = (req, url, publicUrl, opt_nokey) => {
24
24
  query = `?${queryParams.join('&')}`;
25
25
  }
26
26
  return url.replace(
27
- 'local://', utils.getPublicUrl(publicUrl, req)) + query;
27
+ 'local://', getPublicUrl(publicUrl, req)) + query;
28
28
  };
29
29
 
30
- module.exports = {
30
+ export const serve_style = {
31
31
  init: (options, repo) => {
32
32
  const app = express().disable('x-powered-by');
33
33
 
@@ -56,8 +56,8 @@ module.exports = {
56
56
  if (!item || !item.spritePath) {
57
57
  return res.sendStatus(404);
58
58
  }
59
- const scale = req.params.scale,
60
- format = req.params.format;
59
+ const scale = req.params.scale;
60
+ const format = req.params.format;
61
61
  const filename = `${item.spritePath + (scale || '')}.${format}`;
62
62
  return fs.readFile(filename, (err, data) => {
63
63
  if (err) {
@@ -87,7 +87,7 @@ module.exports = {
87
87
  return false;
88
88
  }
89
89
 
90
- let validationErrors = validate(styleFileData);
90
+ const validationErrors = validate(styleFileData);
91
91
  if (validationErrors.length > 0) {
92
92
  console.log(`The file "${params.style}" is not valid a valid style file:`);
93
93
  for (const err of validationErrors) {
@@ -95,7 +95,7 @@ module.exports = {
95
95
  }
96
96
  return false;
97
97
  }
98
- let styleJSON = JSON.parse(styleFileData);
98
+ const styleJSON = JSON.parse(styleFileData);
99
99
 
100
100
  for (const name of Object.keys(styleJSON.sources)) {
101
101
  const source = styleJSON.sources[name];
@@ -120,7 +120,7 @@ module.exports = {
120
120
  }
121
121
  }
122
122
 
123
- for (let obj of styleJSON.layers) {
123
+ for (const obj of styleJSON.layers) {
124
124
  if (obj['type'] === 'symbol') {
125
125
  const fonts = (obj['layout'] || {})['text-font'];
126
126
  if (fonts && fonts.length) {
@@ -136,9 +136,9 @@ module.exports = {
136
136
 
137
137
  if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
138
138
  spritePath = path.join(options.paths.sprites,
139
- styleJSON.sprite
140
- .replace('{style}', path.basename(styleFile, '.json'))
141
- .replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleFile)))
139
+ styleJSON.sprite
140
+ .replace('{style}', path.basename(styleFile, '.json'))
141
+ .replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleFile)))
142
142
  );
143
143
  styleJSON.sprite = `local://styles/${id}/sprite`;
144
144
  }