tileserver-gl-light 4.13.1 → 4.13.3

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/.dockerignore CHANGED
@@ -5,3 +5,4 @@
5
5
  !package.json
6
6
  !package-lock.json
7
7
  !docker-entrypoint.sh
8
+ **.gitignore
package/docs/config.rst CHANGED
@@ -17,7 +17,8 @@ Example:
17
17
  "icons": "icons",
18
18
  "styles": "styles",
19
19
  "mbtiles": "data",
20
- "pmtiles": "data"
20
+ "pmtiles": "data",
21
+ "files": "files"
21
22
  },
22
23
  "domains": [
23
24
  "localhost:8080",
@@ -77,7 +77,7 @@ Static images
77
77
  * scales with ``scale`` parameter since image placement is relative to it's size
78
78
  * e.g. ``2,-4`` - Image will be moved 2 pixel to the right and 4 pixel in the upwards direction from the provided location
79
79
 
80
- * e.g. ``5.9,45.8|marker-start.svg|scale:0.5|offset:2,-4``
80
+ * e.g. ``5.9,45.8|marker-icon.png|scale:0.5|offset:2,-4``
81
81
  * can be provided multiple times
82
82
 
83
83
  * ``padding`` - "percentage" padding for fitted endpoints (area-based and path autofit)
@@ -100,6 +100,18 @@ Source data
100
100
 
101
101
  * TileJSON at ``/data/{id}.json``
102
102
 
103
+ Static files
104
+ ===========
105
+ * Static files are served at ``/files/{filename}``
106
+
107
+ * The source folder can be configured (``options.paths.files``), default is ``public/files``
108
+
109
+ * This feature can be used to serve ``geojson`` files for styles and rendered tiles.
110
+
111
+ * Keep in mind, that each rendered tile loads the whole geojson file, if performance matters a conversion to a tiled format (e.g. with https://github.com/felt/tippecanoe)may be a better approch.
112
+
113
+ * Use ``file://{filename}`` to have matching paths for both endoints
114
+
103
115
  TileJSON arrays
104
116
  ===============
105
117
  Array of all TileJSONs is at ``[/{tileSize}]/index.json`` (``[/{tileSize}]/rendered.json``; ``/data.json``)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tileserver-gl-light",
3
- "version": "4.13.1",
3
+ "version": "4.13.3",
4
4
  "description": "Map tile server for JSON GL styles - serving vector tiles",
5
5
  "main": "src/main.js",
6
6
  "bin": "src/main.js",
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title></title>
5
+ </head>
6
+ <body>
7
+ </body>
8
+ </html>
@@ -41,7 +41,7 @@ import {
41
41
  } from './pmtiles_adapter.js';
42
42
  import { renderOverlay, renderWatermark, renderAttribution } from './render.js';
43
43
  import fsp from 'node:fs/promises';
44
- import { gunzipP } from './promises.js';
44
+ import { existsP, gunzipP } from './promises.js';
45
45
  import { openMbTilesWrapper } from './mbtiles_wrapper.js';
46
46
 
47
47
  const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)';
@@ -893,13 +893,15 @@ export const serve_rendered = {
893
893
  // console.log('Handling request:', req);
894
894
  if (protocol === 'sprites') {
895
895
  const dir = options.paths[protocol];
896
- const file = unescape(req.url).substring(protocol.length + 3);
896
+ const file = decodeURIComponent(req.url).substring(
897
+ protocol.length + 3,
898
+ );
897
899
  fs.readFile(path.join(dir, file), (err, data) => {
898
900
  callback(err, { data: data });
899
901
  });
900
902
  } else if (protocol === 'fonts') {
901
903
  const parts = req.url.split('/');
902
- const fontstack = unescape(parts[2]);
904
+ const fontstack = decodeURIComponent(parts[2]);
903
905
  const range = parts[3].split('.')[0];
904
906
 
905
907
  try {
@@ -1039,6 +1041,25 @@ export const serve_rendered = {
1039
1041
  const format = extensionToFormat[extension] || '';
1040
1042
  createEmptyResponse(format, '', callback);
1041
1043
  }
1044
+ } else if (protocol === 'file') {
1045
+ const name = decodeURI(req.url).substring(protocol.length + 3);
1046
+ const file = path.join(options.paths['files'], name);
1047
+ if (await existsP(file)) {
1048
+ const inputFileStats = await fsp.stat(file);
1049
+ if (!inputFileStats.isFile() || inputFileStats.size === 0) {
1050
+ throw Error(
1051
+ `File is not valid: "${req.url}" - resolved to "${file}"`,
1052
+ );
1053
+ }
1054
+
1055
+ fs.readFile(file, (err, data) => {
1056
+ callback(err, { data: data });
1057
+ });
1058
+ } else {
1059
+ throw Error(
1060
+ `File does not exist: "${req.url}" - resolved to "${file}"`,
1061
+ );
1062
+ }
1042
1063
  }
1043
1064
  },
1044
1065
  });
@@ -26,6 +26,9 @@ export const serve_style = {
26
26
  for (const name of Object.keys(styleJSON_.sources)) {
27
27
  const source = styleJSON_.sources[name];
28
28
  source.url = fixUrl(req, source.url, item.publicUrl);
29
+ if (typeof source.data == 'string') {
30
+ source.data = fixUrl(req, source.data, item.publicUrl);
31
+ }
29
32
  }
30
33
  // mapbox-gl-js viewer cannot handle sprite urls with query
31
34
  if (styleJSON_.sprite) {
@@ -89,7 +92,7 @@ export const serve_style = {
89
92
  try {
90
93
  styleFileData = fs.readFileSync(styleFile); // TODO: could be made async if this function was
91
94
  } catch (e) {
92
- console.log('Error reading style file');
95
+ console.log(`Error reading style file "${params.style}"`);
93
96
  return false;
94
97
  }
95
98
 
@@ -128,6 +131,16 @@ export const serve_style = {
128
131
  }
129
132
  source.url = `local://data/${identifier}.json`;
130
133
  }
134
+
135
+ let data = source.data;
136
+ if (data && typeof data == 'string' && data.startsWith('file://')) {
137
+ source.data =
138
+ 'local://files' +
139
+ path.resolve(
140
+ '/',
141
+ data.replace('file://', '').replace(options.paths.files, ''),
142
+ );
143
+ }
131
144
  }
132
145
 
133
146
  for (const obj of styleJSON.layers) {
package/src/server.js CHANGED
@@ -94,24 +94,23 @@ function start(opts) {
94
94
  paths.sprites = path.resolve(paths.root, paths.sprites || '');
95
95
  paths.mbtiles = path.resolve(paths.root, paths.mbtiles || '');
96
96
  paths.pmtiles = path.resolve(paths.root, paths.pmtiles || '');
97
- paths.icons = path.resolve(paths.root, paths.icons || '');
97
+ paths.icons = paths.icons
98
+ ? path.resolve(paths.root, paths.icons)
99
+ : path.resolve(__dirname, '../public/resources/images');
100
+ paths.files = paths.files
101
+ ? path.resolve(paths.root, paths.files)
102
+ : path.resolve(__dirname, '../public/files');
98
103
 
99
104
  const startupPromises = [];
100
105
 
101
- const checkPath = (type) => {
106
+ for (const type of Object.keys(paths)) {
102
107
  if (!fs.existsSync(paths[type])) {
103
108
  console.error(
104
109
  `The specified path for "${type}" does not exist (${paths[type]}).`,
105
110
  );
106
111
  process.exit(1);
107
112
  }
108
- };
109
- checkPath('styles');
110
- checkPath('fonts');
111
- checkPath('sprites');
112
- checkPath('mbtiles');
113
- checkPath('pmtiles');
114
- checkPath('icons');
113
+ }
115
114
 
116
115
  /**
117
116
  * Recursively get all files within a directory.
@@ -161,6 +160,7 @@ function start(opts) {
161
160
  }
162
161
 
163
162
  app.use('/data/', serve_data.init(options, serving.data));
163
+ app.use('/files/', express.static(paths.files));
164
164
  app.use('/styles/', serve_style.init(options, serving.styles));
165
165
  if (!isLight) {
166
166
  startupPromises.push(