tileserver-gl-light 4.5.1 → 4.5.2
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/.readthedocs.yaml +18 -0
- package/docs/config.rst +16 -1
- package/docs/endpoints.rst +17 -8
- package/package.json +3 -3
- package/src/serve_rendered.js +42 -9
- package/src/serve_style.js +1 -1
- package/test/static.js +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Read the Docs configuration file for Sphinx projects
|
|
2
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
3
|
+
|
|
4
|
+
# Required
|
|
5
|
+
version: 2
|
|
6
|
+
|
|
7
|
+
# Set the version of Python and other tools you might need
|
|
8
|
+
build:
|
|
9
|
+
os: ubuntu-22.04
|
|
10
|
+
tools:
|
|
11
|
+
python: "3.11"
|
|
12
|
+
|
|
13
|
+
# Build documentation in the doc/help/ directory with Sphinx
|
|
14
|
+
sphinx:
|
|
15
|
+
configuration: docs/conf.py
|
|
16
|
+
|
|
17
|
+
formats:
|
|
18
|
+
- pdf
|
package/docs/config.rst
CHANGED
|
@@ -33,6 +33,8 @@ Example:
|
|
|
33
33
|
"serveAllStyles": false,
|
|
34
34
|
"serveStaticMaps": true,
|
|
35
35
|
"allowRemoteMarkerIcons": true,
|
|
36
|
+
"allowInlineMarkerImages": true,
|
|
37
|
+
"staticAttributionText": "© OpenMapTiles © OpenStreetMaps",
|
|
36
38
|
"tileMargin": 0
|
|
37
39
|
},
|
|
38
40
|
"styles": {
|
|
@@ -140,7 +142,13 @@ It is recommended to also use the ``serveAllFonts`` option when using this optio
|
|
|
140
142
|
-----------
|
|
141
143
|
|
|
142
144
|
Optional string to be rendered into the raster tiles (and static maps) as watermark (bottom-left corner).
|
|
143
|
-
|
|
145
|
+
Not used by default.
|
|
146
|
+
|
|
147
|
+
``staticAttributionText``
|
|
148
|
+
-----------
|
|
149
|
+
|
|
150
|
+
Optional string to be rendered in the static images endpoint. Text will be rendered in the bottom-right corner,
|
|
151
|
+
and styled similar to attribution on web-based maps (text only, links not supported).
|
|
144
152
|
Not used by default.
|
|
145
153
|
|
|
146
154
|
``allowRemoteMarkerIcons``
|
|
@@ -150,6 +158,13 @@ Allows the rendering of marker icons fetched via http(s) hyperlinks.
|
|
|
150
158
|
For security reasons only allow this if you can control the origins from where the markers are fetched!
|
|
151
159
|
Default is to disallow fetching of icons from remote sources.
|
|
152
160
|
|
|
161
|
+
``allowInlineMarkerImages``
|
|
162
|
+
--------------
|
|
163
|
+
Allows the rendering of inline marker icons or base64 urls.
|
|
164
|
+
For security reasons only allow this if you can control the origins from where the markers are fetched!
|
|
165
|
+
Not used by default.
|
|
166
|
+
|
|
167
|
+
|
|
153
168
|
``styles``
|
|
154
169
|
==========
|
|
155
170
|
|
package/docs/endpoints.rst
CHANGED
|
@@ -35,14 +35,23 @@ Static images
|
|
|
35
35
|
|
|
36
36
|
* All the static image endpoints additionally support following query parameters:
|
|
37
37
|
|
|
38
|
-
* ``path``
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
* ``path`` - ``((fill|stroke|width)\:[^\|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)``
|
|
39
|
+
|
|
40
|
+
* comma-separated ``lng,lat``, pipe-separated pairs
|
|
41
|
+
|
|
42
|
+
* e.g. ``path=5.9,45.8|5.9,47.8|10.5,47.8|10.5,45.8|5.9,45.8``
|
|
43
|
+
|
|
44
|
+
* `Google Encoded Polyline Format <https://developers.google.com/maps/documentation/utilities/polylinealgorithm>`_
|
|
45
|
+
|
|
46
|
+
* e.g. ``path=enc:_p~iF~ps|U_ulLnnqC_mqNvxq`@``
|
|
47
|
+
* If 'enc:' is used, the rest of the path parameter is considered to be part of the encoded polyline string -- do not specify the coordinate pairs.
|
|
48
|
+
|
|
49
|
+
* With options (fill|stroke|width)
|
|
50
|
+
|
|
51
|
+
* e.g. ``path=stroke:yellow|width:2|fill:green|5.9,45.8|5.9,47.8|10.5,47.8|10.5,45.8|5.9,45.8`` or ``path=stroke:blue|width:1|fill:yellow|enc:_p~iF~ps|U_ulLnnqC_mqNvxq`@``
|
|
52
|
+
|
|
53
|
+
* can be provided multiple times
|
|
54
|
+
|
|
46
55
|
* ``latlng`` - indicates coordinates are in ``lat,lng`` order rather than the usual ``lng,lat``
|
|
47
56
|
* ``fill`` - color to use as the fill (e.g. ``red``, ``rgba(255,255,255,0.5)``, ``#0000ff``)
|
|
48
57
|
* ``stroke`` - color of the path stroke
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tileserver-gl-light",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.2",
|
|
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",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"chokidar": "3.5.3",
|
|
28
28
|
"clone": "2.1.2",
|
|
29
29
|
"color": "4.2.3",
|
|
30
|
-
"commander": "11.
|
|
30
|
+
"commander": "11.1.0",
|
|
31
31
|
"cors": "2.8.5",
|
|
32
32
|
"express": "4.18.2",
|
|
33
33
|
"handlebars": "4.7.8",
|
|
34
34
|
"http-shutdown": "1.2.2",
|
|
35
35
|
"morgan": "1.10.0",
|
|
36
36
|
"pbf": "3.2.1",
|
|
37
|
-
"proj4": "2.9.
|
|
37
|
+
"proj4": "2.9.1",
|
|
38
38
|
"request": "2.88.2",
|
|
39
39
|
"sanitize-filename": "1.6.3",
|
|
40
40
|
"tileserver-gl-styles": "2.0.0"
|
package/src/serve_rendered.js
CHANGED
|
@@ -22,8 +22,8 @@ import { getFontsPbf, getTileUrls, fixTileJSONCenter } from './utils.js';
|
|
|
22
22
|
|
|
23
23
|
const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)';
|
|
24
24
|
const PATH_PATTERN =
|
|
25
|
-
/^((fill|stroke|width)\:[^\|]+\|)*(
|
|
26
|
-
const httpTester =
|
|
25
|
+
/^((fill|stroke|width)\:[^\|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)/;
|
|
26
|
+
const httpTester = /^\/\//;
|
|
27
27
|
|
|
28
28
|
const mercator = new SphericalMercator();
|
|
29
29
|
const getScale = (scale) => (scale || '@1x').slice(1, 2) | 0;
|
|
@@ -158,10 +158,7 @@ const extractPathsFromQuery = (query, transformer) => {
|
|
|
158
158
|
// Iterate through paths, parse and validate them
|
|
159
159
|
for (const providedPath of providedPaths) {
|
|
160
160
|
// Logic for pushing coords to path when path includes google polyline
|
|
161
|
-
if (
|
|
162
|
-
providedPath.includes('enc:') &&
|
|
163
|
-
PATH_PATTERN.test(decodeURIComponent(providedPath))
|
|
164
|
-
) {
|
|
161
|
+
if (providedPath.includes('enc:') && PATH_PATTERN.test(providedPath)) {
|
|
165
162
|
// +4 because 'enc:' is 4 characters, everything after 'enc:' is considered to be part of the polyline
|
|
166
163
|
const encIndex = providedPath.indexOf('enc:') + 4;
|
|
167
164
|
const coords = polyline
|
|
@@ -279,7 +276,10 @@ const extractMarkersFromQuery = (query, options, transformer) => {
|
|
|
279
276
|
let iconURI = markerParts[1];
|
|
280
277
|
// Check if icon is served via http otherwise marker icons are expected to
|
|
281
278
|
// be provided as filepaths relative to configured icon path
|
|
282
|
-
|
|
279
|
+
const isRemoteURL =
|
|
280
|
+
iconURI.startsWith('http://') || iconURI.startsWith('https://');
|
|
281
|
+
const isDataURL = iconURI.startsWith('data:');
|
|
282
|
+
if (!(isRemoteURL || isDataURL)) {
|
|
283
283
|
// Sanitize URI with sanitize-filename
|
|
284
284
|
// https://www.npmjs.com/package/sanitize-filename#details
|
|
285
285
|
iconURI = sanitize(iconURI);
|
|
@@ -292,7 +292,9 @@ const extractMarkersFromQuery = (query, options, transformer) => {
|
|
|
292
292
|
iconURI = path.resolve(options.paths.icons, iconURI);
|
|
293
293
|
|
|
294
294
|
// When we encounter a remote icon check if the configuration explicitly allows them.
|
|
295
|
-
} else if (options.allowRemoteMarkerIcons !== true) {
|
|
295
|
+
} else if (isRemoteURL && options.allowRemoteMarkerIcons !== true) {
|
|
296
|
+
continue;
|
|
297
|
+
} else if (isDataURL && options.allowInlineMarkerImages !== true) {
|
|
296
298
|
continue;
|
|
297
299
|
}
|
|
298
300
|
|
|
@@ -427,7 +429,7 @@ const drawMarkers = async (ctx, markers, z) => {
|
|
|
427
429
|
* @param {number} z Map zoom level.
|
|
428
430
|
*/
|
|
429
431
|
const drawPath = (ctx, path, query, pathQuery, z) => {
|
|
430
|
-
const splitPaths =
|
|
432
|
+
const splitPaths = pathQuery.split('|');
|
|
431
433
|
|
|
432
434
|
if (!path || path.length < 2) {
|
|
433
435
|
return null;
|
|
@@ -771,6 +773,35 @@ export const serve_rendered = {
|
|
|
771
773
|
composite_array.push({ input: canvas.toBuffer() });
|
|
772
774
|
}
|
|
773
775
|
|
|
776
|
+
if (opt_mode === 'static' && item.staticAttributionText) {
|
|
777
|
+
const canvas = createCanvas(scale * width, scale * height);
|
|
778
|
+
const ctx = canvas.getContext('2d');
|
|
779
|
+
ctx.scale(scale, scale);
|
|
780
|
+
|
|
781
|
+
ctx.font = '10px sans-serif';
|
|
782
|
+
const text = item.staticAttributionText;
|
|
783
|
+
const textMetrics = ctx.measureText(text);
|
|
784
|
+
const textWidth = textMetrics.width;
|
|
785
|
+
const textHeight = 14;
|
|
786
|
+
|
|
787
|
+
const padding = 6;
|
|
788
|
+
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
|
|
789
|
+
ctx.fillRect(
|
|
790
|
+
width - textWidth - padding,
|
|
791
|
+
height - textHeight - padding,
|
|
792
|
+
textWidth + padding,
|
|
793
|
+
textHeight + padding,
|
|
794
|
+
);
|
|
795
|
+
ctx.fillStyle = 'rgba(0,0,0,.8)';
|
|
796
|
+
ctx.fillText(
|
|
797
|
+
item.staticAttributionText,
|
|
798
|
+
width - textWidth - padding / 2,
|
|
799
|
+
height - textHeight + 8,
|
|
800
|
+
);
|
|
801
|
+
|
|
802
|
+
composite_array.push({ input: canvas.toBuffer() });
|
|
803
|
+
}
|
|
804
|
+
|
|
774
805
|
if (composite_array.length > 0) {
|
|
775
806
|
image.composite(composite_array);
|
|
776
807
|
}
|
|
@@ -1378,6 +1409,8 @@ export const serve_rendered = {
|
|
|
1378
1409
|
dataProjWGStoInternalWGS: null,
|
|
1379
1410
|
lastModified: new Date().toUTCString(),
|
|
1380
1411
|
watermark: params.watermark || options.watermark,
|
|
1412
|
+
staticAttributionText:
|
|
1413
|
+
params.staticAttributionText || options.staticAttributionText,
|
|
1381
1414
|
};
|
|
1382
1415
|
repo[id] = repoobj;
|
|
1383
1416
|
|
package/src/serve_style.js
CHANGED
|
@@ -9,7 +9,7 @@ import { validate } from '@maplibre/maplibre-gl-style-spec';
|
|
|
9
9
|
|
|
10
10
|
import { getPublicUrl } from './utils.js';
|
|
11
11
|
|
|
12
|
-
const httpTester =
|
|
12
|
+
const httpTester = /^\/\//;
|
|
13
13
|
|
|
14
14
|
const fixUrl = (req, url, publicUrl, opt_nokey) => {
|
|
15
15
|
if (!url || typeof url !== 'string' || url.indexOf('local://') !== 0) {
|
package/test/static.js
CHANGED