Merge branch 'master' into windows
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
This commit is contained in:
commit
e0d1a1c708
13 changed files with 701 additions and 681 deletions
|
@ -28,8 +28,8 @@ docker build -t tileserver-gl-light .
|
|||
[Download from OpenMapTiles.com](https://openmaptiles.com/downloads/planet/) or [create](https://github.com/openmaptiles/openmaptiles) your vector tile, and run following in directory contains your *.mbtiles.
|
||||
|
||||
```
|
||||
docker run --rm -it -v $(pwd):/data -p 8000:80 tileserver-gl-light
|
||||
docker run --rm -it -v $(pwd):/data -p 8080:8080 tileserver-gl-light
|
||||
```
|
||||
|
||||
## Documentation
|
||||
You can read full documentation of this project at https://tileserver.readthedocs.io/.
|
||||
You can read full documentation of this project at https://maptiler-tileserver.readthedocs.io/
|
||||
|
|
|
@ -132,6 +132,19 @@ If you have plenty of memory, try setting these equal to or slightly above your
|
|||
If you need to conserve memory, try lower values for scale factors that are less common.
|
||||
Default is ``[16, 8, 4]``.
|
||||
|
||||
``pbfAlias``
|
||||
------------------------
|
||||
|
||||
Some CDNs did not handle .pbf extension as a static file correctly.
|
||||
The default URLs (with .pbf) are always available, but an alternative can be set.
|
||||
An example extension suffix would be ".pbf.pict".
|
||||
|
||||
``serveAllFonts``
|
||||
------------------------
|
||||
|
||||
If this option is enabled, all the fonts from the ``paths.fonts`` will be served.
|
||||
Otherwise only the fonts referenced by available styles will be served.
|
||||
|
||||
``serveAllStyles``
|
||||
------------------------
|
||||
|
||||
|
@ -139,10 +152,16 @@ If this option is enabled, all the styles from the ``paths.styles`` will be serv
|
|||
The process will also watch for changes in this directory and remove/add more styles dynamically.
|
||||
It is recommended to also use the ``serveAllFonts`` option when using this option.
|
||||
|
||||
``serveStaticMaps``
|
||||
------------------------
|
||||
|
||||
If this option is enabled, all the static map endpoints will be served.
|
||||
Default is ``true``.
|
||||
|
||||
``watermark``
|
||||
-----------
|
||||
|
||||
Optional string to be rendered into the raster tiles (and static maps) as watermark (bottom-left corner).
|
||||
Optional string to be rendered into the raster tiles and static maps as watermark (bottom-left corner).
|
||||
Not used by default.
|
||||
|
||||
``staticAttributionText``
|
||||
|
|
|
@ -52,14 +52,14 @@ Static images
|
|||
|
||||
* can be provided multiple times
|
||||
|
||||
* ``latlng`` - indicates coordinates are in ``lat,lng`` order rather than the usual ``lng,lat``
|
||||
* ``fill`` - color to use as the fill (e.g. ``red``, ``rgba(255,255,255,0.5)``, ``#0000ff``)
|
||||
* ``stroke`` - color of the path stroke
|
||||
* ``width`` - width of the stroke
|
||||
* ``linecap`` - rendering style for the start and end points of the path
|
||||
* ``linejoin`` - rendering style for overlapping segments of the path with differing directions
|
||||
* ``border`` - color of the optional border path stroke
|
||||
* ``borderwidth`` - width of the border stroke (default 10% of width)
|
||||
* ``latlng`` - indicates coordinates are in ``lat,lng`` order rather than the usual ``lng,lat`` for paths and markers
|
||||
* ``fill`` - default color to use as the fill (e.g. ``red``, ``rgba(255,255,255,0.5)``, ``#0000ff``) for all paths
|
||||
* ``stroke`` - default color of the path stroke for all paths
|
||||
* ``width`` - default width of the stroke for all paths
|
||||
* ``linecap`` - rendering style for the start and end points of all paths - see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap
|
||||
* ``linejoin`` - rendering style for joining successive segments of all paths when the direction changes - see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
|
||||
* ``border`` - color of the optional border stroke for all paths ; the border is like a halo around the stroke
|
||||
* ``borderwidth`` - width of the border stroke (default 10% of stroke width) for all paths
|
||||
* ``marker`` - Marker in format ``lng,lat|iconPath|option|option|...``
|
||||
|
||||
* Will be rendered with the bottom center at the provided location
|
||||
|
|
286
package-lock.json
generated
286
package-lock.json
generated
|
@ -16,7 +16,7 @@
|
|||
"@mapbox/vector-tile": "1.3.1",
|
||||
"@maplibre/maplibre-gl-native": "5.2.0",
|
||||
"@maplibre/maplibre-gl-style-spec": "18.0.0",
|
||||
"@sindresorhus/fnv1a": "3.0.0",
|
||||
"@sindresorhus/fnv1a": "3.1.0",
|
||||
"advanced-pool": "0.3.3",
|
||||
"axios": "^1.6.2",
|
||||
"canvas": "2.11.2",
|
||||
|
@ -40,12 +40,12 @@
|
|||
"tileserver-gl": "src/main.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.4.1",
|
||||
"@commitlint/config-conventional": "^18.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@commitlint/cli": "^18.4.3",
|
||||
"@commitlint/config-conventional": "^18.4.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"chai": "4.3.10",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-jsdoc": "^46.9.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
|
@ -207,16 +207,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/cli": {
|
||||
"version": "18.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.1.tgz",
|
||||
"integrity": "sha512-4+jljfd29Udw9RDDyigavLO9LvdbmB8O9xjDzVZ0R3lJuG7nCeyHgnKWIVpFaN590isZMV/cMeQK0gH7hRF40A==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.4.3.tgz",
|
||||
"integrity": "sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/format": "^18.4.0",
|
||||
"@commitlint/lint": "^18.4.0",
|
||||
"@commitlint/load": "^18.4.1",
|
||||
"@commitlint/read": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/format": "^18.4.3",
|
||||
"@commitlint/lint": "^18.4.3",
|
||||
"@commitlint/load": "^18.4.3",
|
||||
"@commitlint/read": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"execa": "^5.0.0",
|
||||
"lodash.isfunction": "^3.0.9",
|
||||
"resolve-from": "5.0.0",
|
||||
|
@ -231,9 +231,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-conventional": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.0.tgz",
|
||||
"integrity": "sha512-vArwCZopsZs0FnGsh9AR7uUTPZ5oVGk8+qnEZWq2KTsMjrE0k80b+oZ32GSQmXQT2iMKVrDC8pKX5uKNkCe9Sw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.4.3.tgz",
|
||||
"integrity": "sha512-729eRRaNta7JZF07qf6SAGSghoDEp9mH7yHU0m7ff0q89W97wDrWCyZ3yoV3mcQJwbhlmVmZPTkPcm7qiAu8WA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"conventional-changelog-conventionalcommits": "^7.0.2"
|
||||
|
@ -243,12 +243,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/config-validator": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.4.0.tgz",
|
||||
"integrity": "sha512-1y6qHMU3o4cYQSK+Y9EnmH6H1GRiwQGjnLIUOIKlekrmfc8MrMk1ByNmb8od4vK3qHJAaL/77/5n+1uyyIF5dA==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.4.3.tgz",
|
||||
"integrity": "sha512-FPZZmTJBARPCyef9ohRC9EANiQEKSWIdatx5OlgeHKu878dWwpyeFauVkhzuBRJFcCA4Uvz/FDtlDKs008IHcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"ajv": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -256,12 +256,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/ensure": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.4.0.tgz",
|
||||
"integrity": "sha512-N5cJo/n61ULSwz3W5Iz/IZJ0I9H/PaHc+OMcF2XcRVbLa6B3YwzEW66XGCRKVULlsBNSrIH6tk5un9ayXAXIdw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.4.3.tgz",
|
||||
"integrity": "sha512-MI4fwD9TWDVn4plF5+7JUyLLbkOdzIRBmVeNlk4dcGlkrVA+/l5GLcpN66q9LkFsFv6G2X31y89ApA3hqnqIFg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.snakecase": "^4.1.1",
|
||||
|
@ -273,21 +273,21 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/execute-rule": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.4.0.tgz",
|
||||
"integrity": "sha512-g013SWki6ZWhURBLOSXTaVQGWHdA0QlPJGiW4a+YpThezmJOemvc4LiKVpn13AjSKQ40QnmBqpBrxujOaSo+3A==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.4.3.tgz",
|
||||
"integrity": "sha512-t7FM4c+BdX9WWZCPrrbV5+0SWLgT3kCq7e7/GhHCreYifg3V8qyvO127HF796vyFql75n4TFF+5v1asOOWkV1Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=v18"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/format": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.4.0.tgz",
|
||||
"integrity": "sha512-MiAe4D5/ahty38CzULdQbpRa3ReKZtx0kyigOWcntq+N5uqez+Ac4/MO7H+3j1kC4G7nfJVfBu6TqcXeyNvhCQ==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.4.3.tgz",
|
||||
"integrity": "sha512-8b+ItXYHxAhRAXFfYki5PpbuMMOmXYuzLxib65z2XTqki59YDQJGpJ/wB1kEE5MQDgSTQWtKUrA8n9zS/1uIDQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"chalk": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -295,12 +295,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/is-ignored": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.4.0.tgz",
|
||||
"integrity": "sha512-vyBKBj3Q4N3Xe4ZQcJXW9ef6gVrDL9Fl2HXnnC3F0Qt/F6E4runhJkEuUh5DB3WCXTJUHIJkByKPqrnz4RNrZw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.4.3.tgz",
|
||||
"integrity": "sha512-ZseOY9UfuAI32h9w342Km4AIaTieeFskm2ZKdrG7r31+c6zGBzuny9KQhwI9puc0J3GkUquEgKJblCl7pMnjwg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"semver": "7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -308,30 +308,30 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/lint": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.4.0.tgz",
|
||||
"integrity": "sha512-Wkkf1DPVeLdHYGqtzMBfWoMbUtCojvlzDR89OKVic1rid41iZbb0FzTcwgMYs/1TNWNxoIq9PVVwY7ovLX1aJQ==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.4.3.tgz",
|
||||
"integrity": "sha512-18u3MRgEXNbnYkMOWoncvq6QB8/90m9TbERKgdPqVvS+zQ/MsuRhdvHYCIXGXZxUb0YI4DV2PC4bPneBV/fYuA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/is-ignored": "^18.4.0",
|
||||
"@commitlint/parse": "^18.4.0",
|
||||
"@commitlint/rules": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0"
|
||||
"@commitlint/is-ignored": "^18.4.3",
|
||||
"@commitlint/parse": "^18.4.3",
|
||||
"@commitlint/rules": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v18"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/load": {
|
||||
"version": "18.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.4.1.tgz",
|
||||
"integrity": "sha512-o/plBiPJQgbSq/4ipDpsq4HCmURjBAEjr1EO/p2falr3VhwV0WGXTvb8NlihgI8xtSyO6lHvtycrE535GMLQbA==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.4.3.tgz",
|
||||
"integrity": "sha512-v6j2WhvRQJrcJaj5D+EyES2WKTxPpxENmNpNG3Ww8MZGik3jWRXtph0QTzia5ZJyPh2ib5aC/6BIDymkUUM58Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/config-validator": "^18.4.0",
|
||||
"@commitlint/execute-rule": "^18.4.0",
|
||||
"@commitlint/resolve-extends": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/config-validator": "^18.4.3",
|
||||
"@commitlint/execute-rule": "^18.4.3",
|
||||
"@commitlint/resolve-extends": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^8.3.6",
|
||||
|
@ -346,22 +346,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/message": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.4.0.tgz",
|
||||
"integrity": "sha512-3kg6NQO6pJ+VdBTWi51KInT8ngkxPJaW+iI7URtUALjKcO9K4XY3gf80ZPmS1hDessrjb7qCr1lau8eWMINAQw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.4.3.tgz",
|
||||
"integrity": "sha512-ddJ7AztWUIoEMAXoewx45lKEYEOeOlBVWjk8hDMUGpprkuvWULpaXczqdjwVtjrKT3JhhN+gMs8pm5G3vB2how==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=v18"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/parse": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.4.0.tgz",
|
||||
"integrity": "sha512-SxTCSUZH8CJNYWOlFg18YUQ2RLz8ubXKbpHUIiSNwCbiQx7UDCydp1JnhoB4sOYOxgV8d3nuDwYluRU5KnEY4A==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.4.3.tgz",
|
||||
"integrity": "sha512-eoH7CXM9L+/Me96KVcfJ27EIIbA5P9sqw3DqjJhRYuhaULIsPHFs5S5GBDCqT0vKZQDx0DgxhMpW6AQbnKrFtA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"conventional-changelog-angular": "^6.0.0",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"conventional-changelog-angular": "^7.0.0",
|
||||
"conventional-commits-parser": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -369,13 +369,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/read": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.4.0.tgz",
|
||||
"integrity": "sha512-IpnABCbDeOw5npZ09SZZGLfd3T7cFtsxUYm6wT3aGmIB2fXKE3fMeuj3jxXjMibiGIyA3Z5voCMuOcKWpkNySA==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.4.3.tgz",
|
||||
"integrity": "sha512-H4HGxaYA6OBCimZAtghL+B+SWu8ep4X7BwgmedmqWZRHxRLcX2q0bWBtUm5FsMbluxbOfrJwOs/Z0ah4roP/GQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/top-level": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/top-level": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"fs-extra": "^11.0.0",
|
||||
"git-raw-commits": "^2.0.11",
|
||||
"minimist": "^1.2.6"
|
||||
|
@ -385,13 +385,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/resolve-extends": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.4.0.tgz",
|
||||
"integrity": "sha512-qhgU6ach+S6sJMD9NjCYiEycOObGhxzWQLQzqlScJCv9zkPs15Bg0ffLXTQ3z7ipXv46XEKYMnSJzjLRw2Tlkg==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.4.3.tgz",
|
||||
"integrity": "sha512-30sk04LZWf8+SDgJrbJCjM90gTg2LxsD9cykCFeFu+JFHvBFq5ugzp2eO/DJGylAdVaqxej3c7eTSE64hR/lnw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/config-validator": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/config-validator": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"import-fresh": "^3.0.0",
|
||||
"lodash.mergewith": "^4.6.2",
|
||||
"resolve-from": "^5.0.0",
|
||||
|
@ -402,15 +402,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/rules": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.4.0.tgz",
|
||||
"integrity": "sha512-T3ChRxQZ6g0iNCpVLc6KeQId0/86TnyQA8PFkng+dWElO2DAA5km/yirgKZV1Xlc+gF7Rf6d+a0ottxdKpOY+w==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.4.3.tgz",
|
||||
"integrity": "sha512-8KIeukDf45BiY+Lul1T0imSNXF0sMrlLG6JpLLKolkmYVQ6PxxoNOriwyZ3UTFFpaVbPy0rcITaV7U9JCAfDTA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@commitlint/ensure": "^18.4.0",
|
||||
"@commitlint/message": "^18.4.0",
|
||||
"@commitlint/to-lines": "^18.4.0",
|
||||
"@commitlint/types": "^18.4.0",
|
||||
"@commitlint/ensure": "^18.4.3",
|
||||
"@commitlint/message": "^18.4.3",
|
||||
"@commitlint/to-lines": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"execa": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -418,18 +418,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/to-lines": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.4.0.tgz",
|
||||
"integrity": "sha512-bZXuCtfBPjNgtEnG3gwJrveIgfKK2UdhIhFvKpMTrQl/gAwoto/3mzmE7qGAHwmuP4eZ2U8X7iwMnqIlWmv2Tw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.4.3.tgz",
|
||||
"integrity": "sha512-fy1TAleik4Zfru1RJ8ZU6cOSvgSVhUellxd3WZV1D5RwHZETt1sZdcA4mQN2y3VcIZsUNKkW0Mq8CM9/L9harQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=v18"
|
||||
}
|
||||
},
|
||||
"node_modules/@commitlint/top-level": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.4.0.tgz",
|
||||
"integrity": "sha512-TfulcA8UHF7MZ6tm4Ci3aqZgMBZa1OoCg4prccWHvwG/hsHujZ7+0FKbeKqDbcSli/YWm4NJwEjl4uh5itIJeA==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.4.3.tgz",
|
||||
"integrity": "sha512-E6fJPBLPFL5R8+XUNSYkj4HekIOuGMyJo3mIx2PkYc3clel+pcWQ7TConqXxNWW4x1ugigiIY2RGot55qUq1hw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"find-up": "^5.0.0"
|
||||
|
@ -439,9 +439,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@commitlint/types": {
|
||||
"version": "18.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.4.0.tgz",
|
||||
"integrity": "sha512-MKeaFxt0I9fhqUb2E+YIzX/gZtmkuodJET/XKiZIMvXUff8Ee4Ih86eLg+yAm2jf1pwGBmU02uNOp0y094w2Uw==",
|
||||
"version": "18.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.4.3.tgz",
|
||||
"integrity": "sha512-cvzx+vtY/I2hVBZHCLrpoh+sA0hfuzHwDc+BAFPimYLjJkpHnghQM+z8W/KyLGkygJh3BtI3xXXq+dKjnSWEmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0"
|
||||
|
@ -556,9 +556,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.53.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz",
|
||||
"integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==",
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz",
|
||||
"integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -969,9 +969,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/fnv1a": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-3.0.0.tgz",
|
||||
"integrity": "sha512-M6pmbdZqAryzjZ4ELAzrdCMoMZk5lH/fshKrapfSeXdf2W+GDqZvPmfXaNTZp43//FVbSwkTPwpEMnehSyskkQ==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz",
|
||||
"integrity": "sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
|
@ -1005,9 +1005,9 @@
|
|||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz",
|
||||
"integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==",
|
||||
"version": "18.18.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.11.tgz",
|
||||
"integrity": "sha512-c1vku6qnTeujJneYH94/4aq73XrVcsJe35UPyAsSok1ijiKrkRzK+AxQPSpNMUnC03roWBBwJx/9I8V7lQoxmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
|
@ -1025,16 +1025,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz",
|
||||
"integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz",
|
||||
"integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/type-utils": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/type-utils": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
|
@ -1060,15 +1060,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz",
|
||||
"integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz",
|
||||
"integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1088,13 +1088,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz",
|
||||
"integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz",
|
||||
"integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0"
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1105,13 +1105,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz",
|
||||
"integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz",
|
||||
"integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
|
@ -1132,9 +1132,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz",
|
||||
"integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz",
|
||||
"integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1145,13 +1145,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz",
|
||||
"integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz",
|
||||
"integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -1172,17 +1172,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz",
|
||||
"integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz",
|
||||
"integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1197,12 +1197,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz",
|
||||
"integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz",
|
||||
"integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -2117,15 +2117,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/conventional-changelog-angular": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz",
|
||||
"integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
|
||||
"integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"compare-func": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/conventional-changelog-conventionalcommits": {
|
||||
|
@ -2809,15 +2809,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.53.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz",
|
||||
"integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==",
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz",
|
||||
"integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
"@eslint/eslintrc": "^2.1.3",
|
||||
"@eslint/js": "8.53.0",
|
||||
"@eslint/js": "8.54.0",
|
||||
"@humanwhocodes/config-array": "^0.11.13",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
|
|
16
package.json
16
package.json
|
@ -6,7 +6,7 @@
|
|||
"bin": "src/main.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "mocha test/**.js --timeout 10000",
|
||||
"test": "mocha test/**.js --timeout 10000 --exit",
|
||||
"lint:yml": "yamllint --schema=CORE_SCHEMA *.{yml,yaml}",
|
||||
"lint:js": "npm run lint:eslint && npm run lint:prettier",
|
||||
"lint:js:fix": "npm run lint:eslint:fix && npm run lint:prettier:fix",
|
||||
|
@ -14,7 +14,7 @@
|
|||
"lint:eslint:fix": "eslint --fix \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs}\" --ignore-path .gitignore",
|
||||
"lint:prettier": "prettier --check \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
||||
"lint:prettier:fix": "prettier --write \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
||||
"docker": "docker build -f Dockerfile . && docker run --rm -i -p 8080:8080 $(docker build -q .)",
|
||||
"docker": "docker build . && docker run --rm -i -p 8080:8080 $(docker build -q .)",
|
||||
"prepare": "node -e \"if (process.env.NODE_ENV !== 'production'){ process.exit(1) } \" || husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -25,7 +25,7 @@
|
|||
"@mapbox/vector-tile": "1.3.1",
|
||||
"@maplibre/maplibre-gl-native": "5.2.0",
|
||||
"@maplibre/maplibre-gl-style-spec": "18.0.0",
|
||||
"@sindresorhus/fnv1a": "3.0.0",
|
||||
"@sindresorhus/fnv1a": "3.1.0",
|
||||
"advanced-pool": "0.3.3",
|
||||
"axios": "^1.6.2",
|
||||
"canvas": "2.11.2",
|
||||
|
@ -46,12 +46,12 @@
|
|||
"tileserver-gl-styles": "2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.4.1",
|
||||
"@commitlint/config-conventional": "^18.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@commitlint/cli": "^18.4.3",
|
||||
"@commitlint/config-conventional": "^18.4.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"chai": "4.3.10",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-jsdoc": "^46.9.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
|
|
|
@ -82,9 +82,6 @@
|
|||
<div class="identifier">type: {{#is_vector}}vector{{/is_vector}}{{^is_vector}}raster{{/is_vector}} data {{#if source_type}} | ext: {{source_type}}{{/if}}</div>
|
||||
<p class="services">
|
||||
services: <a href="{{public_url}}data/{{@key}}.json{{&../key_query}}">TileJSON</a>
|
||||
{{#if wmts_link}}
|
||||
| <a href="{{&wmts_link}}">WMTS</a>
|
||||
{{/if}}
|
||||
{{#if xyz_link}}
|
||||
| <a href="#" onclick="return toggle_xyz('xyz_data_{{@key}}');">XYZ</a>
|
||||
<input id="xyz_data_{{@key}}" type="text" value="{{&xyz_link}}" style="display:none;" />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as http from 'http';
|
||||
var options = {
|
||||
const options = {
|
||||
timeout: 2000,
|
||||
};
|
||||
var url = 'http://localhost:8080/health';
|
||||
var request = http.request(url, options, (res) => {
|
||||
const url = 'http://localhost:8080/health';
|
||||
const request = http.request(url, options, (res) => {
|
||||
console.log(`STATUS: ${res.statusCode}`);
|
||||
if (res.statusCode == 200) {
|
||||
process.exit(0);
|
||||
|
|
303
src/render.js
Normal file
303
src/render.js
Normal file
|
@ -0,0 +1,303 @@
|
|||
'use strict';
|
||||
|
||||
import { createCanvas, Image } from 'canvas';
|
||||
|
||||
import SphericalMercator from '@mapbox/sphericalmercator';
|
||||
|
||||
const mercator = new SphericalMercator();
|
||||
|
||||
/**
|
||||
* Transforms coordinates to pixels.
|
||||
* @param {List[Number]} ll Longitude/Latitude coordinate pair.
|
||||
* @param {number} zoom Map zoom level.
|
||||
*/
|
||||
const precisePx = (ll, zoom) => {
|
||||
const px = mercator.px(ll, 20);
|
||||
const scale = Math.pow(2, zoom - 20);
|
||||
return [px[0] * scale, px[1] * scale];
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a marker in canvas context.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {object} marker Marker object parsed by extractMarkersFromQuery.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawMarker = (ctx, marker, z) => {
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image();
|
||||
const pixelCoords = precisePx(marker.location, z);
|
||||
|
||||
const getMarkerCoordinates = (imageWidth, imageHeight, scale) => {
|
||||
// Images are placed with their top-left corner at the provided location
|
||||
// within the canvas but we expect icons to be centered and above it.
|
||||
|
||||
// Substract half of the images width from the x-coordinate to center
|
||||
// the image in relation to the provided location
|
||||
let xCoordinate = pixelCoords[0] - imageWidth / 2;
|
||||
// Substract the images height from the y-coordinate to place it above
|
||||
// the provided location
|
||||
let yCoordinate = pixelCoords[1] - imageHeight;
|
||||
|
||||
// Since image placement is dependent on the size offsets have to be
|
||||
// scaled as well. Additionally offsets are provided as either positive or
|
||||
// negative values so we always add them
|
||||
if (marker.offsetX) {
|
||||
xCoordinate = xCoordinate + marker.offsetX * scale;
|
||||
}
|
||||
if (marker.offsetY) {
|
||||
yCoordinate = yCoordinate + marker.offsetY * scale;
|
||||
}
|
||||
|
||||
return {
|
||||
x: xCoordinate,
|
||||
y: yCoordinate,
|
||||
};
|
||||
};
|
||||
|
||||
const drawOnCanvas = () => {
|
||||
// Check if the images should be resized before beeing drawn
|
||||
const defaultScale = 1;
|
||||
const scale = marker.scale ? marker.scale : defaultScale;
|
||||
|
||||
// Calculate scaled image sizes
|
||||
const imageWidth = img.width * scale;
|
||||
const imageHeight = img.height * scale;
|
||||
|
||||
// Pass the desired sizes to get correlating coordinates
|
||||
const coords = getMarkerCoordinates(imageWidth, imageHeight, scale);
|
||||
|
||||
// Draw the image on canvas
|
||||
if (scale != defaultScale) {
|
||||
ctx.drawImage(img, coords.x, coords.y, imageWidth, imageHeight);
|
||||
} else {
|
||||
ctx.drawImage(img, coords.x, coords.y);
|
||||
}
|
||||
// Resolve the promise when image has been drawn
|
||||
resolve();
|
||||
};
|
||||
|
||||
img.onload = drawOnCanvas;
|
||||
img.onerror = (err) => {
|
||||
throw err;
|
||||
};
|
||||
img.src = marker.icon;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a list of markers onto a canvas.
|
||||
* Wraps drawing of markers into list of promises and awaits them.
|
||||
* It's required because images are expected to load asynchronous in canvas js
|
||||
* even when provided from a local disk.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {List[Object]} markers Marker objects parsed by extractMarkersFromQuery.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawMarkers = async (ctx, markers, z) => {
|
||||
const markerPromises = [];
|
||||
|
||||
for (const marker of markers) {
|
||||
// Begin drawing marker
|
||||
markerPromises.push(drawMarker(ctx, marker, z));
|
||||
}
|
||||
|
||||
// Await marker drawings before continuing
|
||||
await Promise.all(markerPromises);
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a list of coordinates onto a canvas and styles the resulting path.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {List[Number]} path List of coordinates.
|
||||
* @param {object} query Request query parameters.
|
||||
* @param {string} pathQuery Path query parameter.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawPath = (ctx, path, query, pathQuery, z) => {
|
||||
const splitPaths = pathQuery.split('|');
|
||||
|
||||
if (!path || path.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
// Transform coordinates to pixel on canvas and draw lines between points
|
||||
for (const pair of path) {
|
||||
const px = precisePx(pair, z);
|
||||
ctx.lineTo(px[0], px[1]);
|
||||
}
|
||||
|
||||
// Check if first coordinate matches last coordinate
|
||||
if (
|
||||
path[0][0] === path[path.length - 1][0] &&
|
||||
path[0][1] === path[path.length - 1][1]
|
||||
) {
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
// Optionally fill drawn shape with a rgba color from query
|
||||
const pathHasFill = splitPaths.filter((x) => x.startsWith('fill')).length > 0;
|
||||
if (query.fill !== undefined || pathHasFill) {
|
||||
if ('fill' in query) {
|
||||
ctx.fillStyle = query.fill || 'rgba(255,255,255,0.4)';
|
||||
}
|
||||
if (pathHasFill) {
|
||||
ctx.fillStyle = splitPaths
|
||||
.find((x) => x.startsWith('fill:'))
|
||||
.replace('fill:', '');
|
||||
}
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Get line width from query and fall back to 1 if not provided
|
||||
const pathHasWidth =
|
||||
splitPaths.filter((x) => x.startsWith('width')).length > 0;
|
||||
if (query.width !== undefined || pathHasWidth) {
|
||||
let lineWidth = 1;
|
||||
// Get line width from query
|
||||
if ('width' in query) {
|
||||
lineWidth = Number(query.width);
|
||||
}
|
||||
// Get line width from path in query
|
||||
if (pathHasWidth) {
|
||||
lineWidth = Number(
|
||||
splitPaths.find((x) => x.startsWith('width:')).replace('width:', ''),
|
||||
);
|
||||
}
|
||||
// Get border width from query and fall back to 10% of line width
|
||||
const borderWidth =
|
||||
query.borderwidth !== undefined
|
||||
? parseFloat(query.borderwidth)
|
||||
: lineWidth * 0.1;
|
||||
|
||||
// Set rendering style for the start and end points of the path
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap
|
||||
ctx.lineCap = query.linecap || 'butt';
|
||||
|
||||
// Set rendering style for overlapping segments of the path with differing directions
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
|
||||
ctx.lineJoin = query.linejoin || 'miter';
|
||||
|
||||
// In order to simulate a border we draw the path two times with the first
|
||||
// beeing the wider border part.
|
||||
if (query.border !== undefined && borderWidth > 0) {
|
||||
// We need to double the desired border width and add it to the line width
|
||||
// in order to get the desired border on each side of the line.
|
||||
ctx.lineWidth = lineWidth + borderWidth * 2;
|
||||
// Set border style as rgba
|
||||
ctx.strokeStyle = query.border;
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
const pathHasStroke =
|
||||
splitPaths.filter((x) => x.startsWith('stroke')).length > 0;
|
||||
if (query.stroke !== undefined || pathHasStroke) {
|
||||
if ('stroke' in query) {
|
||||
ctx.strokeStyle = query.stroke;
|
||||
}
|
||||
// Path Stroke gets higher priority
|
||||
if (pathHasStroke) {
|
||||
ctx.strokeStyle = splitPaths
|
||||
.find((x) => x.startsWith('stroke:'))
|
||||
.replace('stroke:', '');
|
||||
}
|
||||
} else {
|
||||
ctx.strokeStyle = 'rgba(0,64,255,0.7)';
|
||||
}
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
export const renderOverlay = async (
|
||||
z,
|
||||
x,
|
||||
y,
|
||||
bearing,
|
||||
pitch,
|
||||
w,
|
||||
h,
|
||||
scale,
|
||||
paths,
|
||||
markers,
|
||||
query,
|
||||
) => {
|
||||
if ((!paths || paths.length === 0) && (!markers || markers.length === 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const center = precisePx([x, y], z);
|
||||
|
||||
const mapHeight = 512 * (1 << z);
|
||||
const maxEdge = center[1] + h / 2;
|
||||
const minEdge = center[1] - h / 2;
|
||||
if (maxEdge > mapHeight) {
|
||||
center[1] -= maxEdge - mapHeight;
|
||||
} else if (minEdge < 0) {
|
||||
center[1] -= minEdge;
|
||||
}
|
||||
|
||||
const canvas = createCanvas(scale * w, scale * h);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
if (bearing) {
|
||||
ctx.translate(w / 2, h / 2);
|
||||
ctx.rotate((-bearing / 180) * Math.PI);
|
||||
ctx.translate(-center[0], -center[1]);
|
||||
} else {
|
||||
// optimized path
|
||||
ctx.translate(-center[0] + w / 2, -center[1] + h / 2);
|
||||
}
|
||||
|
||||
// Draw provided paths if any
|
||||
paths.forEach((path, i) => {
|
||||
const pathQuery = Array.isArray(query.path) ? query.path.at(i) : query.path;
|
||||
drawPath(ctx, path, query, pathQuery, z);
|
||||
});
|
||||
|
||||
// Await drawing of markers before rendering the canvas
|
||||
await drawMarkers(ctx, markers, z);
|
||||
|
||||
return canvas.toBuffer();
|
||||
};
|
||||
|
||||
export const renderWatermark = (width, height, scale, text) => {
|
||||
const canvas = createCanvas(scale * width, scale * height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
|
||||
ctx.font = '10px sans-serif';
|
||||
ctx.strokeWidth = '1px';
|
||||
ctx.strokeStyle = 'rgba(255,255,255,.4)';
|
||||
ctx.strokeText(text, 5, height - 5);
|
||||
ctx.fillStyle = 'rgba(0,0,0,.4)';
|
||||
ctx.fillText(text, 5, height - 5);
|
||||
|
||||
return canvas;
|
||||
};
|
||||
|
||||
export const renderAttribution = (width, height, scale, text) => {
|
||||
const canvas = createCanvas(scale * width, scale * height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
|
||||
ctx.font = '10px sans-serif';
|
||||
const textMetrics = ctx.measureText(text);
|
||||
const textWidth = textMetrics.width;
|
||||
const textHeight = 14;
|
||||
|
||||
const padding = 6;
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
|
||||
ctx.fillRect(
|
||||
width - textWidth - padding,
|
||||
height - textHeight - padding,
|
||||
textWidth + padding,
|
||||
textHeight + padding,
|
||||
);
|
||||
ctx.fillStyle = 'rgba(0,0,0,.8)';
|
||||
ctx.fillText(text, width - textWidth - padding / 2, height - textHeight + 8);
|
||||
|
||||
return canvas;
|
||||
};
|
|
@ -1,10 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
import express from 'express';
|
||||
import fs from 'node:fs';
|
||||
import path from 'path';
|
||||
|
||||
import { getFontsPbf } from './utils.js';
|
||||
import { getFontsPbf, listFonts } from './utils.js';
|
||||
|
||||
export const serve_font = (options, allowedFonts) => {
|
||||
const app = express().disable('x-powered-by');
|
||||
|
@ -14,29 +12,6 @@ export const serve_font = (options, allowedFonts) => {
|
|||
const fontPath = options.paths.fonts;
|
||||
|
||||
const existingFonts = {};
|
||||
const fontListingPromise = new Promise((resolve, reject) => {
|
||||
fs.readdir(options.paths.fonts, (err, files) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
for (const file of files) {
|
||||
fs.stat(path.join(fontPath, file), (err, stats) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
stats.isDirectory() &&
|
||||
fs.existsSync(path.join(fontPath, file, '0-255.pbf'))
|
||||
) {
|
||||
existingFonts[path.basename(file)] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/fonts/:fontstack/:range([\\d]+-[\\d]+).pbf', (req, res, next) => {
|
||||
const fontstack = decodeURI(req.params.fontstack);
|
||||
|
@ -65,5 +40,8 @@ export const serve_font = (options, allowedFonts) => {
|
|||
);
|
||||
});
|
||||
|
||||
return fontListingPromise.then(() => app);
|
||||
return listFonts(options.paths.fonts).then((fonts) => {
|
||||
Object.assign(existingFonts, fonts);
|
||||
return app;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ import path from 'path';
|
|||
import url from 'url';
|
||||
import util from 'util';
|
||||
import zlib from 'zlib';
|
||||
import { createCanvas, Image } from 'canvas';
|
||||
import { renderOverlay, renderWatermark, renderAttribution } from './render.js';
|
||||
import sharp from 'sharp'; // sharp has to be required before node-canvas on linux but after it on windows. see https://github.com/lovell/sharp/issues/371
|
||||
import clone from 'clone';
|
||||
import Color from 'color';
|
||||
|
@ -20,6 +20,7 @@ import proj4 from 'proj4';
|
|||
import axios from 'axios';
|
||||
import {
|
||||
getFontsPbf,
|
||||
listFonts,
|
||||
getTileUrls,
|
||||
isValidHttpUrl,
|
||||
fixTileJSONCenter,
|
||||
|
@ -330,263 +331,6 @@ const extractMarkersFromQuery = (query, options, transformer) => {
|
|||
return markers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms coordinates to pixels.
|
||||
* @param {List[Number]} ll Longitude/Latitude coordinate pair.
|
||||
* @param {number} zoom Map zoom level.
|
||||
*/
|
||||
const precisePx = (ll, zoom) => {
|
||||
const px = mercator.px(ll, 20);
|
||||
const scale = Math.pow(2, zoom - 20);
|
||||
return [px[0] * scale, px[1] * scale];
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a marker in cavans context.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {object} marker Marker object parsed by extractMarkersFromQuery.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawMarker = (ctx, marker, z) => {
|
||||
return new Promise((resolve) => {
|
||||
const img = new Image();
|
||||
const pixelCoords = precisePx(marker.location, z);
|
||||
|
||||
const getMarkerCoordinates = (imageWidth, imageHeight, scale) => {
|
||||
// Images are placed with their top-left corner at the provided location
|
||||
// within the canvas but we expect icons to be centered and above it.
|
||||
|
||||
// Substract half of the images width from the x-coordinate to center
|
||||
// the image in relation to the provided location
|
||||
let xCoordinate = pixelCoords[0] - imageWidth / 2;
|
||||
// Substract the images height from the y-coordinate to place it above
|
||||
// the provided location
|
||||
let yCoordinate = pixelCoords[1] - imageHeight;
|
||||
|
||||
// Since image placement is dependent on the size offsets have to be
|
||||
// scaled as well. Additionally offsets are provided as either positive or
|
||||
// negative values so we always add them
|
||||
if (marker.offsetX) {
|
||||
xCoordinate = xCoordinate + marker.offsetX * scale;
|
||||
}
|
||||
if (marker.offsetY) {
|
||||
yCoordinate = yCoordinate + marker.offsetY * scale;
|
||||
}
|
||||
|
||||
return {
|
||||
x: xCoordinate,
|
||||
y: yCoordinate,
|
||||
};
|
||||
};
|
||||
|
||||
const drawOnCanvas = () => {
|
||||
// Check if the images should be resized before beeing drawn
|
||||
const defaultScale = 1;
|
||||
const scale = marker.scale ? marker.scale : defaultScale;
|
||||
|
||||
// Calculate scaled image sizes
|
||||
const imageWidth = img.width * scale;
|
||||
const imageHeight = img.height * scale;
|
||||
|
||||
// Pass the desired sizes to get correlating coordinates
|
||||
const coords = getMarkerCoordinates(imageWidth, imageHeight, scale);
|
||||
|
||||
// Draw the image on canvas
|
||||
if (scale != defaultScale) {
|
||||
ctx.drawImage(img, coords.x, coords.y, imageWidth, imageHeight);
|
||||
} else {
|
||||
ctx.drawImage(img, coords.x, coords.y);
|
||||
}
|
||||
// Resolve the promise when image has been drawn
|
||||
resolve();
|
||||
};
|
||||
|
||||
img.onload = drawOnCanvas;
|
||||
img.onerror = (err) => {
|
||||
throw err;
|
||||
};
|
||||
img.src = marker.icon;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a list of markers onto a canvas.
|
||||
* Wraps drawing of markers into list of promises and awaits them.
|
||||
* It's required because images are expected to load asynchronous in canvas js
|
||||
* even when provided from a local disk.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {List[Object]} markers Marker objects parsed by extractMarkersFromQuery.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawMarkers = async (ctx, markers, z) => {
|
||||
const markerPromises = [];
|
||||
|
||||
for (const marker of markers) {
|
||||
// Begin drawing marker
|
||||
markerPromises.push(drawMarker(ctx, marker, z));
|
||||
}
|
||||
|
||||
// Await marker drawings before continuing
|
||||
await Promise.all(markerPromises);
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a list of coordinates onto a canvas and styles the resulting path.
|
||||
* @param {object} ctx Canvas context object.
|
||||
* @param {List[Number]} path List of coordinates.
|
||||
* @param {object} query Request query parameters.
|
||||
* @param {string} pathQuery Path query parameter.
|
||||
* @param {number} z Map zoom level.
|
||||
*/
|
||||
const drawPath = (ctx, path, query, pathQuery, z) => {
|
||||
const splitPaths = pathQuery.split('|');
|
||||
|
||||
if (!path || path.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
// Transform coordinates to pixel on canvas and draw lines between points
|
||||
for (const pair of path) {
|
||||
const px = precisePx(pair, z);
|
||||
ctx.lineTo(px[0], px[1]);
|
||||
}
|
||||
|
||||
// Check if first coordinate matches last coordinate
|
||||
if (
|
||||
path[0][0] === path[path.length - 1][0] &&
|
||||
path[0][1] === path[path.length - 1][1]
|
||||
) {
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
// Optionally fill drawn shape with a rgba color from query
|
||||
const pathHasFill = splitPaths.filter((x) => x.startsWith('fill')).length > 0;
|
||||
if (query.fill !== undefined || pathHasFill) {
|
||||
if ('fill' in query) {
|
||||
ctx.fillStyle = query.fill || 'rgba(255,255,255,0.4)';
|
||||
}
|
||||
if (pathHasFill) {
|
||||
ctx.fillStyle = splitPaths
|
||||
.find((x) => x.startsWith('fill:'))
|
||||
.replace('fill:', '');
|
||||
}
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Get line width from query and fall back to 1 if not provided
|
||||
const pathHasWidth =
|
||||
splitPaths.filter((x) => x.startsWith('width')).length > 0;
|
||||
if (query.width !== undefined || pathHasWidth) {
|
||||
let lineWidth = 1;
|
||||
// Get line width from query
|
||||
if ('width' in query) {
|
||||
lineWidth = Number(query.width);
|
||||
}
|
||||
// Get line width from path in query
|
||||
if (pathHasWidth) {
|
||||
lineWidth = Number(
|
||||
splitPaths.find((x) => x.startsWith('width:')).replace('width:', ''),
|
||||
);
|
||||
}
|
||||
// Get border width from query and fall back to 10% of line width
|
||||
const borderWidth =
|
||||
query.borderwidth !== undefined
|
||||
? parseFloat(query.borderwidth)
|
||||
: lineWidth * 0.1;
|
||||
|
||||
// Set rendering style for the start and end points of the path
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap
|
||||
ctx.lineCap = query.linecap || 'butt';
|
||||
|
||||
// Set rendering style for overlapping segments of the path with differing directions
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
|
||||
ctx.lineJoin = query.linejoin || 'miter';
|
||||
|
||||
// In order to simulate a border we draw the path two times with the first
|
||||
// beeing the wider border part.
|
||||
if (query.border !== undefined && borderWidth > 0) {
|
||||
// We need to double the desired border width and add it to the line width
|
||||
// in order to get the desired border on each side of the line.
|
||||
ctx.lineWidth = lineWidth + borderWidth * 2;
|
||||
// Set border style as rgba
|
||||
ctx.strokeStyle = query.border;
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
const pathHasStroke =
|
||||
splitPaths.filter((x) => x.startsWith('stroke')).length > 0;
|
||||
if (query.stroke !== undefined || pathHasStroke) {
|
||||
if ('stroke' in query) {
|
||||
ctx.strokeStyle = query.stroke;
|
||||
}
|
||||
// Path Stroke gets higher priority
|
||||
if (pathHasStroke) {
|
||||
ctx.strokeStyle = splitPaths
|
||||
.find((x) => x.startsWith('stroke:'))
|
||||
.replace('stroke:', '');
|
||||
}
|
||||
} else {
|
||||
ctx.strokeStyle = 'rgba(0,64,255,0.7)';
|
||||
}
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
const renderOverlay = async (
|
||||
z,
|
||||
x,
|
||||
y,
|
||||
bearing,
|
||||
pitch,
|
||||
w,
|
||||
h,
|
||||
scale,
|
||||
paths,
|
||||
markers,
|
||||
query,
|
||||
) => {
|
||||
if ((!paths || paths.length === 0) && (!markers || markers.length === 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const center = precisePx([x, y], z);
|
||||
|
||||
const mapHeight = 512 * (1 << z);
|
||||
const maxEdge = center[1] + h / 2;
|
||||
const minEdge = center[1] - h / 2;
|
||||
if (maxEdge > mapHeight) {
|
||||
center[1] -= maxEdge - mapHeight;
|
||||
} else if (minEdge < 0) {
|
||||
center[1] -= minEdge;
|
||||
}
|
||||
|
||||
const canvas = createCanvas(scale * w, scale * h);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
if (bearing) {
|
||||
ctx.translate(w / 2, h / 2);
|
||||
ctx.rotate((-bearing / 180) * Math.PI);
|
||||
ctx.translate(-center[0], -center[1]);
|
||||
} else {
|
||||
// optimized path
|
||||
ctx.translate(-center[0] + w / 2, -center[1] + h / 2);
|
||||
}
|
||||
|
||||
// Draw provided paths if any
|
||||
paths.forEach((path, i) => {
|
||||
const pathQuery = Array.isArray(query.path) ? query.path.at(i) : query.path;
|
||||
drawPath(ctx, path, query, pathQuery, z);
|
||||
});
|
||||
|
||||
// Await drawing of markers before rendering the canvas
|
||||
await drawMarkers(ctx, markers, z);
|
||||
|
||||
return canvas.toBuffer();
|
||||
};
|
||||
|
||||
const calcZForBBox = (bbox, w, h, query) => {
|
||||
let z = 25;
|
||||
|
||||
|
@ -608,42 +352,8 @@ const calcZForBBox = (bbox, w, h, query) => {
|
|||
return z;
|
||||
};
|
||||
|
||||
const existingFonts = {};
|
||||
let maxScaleFactor = 2;
|
||||
|
||||
export const serve_rendered = {
|
||||
init: (options, repo) => {
|
||||
const fontListingPromise = new Promise((resolve, reject) => {
|
||||
fs.readdir(options.paths.fonts, (err, files) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
for (const file of files) {
|
||||
fs.stat(path.join(options.paths.fonts, file), (err, stats) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
if (stats.isDirectory()) {
|
||||
existingFonts[path.basename(file)] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
maxScaleFactor = Math.min(Math.floor(options.maxScaleFactor || 3), 9);
|
||||
let scalePattern = '';
|
||||
for (let i = 2; i <= maxScaleFactor; i++) {
|
||||
scalePattern += i.toFixed();
|
||||
}
|
||||
scalePattern = `@[${scalePattern}]x`;
|
||||
|
||||
const app = express().disable('x-powered-by');
|
||||
|
||||
const respondImage = (
|
||||
const respondImage = (
|
||||
options,
|
||||
item,
|
||||
z,
|
||||
lon,
|
||||
|
@ -655,10 +365,9 @@ export const serve_rendered = {
|
|||
scale,
|
||||
format,
|
||||
res,
|
||||
next,
|
||||
opt_overlay,
|
||||
opt_mode = 'tile',
|
||||
) => {
|
||||
overlay = null,
|
||||
mode = 'tile',
|
||||
) => {
|
||||
if (
|
||||
Math.abs(lon) > 180 ||
|
||||
Math.abs(lat) > 85.06 ||
|
||||
|
@ -686,7 +395,7 @@ export const serve_rendered = {
|
|||
|
||||
const tileMargin = Math.max(options.tileMargin || 0, 0);
|
||||
let pool;
|
||||
if (opt_mode === 'tile' && tileMargin === 0) {
|
||||
if (mode === 'tile' && tileMargin === 0) {
|
||||
pool = item.map.renderers[scale];
|
||||
} else {
|
||||
pool = item.map.renderers_static[scale];
|
||||
|
@ -716,10 +425,7 @@ export const serve_rendered = {
|
|||
pool.release(renderer);
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res
|
||||
.status(500)
|
||||
.header('Content-Type', 'text/plain')
|
||||
.send(err);
|
||||
return res.status(500).header('Content-Type', 'text/plain').send(err);
|
||||
}
|
||||
|
||||
// Fix semi-transparent outlines on raw, premultiplied input
|
||||
|
@ -765,48 +471,22 @@ export const serve_rendered = {
|
|||
image.resize(width * scale, height * scale);
|
||||
}
|
||||
|
||||
var composite_array = [];
|
||||
if (opt_overlay) {
|
||||
composite_array.push({ input: opt_overlay });
|
||||
const composite_array = [];
|
||||
if (overlay) {
|
||||
composite_array.push({ input: overlay });
|
||||
}
|
||||
if (item.watermark) {
|
||||
const canvas = createCanvas(scale * width, scale * height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
ctx.font = '10px sans-serif';
|
||||
ctx.strokeWidth = '1px';
|
||||
ctx.strokeStyle = 'rgba(255,255,255,.4)';
|
||||
ctx.strokeText(item.watermark, 5, height - 5);
|
||||
ctx.fillStyle = 'rgba(0,0,0,.4)';
|
||||
ctx.fillText(item.watermark, 5, height - 5);
|
||||
const canvas = renderWatermark(width, height, scale, item.watermark);
|
||||
|
||||
composite_array.push({ input: canvas.toBuffer() });
|
||||
}
|
||||
|
||||
if (opt_mode === 'static' && item.staticAttributionText) {
|
||||
const canvas = createCanvas(scale * width, scale * height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
|
||||
ctx.font = '10px sans-serif';
|
||||
const text = item.staticAttributionText;
|
||||
const textMetrics = ctx.measureText(text);
|
||||
const textWidth = textMetrics.width;
|
||||
const textHeight = 14;
|
||||
|
||||
const padding = 6;
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
|
||||
ctx.fillRect(
|
||||
width - textWidth - padding,
|
||||
height - textHeight - padding,
|
||||
textWidth + padding,
|
||||
textHeight + padding,
|
||||
);
|
||||
ctx.fillStyle = 'rgba(0,0,0,.8)';
|
||||
ctx.fillText(
|
||||
if (mode === 'static' && item.staticAttributionText) {
|
||||
const canvas = renderAttribution(
|
||||
width,
|
||||
height,
|
||||
scale,
|
||||
item.staticAttributionText,
|
||||
width - textWidth - padding / 2,
|
||||
height - textHeight + 8,
|
||||
);
|
||||
|
||||
composite_array.push({ input: canvas.toBuffer() });
|
||||
|
@ -838,7 +518,21 @@ export const serve_rendered = {
|
|||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const existingFonts = {};
|
||||
let maxScaleFactor = 2;
|
||||
|
||||
export const serve_rendered = {
|
||||
init: (options, repo) => {
|
||||
maxScaleFactor = Math.min(Math.floor(options.maxScaleFactor || 3), 9);
|
||||
let scalePattern = '';
|
||||
for (let i = 2; i <= maxScaleFactor; i++) {
|
||||
scalePattern += i.toFixed();
|
||||
}
|
||||
scalePattern = `@[${scalePattern}]x`;
|
||||
|
||||
const app = express().disable('x-powered-by');
|
||||
|
||||
app.get(
|
||||
`/:id/:z(\\d+)/:x(\\d+)/:y(\\d+):scale(${scalePattern})?.:format([\\w]+)`,
|
||||
|
@ -880,6 +574,7 @@ export const serve_rendered = {
|
|||
z,
|
||||
);
|
||||
return respondImage(
|
||||
options,
|
||||
item,
|
||||
z,
|
||||
tileCenter[0],
|
||||
|
@ -891,7 +586,6 @@ export const serve_rendered = {
|
|||
scale,
|
||||
format,
|
||||
res,
|
||||
next,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -962,6 +656,7 @@ export const serve_rendered = {
|
|||
);
|
||||
|
||||
return respondImage(
|
||||
options,
|
||||
item,
|
||||
z,
|
||||
x,
|
||||
|
@ -973,7 +668,6 @@ export const serve_rendered = {
|
|||
scale,
|
||||
format,
|
||||
res,
|
||||
next,
|
||||
overlay,
|
||||
'static',
|
||||
);
|
||||
|
@ -1043,6 +737,7 @@ export const serve_rendered = {
|
|||
req.query,
|
||||
);
|
||||
return respondImage(
|
||||
options,
|
||||
item,
|
||||
z,
|
||||
x,
|
||||
|
@ -1054,7 +749,6 @@ export const serve_rendered = {
|
|||
scale,
|
||||
format,
|
||||
res,
|
||||
next,
|
||||
overlay,
|
||||
'static',
|
||||
);
|
||||
|
@ -1177,6 +871,7 @@ export const serve_rendered = {
|
|||
);
|
||||
|
||||
return respondImage(
|
||||
options,
|
||||
item,
|
||||
z,
|
||||
x,
|
||||
|
@ -1188,7 +883,6 @@ export const serve_rendered = {
|
|||
scale,
|
||||
format,
|
||||
res,
|
||||
next,
|
||||
overlay,
|
||||
'static',
|
||||
);
|
||||
|
@ -1215,7 +909,10 @@ export const serve_rendered = {
|
|||
return res.send(info);
|
||||
});
|
||||
|
||||
return Promise.all([fontListingPromise]).then(() => app);
|
||||
return listFonts(options.paths.fonts).then((fonts) => {
|
||||
Object.assign(existingFonts, fonts);
|
||||
return app;
|
||||
});
|
||||
},
|
||||
add: async (options, repo, params, id, publicUrl, dataResolver) => {
|
||||
const map = {
|
||||
|
@ -1618,7 +1315,7 @@ export const serve_rendered = {
|
|||
}
|
||||
});
|
||||
|
||||
return Promise.all([renderersReadyPromise]);
|
||||
return renderersReadyPromise;
|
||||
},
|
||||
remove: (repo, id) => {
|
||||
const item = repo[id];
|
||||
|
|
|
@ -98,9 +98,7 @@ export const serve_style = {
|
|||
|
||||
const validationErrors = validate(styleFileData);
|
||||
if (validationErrors.length > 0) {
|
||||
console.log(
|
||||
`The file "${params.style}" is not valid a valid style file:`,
|
||||
);
|
||||
console.log(`The file "${params.style}" is not a valid style file:`);
|
||||
for (const err of validationErrors) {
|
||||
console.log(`${err.line}: ${err.message}`);
|
||||
}
|
||||
|
|
29
src/utils.js
29
src/utils.js
|
@ -163,6 +163,35 @@ export const getFontsPbf = (
|
|||
return Promise.all(queue).then((values) => glyphCompose.combine(values));
|
||||
};
|
||||
|
||||
export const listFonts = async (fontPath) => {
|
||||
const existingFonts = {};
|
||||
const fontListingPromise = new Promise((resolve, reject) => {
|
||||
fs.readdir(fontPath, (err, files) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
for (const file of files) {
|
||||
fs.stat(path.join(fontPath, file), (err, stats) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
stats.isDirectory() &&
|
||||
fs.existsSync(path.join(fontPath, file, '0-255.pbf'))
|
||||
) {
|
||||
existingFonts[path.basename(file)] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await fontListingPromise;
|
||||
return existingFonts;
|
||||
};
|
||||
|
||||
export const isValidHttpUrl = (string) => {
|
||||
let url;
|
||||
|
||||
|
|
|
@ -24,6 +24,5 @@ after(function () {
|
|||
console.log('global teardown');
|
||||
global.server.close(function () {
|
||||
console.log('Done');
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue