Compare commits

..

98 Commits

Author SHA1 Message Date
Petr Sloup
4996848bdc Update package version to 2.6.0 2019-08-26 12:16:06 +02:00
Petr Sloup
aa7ae575d0 Flatten 3D buildings when rendering to remove artifacts 2019-08-26 12:10:49 +02:00
Petr Sloup
9603703908 Minor css fix 2019-08-26 12:10:32 +02:00
Petr Sloup
e44104254e Update handlebars 2019-07-12 11:25:08 +02:00
Petr Sloup
58b536036f Merge pull request #370 from golubev/patch-1
update 'installation.rst': fix a mistake
2019-06-25 07:58:53 +02:00
Sergii Golubev
a68e095400 update 'installation.rst': fix a mistake 2019-06-24 18:56:04 +03:00
Petr Sloup
53b28b35f1 Merge pull request #369 from bradh/patch-1
Trivial typo fix in docs
2019-06-24 07:39:44 +02:00
Brad Hards
58f92ae947 Trivial typo fix in docs 2019-06-22 11:02:36 +10:00
Petr Sloup
e506014763 Minor /styles.json fix (close #361) 2019-04-29 06:48:23 +02:00
Petr Sloup
7c5e7e94e9 Merge pull request #358 from disarticulate/master
Use verbose flag to debug corrupted mbtiles
2019-04-25 10:34:28 +02:00
Eric Xanderson
e6747ebb78 Merge pull request #2 from disarticulate/patch-2
verbose output empty tile warning
2019-04-23 20:53:17 -05:00
Eric Xanderson
2a87ad19c9 Merge pull request #1 from disarticulate/patch-1
add verbose to options
2019-04-23 20:52:46 -05:00
Eric Xanderson
ba62f0bf30 verbose output empty tile warning
Empty tile warning details; definitely what you would expect if there's not a catastrophic error, but you're getting blank tiles.

such as: ```
MBTiles error, serving empty { Error: SQLITE_CORRUPT: database disk image is malformed
lily_tile_server |     at Error (native) errno: 11, code: 'SQLITE_CORRUPT' }

```
https://github.com/klokantech/tileserver-gl/issues/323
2019-04-23 20:51:39 -05:00
Eric Xanderson
08369a666d add verbose to options
pass verbose to server for better handling of warnings
2019-04-23 20:43:56 -05:00
Petr Sloup
f771d41788 Merge pull request #355 from cyclemap/master
let the user define a log file or a log format
2019-04-15 08:00:28 +02:00
adrian
9dda95ee8e let the user define a log file or a log format
log file defaults to standard out.

log format defaults to current behavior ('tiny' for production, 'dev' for dev, and not enabled in test)
2019-04-13 11:55:37 -04:00
Petr Sloup
63483a3155 Merge pull request #339 from ibesora/master
Removes body data from http 204 response
2019-01-07 14:16:30 +01:00
Isaac Besora Vilardaga
bca5191ad9 Removes body data from http 204 response 2019-01-07 13:48:22 +01:00
Petr Sloup
245d9765a9 Merge pull request #337 from mcolmant/master
Correctly retrieve the public_url parameter on start
2019-01-03 10:57:05 +01:00
Maxime Colmant
e8134dfeb0 fix: correctly retrieve the public_url parameter on start 2018-12-26 16:26:49 +01:00
Petr Sloup
a1a8996d3f Update package version to 2.5.0 2018-12-19 13:28:27 +01:00
Petr Sloup
bea528ab64 Update dependencies 2018-12-19 13:22:41 +01:00
Petr Sloup
cde0233130 Merge pull request #230 from koumoul-dev/public_url
add public_url option
2018-12-19 13:19:07 +01:00
Alban Mouton
c99a1a5425 Merge remote-tracking branch 'klokantech/master' into public_url
# Conflicts:
#	src/main.js
#	src/server.js
2018-12-19 09:53:40 +01:00
Petr Sloup
243bdbdaa0 Update Dockerfile_light to match the baseimage version 2018-12-19 09:28:37 +01:00
Petr Sloup
0631a76a51 Merge pull request #313 from guenhter/ensure-xvfb-started
Wait for Xvfb to startup
2018-12-19 09:27:46 +01:00
guenhter
8e1071aad0 Wait for Xvfb to startup 2018-12-19 09:06:53 +01:00
Petr Sloup
e283569897 Merge pull request #333 from luzik/patch-1
new mapbox-gl-native version
2018-12-18 09:10:15 +01:00
Petr Sloup
507da8567e Merge pull request #321 from loicgasser/css-break-all
Break all on long title and item
2018-12-18 09:02:42 +01:00
luzik
9cd6feb56d new mapbox-gl-native version
According to https://github.com/mapbox/mapbox-gl-native/blob/master/platform/node/CHANGELOG.md there is no broken features.
Previous version is not buildable now.

> @mapbox/mapbox-gl-native@3.5.4 install /home/ubuntu/maps/node_modules/@mapbox/mapbox-gl-native
> node-pre-gyp install --fallback-to-build=false || make node
```
node-pre-gyp ERR! install error 
node-pre-gyp ERR! stack Error: 403 status code downloading tarball https://mapbox-node-binary.s3.amazonaws.com/@mapbox/mapbox-gl-native/v3.5.4/node-v57-linux-x64-Release.tar.gz
```
2018-12-17 15:52:05 +01:00
Gasser Loïc
059b0f11a0 Break all on long title and item 2018-10-12 10:53:14 -04:00
Petr Sloup
7acbc93ba9 Update package version to 2.4.0 2018-09-14 08:23:55 +02:00
Petr Sloup
bc3d79bfdc Update dependencies 2018-09-14 08:14:28 +02:00
Petr Sloup
58168eb0a5 Merge pull request #307 from spatialillusions/master
Add support for WMTS capabilities
2018-09-14 08:03:59 +02:00
Petr Sloup
f993b01387 Merge pull request #303 from loicgasser/update_libs
Update commander and devDeps
2018-09-14 08:00:03 +02:00
Måns Beckman
782c28cd64 Add key to WMTS xml
This should add the key to the wmts xml for hosted services
2018-09-13 17:58:13 +02:00
Måns Beckman
76a0064f0c Remove unused variables 2018-09-13 17:57:06 +02:00
Petr Sloup
55fa8bf8c1 Merge pull request #278 from amirmasud/return-204-when-no-tile-found
Return 204 when mbtiles error is 'Tile does not exist'
2018-09-13 16:26:35 +02:00
Petr Sloup
0c42fdd6b3 Merge pull request #310 from guenhter/fix-restart
Ensure that container can be restarted
2018-09-13 16:25:16 +02:00
Måns Beckman
e8b3c02546 Fix formating 2018-09-11 17:51:38 +02:00
Måns Beckman
56089c0a62 Remove base64url 2018-09-11 17:47:44 +02:00
guenhter
857ff2d8d7 Ensure that container can be restarted 2018-09-10 10:31:58 +02:00
Måns Beckman
e310fa5165 Merge branch 'master' of https://github.com/spatialillusions/tileserver-gl 2018-08-21 19:33:56 +02:00
Måns Beckman
71fab2a2a1 Add support for WMTS capabilites
https://github.com/klokantech/tileserver-gl/issues/274

Clean up wmts template with correct syntax

Update endpoint URL and change content type

After a good nights sleep I considered the structure of the endpoint link for WMTS, at the same time I cleaned up the code and added the correct content type for the response.
2018-08-21 19:33:37 +02:00
Petr Sloup
1c59e3d742 Fix typo 2018-08-21 19:33:37 +02:00
Måns Beckman
6e24f6ec8e Update endpoint URL and change content type
After a good nights sleep I considered the structure of the endpoint link for WMTS, at the same time I cleaned up the code and added the correct content type for the response.
2018-08-18 12:02:54 +02:00
Måns Beckman
5d5ed1153f Clean up wmts template with correct syntax 2018-08-17 15:48:35 +02:00
Måns Beckman
baf01a117b Add support for WMTS capabilites
https://github.com/klokantech/tileserver-gl/issues/274
2018-08-17 13:11:19 +02:00
Gasser Loïc
2cc2cc1b3b Update commander to the latest version 2018-08-08 11:44:46 -04:00
Loïc Gasser
45ed8d90ca Update commander and devDeps, invert default val and function accordingly 2018-08-03 00:05:20 -04:00
Petr Sloup
8e66736955 Fix typo 2018-06-21 19:00:10 +02:00
Masud Zare
72ea5ab05d fix corresponding test scenario 2018-05-07 15:58:32 +04:30
Masud Zare
9d642fa0b3 return 204 when mbtiles error is 'Tile does not exist' 2018-05-07 15:21:41 +04:30
Petr Sloup
1d734f9b42 Merge pull request #270 from geoadmin/fix_doc
Add silent to doc
2018-04-19 08:38:44 +02:00
loicgasser
80146ed7d9 Add silent to doc 2018-03-22 16:12:06 +00:00
Petr Sloup
a28df7ef8f Merge pull request #269 from michaill/master
Silent mode (do not log requests with status == 200)
2018-03-22 13:14:40 +01:00
Michal Illovsky
c333197a7c Skipping also 304 status codes when in silent mode 2018-03-22 09:02:09 +01:00
Michal Illovsky
45df72df51 Enable silent mode with -s option to not log successful request (status=200) 2018-03-19 13:47:17 +01:00
Petr Sloup
e737753891 Merge pull request #263 from geoadmin/nomnom_commander
Replace Nomnom with Commander
2018-03-14 15:17:29 +01:00
loicgasser
edff8ce06c Fix version and positional argument for mbtiles 2018-03-12 11:53:11 +00:00
loicgasser
df05ce3f2a Add default val in description 2018-03-08 17:55:30 +00:00
loicgasser
a74ca20375 Replace nomnom with commander 2018-03-08 16:05:58 +00:00
loicgasser
1c890b0157 Update doc 2018-03-08 16:05:46 +00:00
Petr Sloup
7a9f04a024 Update MB GL JS to v0.43.0 2018-03-01 09:26:56 +01:00
Petr Pridal
1354c7f663 Update README.md 2018-02-19 15:49:08 +01:00
Petr Sloup
da3cb1e7f5 Update ISSUE_TEMPLATE.md 2018-01-23 12:17:14 +01:00
Petr Sloup
19e821a8fe Update package version to 2.3.1 2017-12-14 09:56:41 +01:00
Petr Sloup
659289d85c Update dependencies 2017-12-14 09:56:21 +01:00
Petr Sloup
734d1f01f0 Prioritize font fallbacks and try to respect proper font style 2017-12-14 09:55:57 +01:00
Petr Sloup
c1055a9647 Update package version to 2.3.0 2017-12-01 11:13:11 +01:00
Petr Sloup
2afb460191 Merge pull request #242 from samizdis/master
Addresses issue #197, send SIGTERM through to node
2017-12-01 10:52:52 +01:00
Sam Brown
8eb736b821 Addresses issue #197, send SIGTERM through to node
Node can't be PID 1, else it can't be term'ed and xvfb won't stop nicely.  So, according to https://docs.docker.com/engine/reference/builder/#entrypoint, we need to make sure it's not the bare entrypoint.

Also we need to be sure that run.sh passes the signal through to node, see https://unix.stackexchange.com/questions/146756/forward-sigterm-to-child-in-bash
2017-11-30 12:30:40 +00:00
Petr Sloup
83e20b7a4e Merge pull request #232 from rani-pinchuk/fix-zlib-incorrect-header-check
Catch incorrect header exceptions
2017-11-13 09:39:06 +01:00
Rani Pinchuk
81f65af3a8 Fix log message when incorrect header exception is caught 2017-11-09 18:00:41 +01:00
Petr Sloup
f5ea790878 Stop Xvfb when stopping the container (#197) 2017-11-08 17:01:28 +01:00
Rani Pinchuk
a0eb5800fd Catch incorrect header exceptions 2017-11-03 16:53:45 +01:00
Petr Sloup
27eb7f0ed8 Merge pull request #229 from tschaub/handle-rejection
Handle promise rejection
2017-11-01 09:15:02 +01:00
Tim Schaub
2f9059d09e Unnecessary promise wrapping 2017-10-23 10:05:30 -06:00
Tim Schaub
e11c8f9315 Reject font listing promise on error 2017-10-23 10:01:43 -06:00
Tim Schaub
650718e0f6 Avoid swallowing rejected font listing promise 2017-10-23 10:01:43 -06:00
Tim Schaub
5ed632c229 Reject source info promise on error 2017-10-23 10:01:32 -06:00
Tim Schaub
f545076986 Avoid swallowing rejected source info promise 2017-10-23 10:01:19 -06:00
Tim Schaub
3d48485475 Reject on font loading error 2017-10-23 10:01:16 -06:00
Tim Schaub
c060dedf20 Avoid swallowing rejected font loading promise 2017-10-23 10:01:01 -06:00
Tim Schaub
cd1f5fd04a Return after rejecting, catch and log 2017-10-23 09:46:04 -06:00
Alban Mouton
dc6be5047c missing public_url in tiles urls 2017-10-18 14:49:10 +02:00
Alban Mouton
47ff33166d missing public_url in templates 2017-10-18 14:20:33 +02:00
Alban Mouton
875521c5a8 add public_url option 2017-10-18 13:51:37 +02:00
Petr Sloup
82f179b07c Minor fix for correctly serving empty responses for missing tiles 2017-10-02 13:56:32 +02:00
Petr Sloup
51d6ca0880 Merge pull request #222 from otsaloma/renderer-pool-sizes
Make raster tile renderer pool sizes configurable
2017-10-02 10:04:22 +02:00
Osmo Salomaa
89878015bb Make raster tile renderer pool sizes configurable 2017-10-01 18:40:16 +03:00
Petr Pridal
ac948b6dee Create ISSUE_TEMPLATE.md 2017-09-28 00:53:05 +02:00
Petr Sloup
440775dbbf Update README.md 2017-09-25 13:23:05 +02:00
Petr Sloup
ea408f8ec9 Increase test timeout since travis can be slow on cold start when under load 2017-09-20 08:21:34 +02:00
Petr Sloup
da646868c3 Wait longer for xvfb to start up (#197) 2017-09-20 08:05:10 +02:00
Petr Sloup
d60996e3c6 Reorganize Dockerfile instructions for faster rebuilds 2017-09-20 08:03:46 +02:00
Petr Sloup
02cf45bbd9 Clean Dockerfile by basing on node:6-stretch 2017-09-20 08:01:35 +02:00
Petr Sloup
d9f8582279 Remove node-pngquant-native dependency
- Unnecessary native dependency
- It was disabled by default
- Has issues on certain platforms
- Not optimal for production use (performance)
2017-09-15 17:06:42 +02:00
29 changed files with 1497 additions and 659 deletions

View File

@@ -1,6 +1,12 @@
FROM debian:stretch
FROM node:6.15.1-stretch
MAINTAINER Petr Sloup <petr.sloup@klokantech.com>
ENV NODE_ENV="production"
VOLUME /data
WORKDIR /data
EXPOSE 80
ENTRYPOINT ["/bin/bash", "/usr/src/app/run.sh"]
RUN apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install \
apt-transport-https \
@@ -15,22 +21,9 @@ RUN apt-get -qq update \
libprotobuf-dev \
libxxf86vm-dev \
xvfb \
&& echo "deb https://deb.nodesource.com/node_6.x stretch main" >> /etc/apt/sources.list.d/nodejs.list \
&& echo "deb-src https://deb.nodesource.com/node_6.x stretch main" >> /etc/apt/sources.list.d/nodejs.list \
&& apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y --allow-unauthenticated install \
nodejs \
&& rm /etc/apt/sources.list.d/nodejs.list \
x11-utils \
&& apt-get clean
RUN mkdir -p /usr/src/app
COPY / /usr/src/app
RUN cd /usr/src/app && npm install --production
VOLUME /data
WORKDIR /data
ENV NODE_ENV="production"
EXPOSE 80
ENTRYPOINT ["/usr/src/app/run.sh"]

View File

@@ -1,14 +1,12 @@
FROM node:6
FROM node:6.15.1-stretch
MAINTAINER Petr Sloup <petr.sloup@klokantech.com>
ENV NODE_ENV="production"
EXPOSE 80
VOLUME /data
WORKDIR /data
ENTRYPOINT ["node", "/usr/src/app/", "-p", "80"]
RUN mkdir -p /usr/src/app
COPY / /usr/src/app
RUN cd /usr/src/app && npm install --production
VOLUME /data
WORKDIR /data
ENV NODE_ENV="production"
EXPOSE 80
ENTRYPOINT ["node", "/usr/src/app/", "-p", "80"]

35
Dockerfile_test Normal file
View File

@@ -0,0 +1,35 @@
# Run tests inside docker without requiring full installation of dependencies on local machine
# Simply run "docker build -f Dockerfile_test ."
# WARNING: sometimes it fails with a core dumped exception
FROM node:6-stretch
MAINTAINER Petr Sloup <petr.sloup@klokantech.com>
RUN apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install \
apt-transport-https \
curl \
unzip \
build-essential \
python \
libcairo2-dev \
libgles2-mesa-dev \
libgbm-dev \
libllvm3.9 \
libprotobuf-dev \
libxxf86vm-dev \
xvfb \
&& apt-get clean
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN wget -O test_data.zip https://github.com/klokantech/tileserver-gl/releases/download/v1.3.0/test_data.zip
RUN unzip -q test_data.zip -d test_data
ENV NODE_ENV="test"
COPY package.json .
RUN npm install
COPY / .
RUN xvfb-run --server-args="-screen 0 1024x768x24" npm test

21
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,21 @@
It is great you want to help us making TileServer GL project better!
This is the right place only for a software bug report or a new software feature request.
NOTE: Questions about OpenMapTiles data, OpenMapTiles Server, TileHosting and other software/products do not belong here (and will not be answered)!
The usage and installation questions belongs to https://stackoverflow.com/questions/tagged/openmaptiles
A guaranteed support and consulting from the core developers via https://openmaptiles.com/support/
Please search this GitHub repo for similar requests before posting (check also closed tickets).
When reporting a problem you have with the TileServer GL software please provide:
- Clear description of the problem: What steps will lead to reproducing the error on our computer? What is exactly wrong?
- Version of the TileServer GL software you have used
- Version and name of the operating system you use or other details of your setup
- Information about your used config / styles / vector tiles
- URL / link to the specific location in a live map demo where a bug is visible is always great
- Screenshot of the problem are cool! Drag&drop an image to the report here...
We love pull requests! If you are able to code, please send us your fix or code modification via GitHub... Thanks!

View File

@@ -9,6 +9,8 @@ Vector and raster maps with GL styles. Server side rendering by Mapbox GL Native
## Get Started
Make sure you have Node.js version **6** installed (running `node -v` it should output something like `v6.11.3`).
Install `tileserver-gl` with server-side raster rendering of vector tiles with npm
```bash
@@ -18,7 +20,7 @@ npm install -g tileserver-gl
Now download vector tiles from [OpenMapTiles](https://openmaptiles.org/downloads/).
```bash
curl -o zurich_switzerland.mbtiles https://openmaptiles.os.zhdk.cloud.switch.ch/v3.3/extracts/zurich_switzerland.mbtiles
curl -o zurich_switzerland.mbtiles https://[GET-YOUR-LINK]/extracts/zurich_switzerland.mbtiles
```
Start `tileserver-gl` with the downloaded vector tiles.

View File

@@ -21,9 +21,7 @@ Example::
],
"formatQuality": {
"jpeg": 80,
"webp": 90,
"pngQuantization": false,
"png": 90
"webp": 90
},
"maxScaleFactor": 3,
"maxSize": 2048,
@@ -83,8 +81,6 @@ Use ``false`` to disable the front page altogether (404).
Quality of the compression of individual image formats. [0-100]
The value for ``png`` is only used when ``pngQuantization`` is ``true``.
``maxScaleFactor``
-----------
@@ -99,6 +95,27 @@ Maximum image side length to be allowed to be rendered (including scale factor).
Be careful when changing this value since there are hardware limits that need to be considered.
Default is ``2048``.
``minRendererPoolSizes``
------------------------
Minimum amount of raster tile renderers per scale factor.
The value is an array: the first element is the minimum amount of renderers for scale factor one, the second for scale factor two and so on.
If the array has less elements than ``maxScaleFactor``, then the last element is used for all remaining scale factors as well.
Selecting renderer pool sizes is a trade-off between memory use and speed.
A reasonable value will depend on your hardware and your amount of styles and scale factors.
If you have plenty of memory, you'll want to set this equal to ``maxRendererPoolSizes`` to avoid increased latency due to renderer destruction and recreation.
If you need to conserve memory, you'll want something lower than ``maxRendererPoolSizes``, possibly allocating more renderers to scale factors that are more common.
Default is ``[8, 4, 2]``.
``maxRendererPoolSizes``
------------------------
Maximum amount of raster tile renderers per scale factor.
The value and considerations are similar to ``minRendererPoolSizes`` above.
If you have plenty of memory, try setting these equal to or slightly above your processor count, e.g. if you have four processors, try a value of ``[6]``.
If you need to conserve memory, try lower values for scale factors that are less common.
Default is ``[16, 8, 4]``.
``watermark``
-----------
@@ -156,7 +173,7 @@ Sprites
If your style requires any sprites, make sure the style JSON contains proper path in the ``sprite`` property.
It can be a local path (e.g. ``my-style/sprite``) or remove http(s) location (e.g. ``https://mycdn.com/my-style/sprite``). Several possible extension are added to this path, so the following files should be present:
It can be a local path (e.g. ``my-style/sprite``) or remote http(s) location (e.g. ``https://mycdn.com/my-style/sprite``). Several possible extension are added to this path, so the following files should be present:
* ``sprite.json``
* ``sprite.png``

View File

@@ -21,6 +21,10 @@ Rendered tiles
* The rendered tiles are not available in the ``tileserver-gl-light`` version.
WMTS Capabilities
==============
* WMTS Capabilities are served at ``/styles/{id}/wmts.xml``
Static images
=============
* Several endpoints:
@@ -39,7 +43,7 @@ Static images
* ``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
* ``padding`` - "percetange" padding for fitted endpoints (area-based and path autofit)
* ``padding`` - "percentage" padding for fitted endpoints (area-based and path autofit)
* value of ``0.1`` means "add 10% size to each side to make sure the area of interest is nicely visible"

View File

@@ -11,7 +11,7 @@ Just run ``docker run --rm -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-
Additional options (see :doc:`/usage`) can be passed to the TileServer GL by appending them to the end of this command. You can, for example, do the following:
* ``docker run ... klokantech/tileserver-gl my-tiles.mbtiles`` -- explicitly specify which mbtiles to use (if you have more in the folder)
* ``docker run ... klokantech/tileserver-gl --mbtiles my-tiles.mbtiles`` -- explicitly specify which mbtiles to use (if you have more in the folder)
* ``docker run ... klokantech/tileserver-gl --verbose`` -- to see the default config created automatically
npm

View File

@@ -4,21 +4,22 @@ Usage
Getting started
======
::
Usage: tileserver-gl [mbtiles] [options]
Usage: main.js tileserver-gl [mbtiles] [options]
mbtiles MBTiles file (uses demo configuration);
ignored if the configuration file is also specified
Options:
-c, --config Configuration file [config.json]
-b, --bind Bind address
-p, --port Port [8080]
-V, --verbose More verbose output
-v, --version Version info
Options:
-h, --help output usage information
--mbtiles <file> MBTiles file (uses demo configuration);
ignored if the configuration file is also specified
-c, --config <file> Configuration file [config.json]
-b, --bind <address> Bind address
-p, --port <port> Port [8080]
-C|--no-cors Disable Cross-origin resource sharing headers
-V, --verbose More verbose output
-s, --silent Less verbose output
-v, --version Version info
Default styles and configuration

View File

@@ -1,6 +1,6 @@
{
"name": "tileserver-gl",
"version": "2.2.0",
"version": "2.6.0",
"description": "Map tile server for JSON GL styles - vector and server side generated raster tiles",
"main": "src/main.js",
"bin": "src/main.js",
@@ -16,35 +16,33 @@
"node": ">=6 <7"
},
"scripts": {
"test": "mocha test/**.js"
"test": "mocha test/**.js --timeout 10000"
},
"dependencies": {
"@mapbox/mapbox-gl-native": "3.5.4",
"@mapbox/mbtiles": "0.9.0",
"@mapbox/sphericalmercator": "1.0.5",
"@mapbox/vector-tile": "1.3.0",
"@mapbox/mapbox-gl-native": "4.0.0",
"@mapbox/mbtiles": "0.10.0",
"@mapbox/sphericalmercator": "1.1.0",
"@mapbox/vector-tile": "1.3.1",
"advanced-pool": "0.3.3",
"base64url": "2.0.0",
"canvas": "1.6.6",
"clone": "2.1.1",
"color": "1.0.3",
"cors": "2.8.4",
"express": "4.15.4",
"canvas": "1.6.13",
"clone": "2.1.2",
"color": "3.1.0",
"commander": "2.19.0",
"cors": "2.8.5",
"express": "4.16.4",
"glyph-pbf-composite": "0.0.2",
"handlebars": "4.0.10",
"handlebars": "4.1.2",
"http-shutdown": "^1.2.0",
"morgan": "1.8.2",
"node-pngquant-native": "1.0.5",
"nomnom": "1.8.1",
"pbf": "3.0.5",
"proj4": "2.4.4",
"request": "2.81.0",
"sharp": "0.18.2",
"morgan": "1.9.1",
"pbf": "3.1.0",
"proj4": "2.5.0",
"request": "2.88.0",
"sharp": "0.21.1",
"tileserver-gl-styles": "1.2.0"
},
"devDependencies": {
"should": "^11.2.0",
"mocha": "^3.2.0",
"supertest": "^3.0.0"
"mocha": "^5.2.0",
"should": "^13.2.0",
"supertest": "^3.1.0"
}
}

View File

@@ -28,7 +28,7 @@ a{
color: #499DCE;
transition: color .2s;
}
a:hover{
a:hover {
color: #395D73;
}
.title {
@@ -47,7 +47,7 @@ a:hover{
color: #499DCE;
font-size:.8em;
}
section{
section {
margin: 15px auto;
width: 930px;
padding: 30px 0;
@@ -70,7 +70,7 @@ section{
font-size:20px;
background:#fff;
}
.item{
.item {
background:#fff;
height: 191px;
border: 1px solid #ededed;
@@ -79,8 +79,9 @@ section{
.item:nth-child(odd) {
background-color:#fbfbfb;
}
.item img{
.item img {
position: absolute;
display: block;
margin: 30px;
width: 128px;
height: 128px;
@@ -122,10 +123,10 @@ section{
text-decoration: none;
font-weight: bold;
}
.btn:first-child:hover{
.btn:first-child:hover {
background: #395D73;
}
footer{
footer {
width:100%;
border-top:1px solid #ededed;
text-align:center;
@@ -133,7 +134,7 @@ footer{
padding-top:10px;
font-size:12px;
}
footer img{
footer img {
width: 118px;
height: 32px;
}
@@ -147,6 +148,10 @@ footer a {
color: #787878;
text-decoration: none;
}
.details h3, .identifier {
max-width: 550px;
word-break: break-all;
}
/* body background image */
body {
@@ -185,31 +190,31 @@ body {
.title.light:after {
font-size:.6em;
}
.title img{
.title img {
width: 200px;
}
.subtitle{
.subtitle {
font-size: 20px;
margin: 0 0 35px 0;
}
.item{
.item {
height: 245px;
}
.viewers{
.viewers {
float: left;
text-align: left;
width: 100%;
margin-left: 30px;
margin-top: 15px;
}
.viewers a{
.viewers a {
display: inline-block;
vertical-align: middle;
}
.btn{
.btn {
margin: 0 20px 0 0;
}
.btn:first-child{
.btn:first-child {
padding: 0 20px;
}
}

View File

@@ -4,6 +4,14 @@
position: relative;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.mapboxgl-map:-webkit-full-screen {
width: 100%;
height: 100%;
}
.mapboxgl-missing-css {
display: none;
}
.mapboxgl-canvas-container.mapboxgl-interactive,
.mapboxgl-ctrl-nav-compass {
@@ -90,11 +98,51 @@
.mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate {
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%23333%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-watching {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%2300f%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate:disabled {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%23aaa%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%2333b5e5%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active-error {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0D%0A%20%20%3Cpath%20style%3D%27fill%3A%23e58978%3B%27%20d%3D%27M10%204C9%204%209%205%209%205L9%205.1A5%205%200%200%200%205.1%209L5%209C5%209%204%209%204%2010%204%2011%205%2011%205%2011L5.1%2011A5%205%200%200%200%209%2014.9L9%2015C9%2015%209%2016%2010%2016%2011%2016%2011%2015%2011%2015L11%2014.9A5%205%200%200%200%2014.9%2011L15%2011C15%2011%2016%2011%2016%2010%2016%209%2015%209%2015%209L14.9%209A5%205%200%200%200%2011%205.1L11%205C11%205%2011%204%2010%204zM10%206.5A3.5%203.5%200%200%201%2013.5%2010%203.5%203.5%200%200%201%2010%2013.5%203.5%203.5%200%200%201%206.5%2010%203.5%203.5%200%200%201%2010%206.5zM10%208.3A1.8%201.8%200%200%200%208.3%2010%201.8%201.8%200%200%200%2010%2011.8%201.8%201.8%200%200%200%2011.8%2010%201.8%201.8%200%200%200%2010%208.3z%27%20%2F%3E%0D%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%2333b5e5%3B%27%20d%3D%27M%2010%2C4%20C%209%2C4%209%2C5%209%2C5%20L%209%2C5.1%20C%207.0357113%2C5.5006048%205.5006048%2C7.0357113%205.1%2C9%20L%205%2C9%20c%200%2C0%20-1%2C0%20-1%2C1%200%2C1%201%2C1%201%2C1%20l%200.1%2C0%20c%200.4006048%2C1.964289%201.9357113%2C3.499395%203.9%2C3.9%20L%209%2C15%20c%200%2C0%200%2C1%201%2C1%201%2C0%201%2C-1%201%2C-1%20l%200%2C-0.1%20c%201.964289%2C-0.400605%203.499395%2C-1.935711%203.9%2C-3.9%20l%200.1%2C0%20c%200%2C0%201%2C0%201%2C-1%20C%2016%2C9%2015%2C9%2015%2C9%20L%2014.9%2C9%20C%2014.499395%2C7.0357113%2012.964289%2C5.5006048%2011%2C5.1%20L%2011%2C5%20c%200%2C0%200%2C-1%20-1%2C-1%20z%20m%200%2C2.5%20c%201.932997%2C0%203.5%2C1.5670034%203.5%2C3.5%200%2C1.932997%20-1.567003%2C3.5%20-3.5%2C3.5%20C%208.0670034%2C13.5%206.5%2C11.932997%206.5%2C10%206.5%2C8.0670034%208.0670034%2C6.5%2010%2C6.5%20Z%27%20%2F%3E%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background-error {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23e54e33%3B%27%20d%3D%27M%2010%2C4%20C%209%2C4%209%2C5%209%2C5%20L%209%2C5.1%20C%207.0357113%2C5.5006048%205.5006048%2C7.0357113%205.1%2C9%20L%205%2C9%20c%200%2C0%20-1%2C0%20-1%2C1%200%2C1%201%2C1%201%2C1%20l%200.1%2C0%20c%200.4006048%2C1.964289%201.9357113%2C3.499395%203.9%2C3.9%20L%209%2C15%20c%200%2C0%200%2C1%201%2C1%201%2C0%201%2C-1%201%2C-1%20l%200%2C-0.1%20c%201.964289%2C-0.400605%203.499395%2C-1.935711%203.9%2C-3.9%20l%200.1%2C0%20c%200%2C0%201%2C0%201%2C-1%20C%2016%2C9%2015%2C9%2015%2C9%20L%2014.9%2C9%20C%2014.499395%2C7.0357113%2012.964289%2C5.5006048%2011%2C5.1%20L%2011%2C5%20c%200%2C0%200%2C-1%20-1%2C-1%20z%20m%200%2C2.5%20c%201.932997%2C0%203.5%2C1.5670034%203.5%2C3.5%200%2C1.932997%20-1.567003%2C3.5%20-3.5%2C3.5%20C%208.0670034%2C13.5%206.5%2C11.932997%206.5%2C10%206.5%2C8.0670034%208.0670034%2C6.5%2010%2C6.5%20Z%27%20%2F%3E%0A%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-waiting {
-webkit-animation: mapboxgl-spin 2s infinite linear;
-moz-animation: mapboxgl-spin 2s infinite linear;
-o-animation: mapboxgl-spin 2s infinite linear;
-ms-animation: mapboxgl-spin 2s infinite linear;
animation: mapboxgl-spin 2s infinite linear;
}
@-webkit-keyframes mapboxgl-spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@-moz-keyframes mapboxgl-spin {
0% { -moz-transform: rotate(0deg); }
100% { -moz-transform: rotate(360deg); }
}
@-o-keyframes mapboxgl-spin {
0% { -o-transform: rotate(0deg); }
100% { -o-transform: rotate(360deg); }
}
@-ms-keyframes mapboxgl-spin {
0% { -ms-transform: rotate(0deg); }
100% { -ms-transform: rotate(360deg); }
}
@keyframes mapboxgl-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-fullscreen {
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4KCjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0iTGF5ZXJfMSIKICAgeD0iMHB4IgogICB5PSIwcHgiCiAgIHZpZXdCb3g9IjAgMCAyMCAyMCIKICAgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjAgMjA7IgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkxIHIxMzcyNSIKICAgc29kaXBvZGk6ZG9jbmFtZT0iZnVsbHNjcmVlbi5zdmciPjxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTQxODUiPjxyZGY6UkRGPjxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj48ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD48ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+PGRjOnRpdGxlPjwvZGM6dGl0bGU+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzCiAgICAgaWQ9ImRlZnM0MTgzIiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMSIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTQ3MSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI2OTUiCiAgICAgaWQ9Im5hbWVkdmlldzQxODEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjExLjMxMzcwOCIKICAgICBpbmtzY2FwZTpjeD0iMTQuNjk4MjgiCiAgICAgaW5rc2NhcGU6Y3k9IjEwLjUyNjY4OSIKICAgICBpbmtzY2FwZTp3aW5kb3cteD0iNjk3IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIyOTgiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJMYXllcl8xIgogICAgIGlua3NjYXBlOnNuYXAtYmJveD0idHJ1ZSIKICAgICBpbmtzY2FwZTpiYm94LXBhdGhzPSJ0cnVlIgogICAgIGlua3NjYXBlOm9iamVjdC1wYXRocz0idHJ1ZSIKICAgICBpbmtzY2FwZTpiYm94LW5vZGVzPSJ0cnVlIgogICAgIGlua3NjYXBlOm9iamVjdC1ub2Rlcz0idHJ1ZSI+PGlua3NjYXBlOmdyaWQKICAgICAgIHR5cGU9Inh5Z3JpZCIKICAgICAgIGlkPSJncmlkNjA3NiIgLz48L3NvZGlwb2RpOm5hbWVkdmlldz48cGF0aAogICAgIGQ9Ik0gNSA0IEMgNC41IDQgNCA0LjUgNCA1IEwgNCA2IEwgNCA5IEwgNC41IDkgTCA1Ljc3NzM0MzggNy4yOTY4NzUgQyA2Ljc3NzEzMTkgOC4wNjAyMTMxIDcuODM1NzY1IDguOTU2NTcyOCA4Ljg5MDYyNSAxMCBDIDcuODI1NzEyMSAxMS4wNjMzIDYuNzc2MTc5MSAxMS45NTE2NzUgNS43ODEyNSAxMi43MDcwMzEgTCA0LjUgMTEgTCA0IDExIEwgNCAxNSBDIDQgMTUuNSA0LjUgMTYgNSAxNiBMIDkgMTYgTCA5IDE1LjUgTCA3LjI3MzQzNzUgMTQuMjA1MDc4IEMgOC4wNDI4OTMxIDEzLjE4Nzg4NiA4LjkzOTU0NDEgMTIuMTMzNDgxIDkuOTYwOTM3NSAxMS4wNjgzNTkgQyAxMS4wNDIzNzEgMTIuMTQ2OTkgMTEuOTQyMDkzIDEzLjIxMTIgMTIuNzA3MDMxIDE0LjIxODc1IEwgMTEgMTUuNSBMIDExIDE2IEwgMTQgMTYgTCAxNSAxNiBDIDE1LjUgMTYgMTYgMTUuNSAxNiAxNSBMIDE2IDE0IEwgMTYgMTEgTCAxNS41IDExIEwgMTQuMjA1MDc4IDEyLjcyNjU2MiBDIDEzLjE3Nzk4NSAxMS45NDk2MTcgMTIuMTEyNzE4IDExLjA0MzU3NyAxMS4wMzcxMDkgMTAuMDA5NzY2IEMgMTIuMTUxODU2IDguOTgxMDYxIDEzLjIyNDM0NSA4LjA3OTg2MjQgMTQuMjI4NTE2IDcuMzA0Njg3NSBMIDE1LjUgOSBMIDE2IDkgTCAxNiA1IEMgMTYgNC41IDE1LjUgNCAxNSA0IEwgMTEgNCBMIDExIDQuNSBMIDEyLjcwMzEyNSA1Ljc3NzM0MzggQyAxMS45MzI2NDcgNi43ODY0ODM0IDExLjAyNjY5MyA3Ljg1NTQ3MTIgOS45NzA3MDMxIDguOTE5OTIxOSBDIDguOTU4NDczOSA3LjgyMDQ5NDMgOC4wNjk4NzY3IDYuNzYyNzE4OCA3LjMwNDY4NzUgNS43NzE0ODQ0IEwgOSA0LjUgTCA5IDQgTCA2IDQgTCA1IDQgeiAiCiAgICAgaWQ9InBhdGg0MTY5IiAvPjwvc3ZnPg==");
@@ -175,6 +223,7 @@ a.mapboxgl-ctrl-logo {
border-color: #333;
padding: 0 5px;
color: #333;
box-sizing: border-box;
}
.mapboxgl-popup {
@@ -304,6 +353,65 @@ a.mapboxgl-ctrl-logo {
will-change: transform;
}
.mapboxgl-user-location-dot {
background-color: #1DA1F2;
width: 16px;
height: 16px;
border-radius: 50%;
box-shadow: 0 0 2px rgba(0,0,0,0.25);
border: 2px solid #fff;
}
.mapboxgl-user-location-dot:after {
content: '';
display: block;
box-shadow: #1DA1F2 0 0 0 2px;
width: 16px;
height: 16px;
border-radius: 50%;
position: relative;
z-index: -1;
-webkit-animation: mapboxgl-user-location-dot-pulse 2s;
-moz-animation: mapboxgl-user-location-dot-pulse 2s;
-ms-animation: mapboxgl-user-location-dot-pulse 2s;
animation: mapboxgl-user-location-dot-pulse 2s;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
@-webkit-keyframes mapboxgl-user-location-dot-pulse {
0% { -webkit-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0.8); }
70% { -webkit-box-shadow: 0 0 0 15px rgba(29, 161, 242, 0); }
242% { -webkit-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0); }
}
@-ms-keyframes mapboxgl-user-location-dot-pulse {
0% { -ms-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0.8); }
70% { -ms-box-shadow: 0 0 0 15px rgba(29, 161, 242, 0); }
242% { -ms-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0); }
}
@keyframes mapboxgl-user-location-dot-pulse {
0% {
-moz-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0.8);
box-shadow: 0 0 0 0 rgba(29, 161, 242, 0.4);
}
70% {
-moz-box-shadow: 0 0 0 15px rgba(29, 161, 242, 0);
box-shadow: 0 0 0 15px rgba(29, 161, 242, 0);
}
100% {
-moz-box-shadow: 0 0 0 0 rgba(29, 161, 242, 0);
box-shadow: 0 0 0 0 rgba(29, 161, 242, 0);
}
}
.mapboxgl-user-location-dot-stale {
background-color: #aaa;
}
.mapboxgl-user-location-dot-stale:after {
display: none
}
.mapboxgl-crosshair,
.mapboxgl-crosshair .mapboxgl-interactive,
.mapboxgl-crosshair .mapboxgl-interactive:active {

File diff suppressed because one or more lines are too long

View File

@@ -5,10 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{name}} - TileServer GL</title>
{{#is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<link rel="stylesheet" type="text/css" href="/mapbox-gl-inspect.css{{&key_query}}" />
<script src="/mapbox-gl.js{{&key_query}}"></script>
<script src="/mapbox-gl-inspect.min.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="{{public_url}}mapbox-gl.css{{&key_query}}" />
<link rel="stylesheet" type="text/css" href="{{public_url}}mapbox-gl-inspect.css{{&key_query}}" />
<script src="{{public_url}}mapbox-gl.js{{&key_query}}"></script>
<script src="{{public_url}}mapbox-gl-inspect.min.js{{&key_query}}"></script>
<style>
body {background:#fff;color:#333;font-family:Arial, sans-serif;}
#map {position:absolute;top:0;left:0;right:250px;bottom:0;}
@@ -18,9 +18,9 @@
</style>
{{/is_vector}}
{{^is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="{{public_url}}mapbox.css{{&key_query}}" />
<script src="{{public_url}}mapbox.js{{&key_query}}"></script>
<script src="{{public_url}}leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@@ -42,7 +42,7 @@
sources: {
'vector_layer_': {
type: 'vector',
url: '/data/{{id}}.json{{&key_query}}'
url: '{{public_url}}data/{{id}}.json{{&key_query}}'
}
},
layers: []
@@ -74,7 +74,7 @@
<h1 style="display:none;">{{name}}</h1>
<div id='map'></div>
<script>
var map = L.mapbox.map('map', '/data/{{id}}.json{{&key_query}}', { zoomControl: false });
var map = L.mapbox.map('map', '{{public_url}}data/{{id}}.json{{&key_query}}', { zoomControl: false });
map.eachLayer(function(layer) {
// do not add scale prefix even if retina display is detected
layer.scalePrefix = '.';

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TileServer GL - Server for vector and raster maps with GL styles</title>
<link rel="stylesheet" type="text/css" href="/index.css{{&key_query}}" />
<link rel="stylesheet" type="text/css" href="{{public_url}}index.css{{&key_query}}" />
<script>
function toggle_xyz(id) {
var el = document.getElementById(id);
@@ -17,7 +17,7 @@
</head>
<body>
<section>
<h1 class="title {{#if is_light}}light{{/if}}"><img src="/images/logo.png" alt="TileServer GL" /></h1>
<h1 class="title {{#if is_light}}light{{/if}}"><img src="{{public_url}}images/logo.png" alt="TileServer GL" /></h1>
<h2 class="subtitle">Vector {{#if is_light}}<s>and raster</s>{{else}}and raster{{/if}} maps with GL styles</h2>
{{#if styles}}
<h2 class="box-header">Styles</h2>
@@ -25,9 +25,9 @@
{{#each styles}}
<div class="item">
{{#if thumbnail}}
<img src="/styles/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
<img src="{{public_url}}styles/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}}
<img src="/images/placeholder.png" alt="{{name}} preview" />
<img src="{{public_url}}images/placeholder.png" alt="{{name}} preview" />
{{/if}}
<div class="details">
<h3>{{name}}</h3>
@@ -35,13 +35,13 @@
<p class="services">
services:
{{#if serving_data}}
<a href="/styles/{{@key}}/style.json{{&../key_query}}">GL Style</a>
<a href="{{public_url}}styles/{{@key}}/style.json{{&../key_query}}">GL Style</a>
{{/if}}
{{#if serving_rendered}}
{{#if serving_data}}| {{/if}}<a href="/styles/{{@key}}.json{{&../key_query}}">TileJSON</a>
{{#if serving_data}}| {{/if}}<a href="{{public_url}}styles/{{@key}}.json{{&../key_query}}">TileJSON</a>
{{/if}}
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS</a>
{{#if serving_rendered}}
| <a href="/styles/{{@key}}/wmts.xml{{&../key_query}}">WMTS</a>
{{/if}}
{{#if xyz_link}}
| <a href="#" onclick="return toggle_xyz('xyz_style_{{@key}}');">XYZ</a>
@@ -52,14 +52,14 @@
<div class="viewers">
{{#if serving_data}}
{{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/{{&../key_query}}{{viewer_hash}}">Viewer</a>
<a class="btn" href="{{public_url}}styles/{{@key}}/{{&../key_query}}{{viewer_hash}}">Viewer</a>
{{/if}}
{{/if}}
{{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}raster{{viewer_hash}}">Raster</a>
<a class="btn" href="{{public_url}}styles/{{@key}}/?{{&../key_query_part}}raster{{viewer_hash}}">Raster</a>
{{/if}}
{{#if serving_data}}
<a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}vector{{viewer_hash}}">Vector</a>
<a class="btn" href="{{public_url}}styles/{{@key}}/?{{&../key_query_part}}vector{{viewer_hash}}">Vector</a>
{{/if}}
</div>
</div>
@@ -72,15 +72,15 @@
{{#each data}}
<div class="item">
{{#if thumbnail}}
<img src="/data/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
<img src="{{public_url}}data/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}}
<img src="/images/placeholder.png" alt="{{name}} preview" />
<img src="{{public_url}}images/placeholder.png" alt="{{name}} preview" />
{{/if}}
<div class="details">
<h3>{{name}}</h3>
<p class="identifier">identifier: {{@key}}{{#if formatted_filesize}} | size: {{formatted_filesize}}{{/if}} | type: {{#is_vector}}vector{{/is_vector}}{{^is_vector}}raster{{/is_vector}} data</p>
<p class="services">
services: <a href="/data/{{@key}}.json{{&../key_query}}">TileJSON</a>
services: <a href="{{public_url}}data/{{@key}}.json{{&../key_query}}">TileJSON</a>
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS</a>
{{/if}}
@@ -92,10 +92,10 @@
</div>
<div class="viewers">
{{#is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Inspect</a>
<a class="btn" href="{{public_url}}data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Inspect</a>
{{/is_vector}}
{{^is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">View</a>
<a class="btn" href="{{public_url}}data/{{@key}}/{{&../key_query}}{{viewer_hash}}">View</a>
{{/is_vector}}
</div>
</div>
@@ -104,10 +104,10 @@
{{/if}}
</section>
<footer>
<a href="https://www.klokantech.com/" target="_blank"><img src="/images/klokantech.png" /></a>
<a href="https://www.klokantech.com/" target="_blank"><img src="{{public_url}}images/klokantech.png" /></a>
<p>
<a href="https://github.com/klokantech/tileserver-gl" target="_blank">Powered by TileServer GL ({{server_version}})</a> <a href="https://www.klokantech.com/" target="_blank">an open-source project from Klokan Technologies GmbH.</a> <img src="https://t.klokantech.com/8073932/19" class="t" />
</p>
</footer>
</body>
</html>
</html>

View File

@@ -4,11 +4,11 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{name}} - TileServer GL</title>
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<script src="/mapbox-gl.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="{{public_url}}mapbox-gl.css{{&key_query}}" />
<script src="{{public_url}}mapbox-gl.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="{{public_url}}mapbox.css{{&key_query}}" />
<script src="{{public_url}}mapbox.js{{&key_query}}"></script>
<script src="{{public_url}}leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@@ -24,15 +24,15 @@
(q.indexOf('raster') >= 0 ? 'raster' :
(mapboxgl.supported() ? 'vector' : 'raster'));
if (preference == 'vector') {
mapboxgl.setRTLTextPlugin('/mapbox-gl-rtl-text.js{{&key_query}}');
mapboxgl.setRTLTextPlugin('{{public_url}}mapbox-gl-rtl-text.js{{&key_query}}');
var map = new mapboxgl.Map({
container: 'map',
style: '/styles/{{id}}/style.json{{&key_query}}',
style: '{{public_url}}styles/{{id}}/style.json{{&key_query}}',
hash: true
});
map.addControl(new mapboxgl.NavigationControl());
} else {
var map = L.mapbox.map('map', '/styles/{{id}}.json{{&key_query}}', { zoomControl: false });
var map = L.mapbox.map('map', '{{public_url}}styles/{{id}}.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() {
new L.Hash(map);

407
public/templates/wmts.tmpl Normal file
View File

@@ -0,0 +1,407 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0">
<!-- Service Identification -->
<ows:ServiceIdentification>
<ows:Title>TileServer GL</ows:Title>
<ows:ServiceType>OGC WMTS</ows:ServiceType>
<ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
</ows:ServiceIdentification>
<!-- Operations Metadata -->
<ows:OperationsMetadata>
<ows:Operation name="GetCapabilities">
<ows:DCP>
<ows:HTTP>
<ows:Get xlink:href="{{baseUrl}}/wmts/{{id}}/">
<ows:Constraint name="GetEncoding">
<ows:AllowedValues>
<ows:Value>RESTful</ows:Value>
</ows:AllowedValues>
</ows:Constraint>
</ows:Get>
</ows:HTTP>
</ows:DCP>
</ows:Operation>
<ows:Operation name="GetTile">
<ows:DCP>
<ows:HTTP>
<ows:Get xlink:href="{{baseUrl}}/styles/">
<ows:Constraint name="GetEncoding">
<ows:AllowedValues>
<ows:Value>RESTful</ows:Value>
</ows:AllowedValues>
</ows:Constraint>
</ows:Get>
</ows:HTTP>
</ows:DCP>
</ows:Operation>
</ows:OperationsMetadata>
<Contents>
<Layer>
<ows:Title>{{name}}</ows:Title>
<ows:Identifier>{{id}}</ows:Identifier>
<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">
<ows:LowerCorner>-180 -85.051128779807</ows:LowerCorner>
<ows:UpperCorner>180 85.051128779807</ows:UpperCorner>
</ows:WGS84BoundingBox>
<Style isDefault="true">
<ows:Identifier>default</ows:Identifier>
</Style>
<Format>image/png</Format>
<TileMatrixSetLink>
<TileMatrixSet>GoogleMapsCompatible</TileMatrixSet>
</TileMatrixSetLink>
<ResourceURL format="image/png" resourceType="tile" template="{{baseUrl}}/styles/{{id}}/{TileMatrix}/{TileCol}/{TileRow}.png{{key_query}}"/>
</Layer><TileMatrixSet>
<ows:Title>GoogleMapsCompatible</ows:Title>
<ows:Abstract>GoogleMapsCompatible EPSG:3857</ows:Abstract>
<ows:Identifier>GoogleMapsCompatible</ows:Identifier>
<ows:SupportedCRS>urn:ogc:def:crs:EPSG::3857</ows:SupportedCRS>
<TileMatrix>
<ows:Identifier>0</ows:Identifier>
<ScaleDenominator>559082264.02872</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1</MatrixWidth>
<MatrixHeight>1</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>1</ows:Identifier>
<ScaleDenominator>279541132.01436</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2</MatrixWidth>
<MatrixHeight>2</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>2</ows:Identifier>
<ScaleDenominator>139770566.00718</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>4</MatrixWidth>
<MatrixHeight>4</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>3</ows:Identifier>
<ScaleDenominator>69885283.00359</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>8</MatrixWidth>
<MatrixHeight>8</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>4</ows:Identifier>
<ScaleDenominator>34942641.501795</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>16</MatrixWidth>
<MatrixHeight>16</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>5</ows:Identifier>
<ScaleDenominator>17471320.750897</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>32</MatrixWidth>
<MatrixHeight>32</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>6</ows:Identifier>
<ScaleDenominator>8735660.3754487</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>64</MatrixWidth>
<MatrixHeight>64</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>7</ows:Identifier>
<ScaleDenominator>4367830.1877244</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>128</MatrixWidth>
<MatrixHeight>128</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>8</ows:Identifier>
<ScaleDenominator>2183915.0938622</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>256</MatrixWidth>
<MatrixHeight>256</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>9</ows:Identifier>
<ScaleDenominator>1091957.5469311</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>512</MatrixWidth>
<MatrixHeight>512</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>10</ows:Identifier>
<ScaleDenominator>545978.77346554</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1024</MatrixWidth>
<MatrixHeight>1024</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>11</ows:Identifier>
<ScaleDenominator>272989.38673277</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2048</MatrixWidth>
<MatrixHeight>2048</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>12</ows:Identifier>
<ScaleDenominator>136494.69336639</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>4096</MatrixWidth>
<MatrixHeight>4096</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>13</ows:Identifier>
<ScaleDenominator>68247.346683193</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>8192</MatrixWidth>
<MatrixHeight>8192</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>14</ows:Identifier>
<ScaleDenominator>34123.673341597</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>16384</MatrixWidth>
<MatrixHeight>16384</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>15</ows:Identifier>
<ScaleDenominator>17061.836670798</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>32768</MatrixWidth>
<MatrixHeight>32768</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>16</ows:Identifier>
<ScaleDenominator>8530.9183353991</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>65536</MatrixWidth>
<MatrixHeight>65536</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>17</ows:Identifier>
<ScaleDenominator>4265.4591676996</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>131072</MatrixWidth>
<MatrixHeight>131072</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>18</ows:Identifier>
<ScaleDenominator>2132.7295838498</ScaleDenominator>
<TopLeftCorner>-20037508.34 20037508.34</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>262144</MatrixWidth>
<MatrixHeight>262144</MatrixHeight>
</TileMatrix></TileMatrixSet><TileMatrixSet>
<ows:Title>WGS84</ows:Title>
<ows:Abstract>WGS84 EPSG:4326</ows:Abstract>
<ows:Identifier>WGS84</ows:Identifier>
<ows:SupportedCRS>urn:ogc:def:crs:EPSG::4326</ows:SupportedCRS>
<TileMatrix>
<ows:Identifier>0</ows:Identifier>
<ScaleDenominator>279541132.01436</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2</MatrixWidth>
<MatrixHeight>1</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>1</ows:Identifier>
<ScaleDenominator>139770566.00718</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>4</MatrixWidth>
<MatrixHeight>2</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>2</ows:Identifier>
<ScaleDenominator>69885283.00359</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>8</MatrixWidth>
<MatrixHeight>4</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>3</ows:Identifier>
<ScaleDenominator>34942641.501795</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>16</MatrixWidth>
<MatrixHeight>8</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>4</ows:Identifier>
<ScaleDenominator>17471320.750897</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>32</MatrixWidth>
<MatrixHeight>16</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>5</ows:Identifier>
<ScaleDenominator>8735660.3754487</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>64</MatrixWidth>
<MatrixHeight>32</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>6</ows:Identifier>
<ScaleDenominator>4367830.1877244</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>128</MatrixWidth>
<MatrixHeight>64</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>7</ows:Identifier>
<ScaleDenominator>2183915.0938622</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>256</MatrixWidth>
<MatrixHeight>128</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>8</ows:Identifier>
<ScaleDenominator>1091957.5469311</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>512</MatrixWidth>
<MatrixHeight>256</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>9</ows:Identifier>
<ScaleDenominator>545978.77346554</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>1024</MatrixWidth>
<MatrixHeight>512</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>10</ows:Identifier>
<ScaleDenominator>272989.38673277</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>2048</MatrixWidth>
<MatrixHeight>1024</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>11</ows:Identifier>
<ScaleDenominator>136494.69336639</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>4096</MatrixWidth>
<MatrixHeight>2048</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>12</ows:Identifier>
<ScaleDenominator>68247.346683193</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>8192</MatrixWidth>
<MatrixHeight>4096</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>13</ows:Identifier>
<ScaleDenominator>34123.673341597</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>16384</MatrixWidth>
<MatrixHeight>8192</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>14</ows:Identifier>
<ScaleDenominator>17061.836670798</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>32768</MatrixWidth>
<MatrixHeight>16384</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>15</ows:Identifier>
<ScaleDenominator>8530.9183353991</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>65536</MatrixWidth>
<MatrixHeight>32768</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>16</ows:Identifier>
<ScaleDenominator>4265.4591676996</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>131072</MatrixWidth>
<MatrixHeight>65536</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>17</ows:Identifier>
<ScaleDenominator>2132.7295838498</ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>262144</MatrixWidth>
<MatrixHeight>131072</MatrixHeight>
</TileMatrix>
<TileMatrix>
<ows:Identifier>18</ows:Identifier>
<ScaleDenominator></ScaleDenominator>
<TopLeftCorner>90 -180</TopLeftCorner>
<TileWidth>256</TileWidth>
<TileHeight>256</TileHeight>
<MatrixWidth>524288</MatrixWidth>
<MatrixHeight>262144</MatrixHeight>
</TileMatrix></TileMatrixSet>
</Contents>
<ServiceMetadataURL xlink:href="{{baseUrl}}/wmts/{{id}}/"/>
</Capabilities>

View File

@@ -23,7 +23,6 @@ packageJson.name += '-light';
packageJson.description = 'Map tile server for JSON GL styles - serving vector tiles';
delete packageJson.dependencies['canvas'];
delete packageJson.dependencies['@mapbox/mapbox-gl-native'];
delete packageJson.dependencies['node-pngquant-native'];
delete packageJson.dependencies['sharp'];
delete packageJson.optionalDependencies;

37
run.sh
View File

@@ -1,8 +1,37 @@
#!/bin/bash
start-stop-daemon --start --pidfile ~/xvfb.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset
sleep 1
export DISPLAY=:99.0
_term() {
echo "Caught signal, stopping gracefully"
kill -TERM "$child" 2>/dev/null
}
trap _term SIGTERM
trap _term SIGINT
xvfbMaxStartWaitTime=5
displayNumber=99
screenNumber=0
# Delete files if they were not cleaned by last run
rm -rf /tmp/.X11-unix /tmp/.X${displayNumber}-lock ~/xvfb.pid
echo "Starting Xvfb on display ${displayNumber}"
start-stop-daemon --start --pidfile ~/xvfb.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :${displayNumber} -screen ${screenNumber} 1024x768x24 -ac +extension GLX +render -noreset
# Wait to be able to connect to the port. This will exit if it cannot in 15 minutes.
timeout ${xvfbMaxStartWaitTime} bash -c "while ! xdpyinfo -display :${displayNumber} >/dev/null; do sleep 0.5; done"
if [ $? -ne 0 ]; then
echo "Could not connect to display ${displayNumber} in ${xvfbMaxStartWaitTime} seconds time."
exit 1
fi
export DISPLAY=:${displayNumber}.${screenNumber}
echo
cd /data
node /usr/src/app/ -p 80 "$@"
node /usr/src/app/ -p 80 "$@" &
child=$!
wait "$child"
start-stop-daemon --stop --retry 5 --pidfile ~/xvfb.pid # stop xvfb when exiting
rm ~/xvfb.pid

View File

@@ -10,56 +10,82 @@ var mbtiles = require('@mapbox/mbtiles');
var packageJson = require('../package');
var opts = require('nomnom')
.option('mbtiles', {
default: undefined,
help: 'MBTiles file (uses demo configuration);\n' +
'\t ignored if the configuration file is also specified',
position: 0
})
.option('config', {
abbr: 'c',
default: 'config.json',
help: 'Configuration file'
})
.option('bind', {
abbr: 'b',
default: undefined,
help: 'Bind address'
})
.option('port', {
abbr: 'p',
default: 8080,
help: 'Port'
})
.option('cors', {
default: true,
help: 'Enable Cross-origin resource sharing headers'
})
.option('verbose', {
abbr: 'V',
flag: true,
help: 'More verbose output'
})
.option('version', {
abbr: 'v',
flag: true,
help: 'Version info',
callback: function() {
return packageJson.name + ' v' + packageJson.version;
}
}).parse();
var args = process.argv;
if (args.length >= 3 && args[2][0] != '-') {
args.splice(2, 0, '--mbtiles');
}
var opts = require('commander')
.description('tileserver-gl startup options')
.usage('tileserver-gl [mbtiles] [options]')
.option(
'--mbtiles <file>',
'MBTiles file (uses demo configuration);\n' +
'\t ignored if the configuration file is also specified'
)
.option(
'-c, --config <file>',
'Configuration file [config.json]',
'config.json'
)
.option(
'-b, --bind <address>',
'Bind address'
)
.option(
'-p, --port <port>',
'Port [8080]',
8080,
parseInt
)
.option(
'-C|--no-cors',
'Disable Cross-origin resource sharing headers'
)
.option(
'-u|--public_url <url>',
'Enable exposing the server on subpaths, not necessarily the root of the domain'
)
.option(
'-V, --verbose',
'More verbose output'
)
.option(
'-s, --silent',
'Less verbose output'
)
.option(
'-l|--log_file <file>',
'output log file (defaults to standard out)'
)
.option(
'-f|--log_format <format>',
'define the log format: https://github.com/expressjs/morgan#morganformat-options'
)
.version(
packageJson.version,
'-v, --version'
)
.parse(args);
console.log('Starting ' + packageJson.name + ' v' + packageJson.version);
var startServer = function(configPath, config) {
var publicUrl = opts.public_url;
if (publicUrl && publicUrl.lastIndexOf('/') !== publicUrl.length - 1) {
publicUrl += '/';
}
return require('./server')({
configPath: configPath,
config: config,
bind: opts.bind,
port: opts.port,
cors: opts.cors
cors: opts.cors,
verbose: opts.verbose,
silent: opts.silent,
logFile: opts.log_file,
logFormat: opts.log_format,
publicUrl: publicUrl
});
};

View File

@@ -18,7 +18,7 @@ try {
var utils = require('./utils');
module.exports = function(options, repo, params, id, styles) {
module.exports = function(options, repo, params, id, styles, publicUrl) {
var app = express().disable('x-powered-by');
var mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles);
@@ -37,7 +37,15 @@ module.exports = function(options, repo, params, id, styles) {
var source;
var sourceInfoPromise = new Promise(function(resolve, reject) {
source = new mbtiles(mbtilesFile, function(err) {
if (err) {
reject(err);
return;
}
source.getInfo(function(err, info) {
if (err) {
reject(err);
return;
}
tileJSON['name'] = id;
tileJSON['format'] = 'pbf';
@@ -81,7 +89,7 @@ module.exports = function(options, repo, params, id, styles) {
source.getTile(z, x, y, function(err, data, headers) {
if (err) {
if (/does not exist/.test(err.message)) {
return res.status(404).send(err.message);
return res.status(204).send();
} else {
return res.status(500).send(err.message);
}
@@ -170,15 +178,13 @@ module.exports = function(options, repo, params, id, styles) {
app.get('/' + id + '.json', function(req, res, next) {
var info = clone(tileJSON);
info.tiles = utils.getTileUrls(req, info.tiles,
'data/' + id, info.format, {
'data/' + id, info.format, publicUrl, {
'pbf': options.pbfAlias
});
return res.send(info);
});
return new Promise(function(resolve, reject) {
sourceInfoPromise.then(function() {
resolve(app);
});
return sourceInfoPromise.then(function() {
return app;
});
};

View File

@@ -17,13 +17,19 @@ module.exports = function(options, allowedFonts) {
var existingFonts = {};
var fontListingPromise = new Promise(function(resolve, reject) {
fs.readdir(options.paths.fonts, function(err, files) {
if (err) {
reject(err);
return;
}
files.forEach(function(file) {
fs.stat(path.join(fontPath, file), function(err, stats) {
if (!err) {
if (stats.isDirectory() &&
fs.existsSync(path.join(fontPath, file, '0-255.pbf'))) {
existingFonts[path.basename(file)] = true;
}
if (err) {
reject(err);
return;
}
if (stats.isDirectory() &&
fs.existsSync(path.join(fontPath, file, '0-255.pbf'))) {
existingFonts[path.basename(file)] = true;
}
});
});
@@ -54,9 +60,7 @@ module.exports = function(options, allowedFonts) {
);
});
return new Promise(function(resolve, reject) {
fontListingPromise.then(function() {
resolve(app);
});
return fontListingPromise.then(function() {
return app;
});
};

View File

@@ -18,7 +18,6 @@ var Canvas = require('canvas'),
mercator = new (require('@mapbox/sphericalmercator'))(),
mbgl = require('@mapbox/mapbox-gl-native'),
mbtiles = require('@mapbox/mbtiles'),
pngquant = require('node-pngquant-native'),
proj4 = require('proj4'),
request = require('request');
@@ -98,7 +97,7 @@ function createEmptyResponse(format, color, callback) {
});
}
module.exports = function(options, repo, params, id, dataResolver) {
module.exports = function(options, repo, params, id, publicUrl, dataResolver) {
var app = express().disable('x-powered-by');
var maxScaleFactor = Math.min(Math.floor(options.maxScaleFactor || 3), 9);
@@ -123,12 +122,18 @@ module.exports = function(options, repo, params, id, dataResolver) {
var existingFonts = {};
var fontListingPromise = new Promise(function(resolve, reject) {
fs.readdir(options.paths.fonts, function(err, files) {
if (err) {
reject(err);
return;
}
files.forEach(function(file) {
fs.stat(path.join(options.paths.fonts, file), function(err, stats) {
if (!err) {
if (stats.isDirectory()) {
existingFonts[path.basename(file)] = true;
}
if (err) {
reject(err);
return;
}
if (stats.isDirectory()) {
existingFonts[path.basename(file)] = true;
}
});
});
@@ -165,14 +170,15 @@ module.exports = function(options, repo, params, id, dataResolver) {
var parts = req.url.split('/');
var sourceId = parts[2];
var source = map.sources[sourceId];
var sourceInfo = styleJSON.sources[sourceId];
var z = parts[3] | 0,
x = parts[4] | 0,
y = parts[5].split('.')[0] | 0,
format = parts[5].split('.')[1];
source.getTile(z, x, y, function(err, data, headers) {
if (err) {
//console.log('MBTiles error, serving empty', err);
createEmptyResponse(source.format, source.color, callback);
if (options.verbose) console.log('MBTiles error, serving empty', err);
createEmptyResponse(sourceInfo.format, sourceInfo.color, callback);
return;
}
@@ -182,7 +188,12 @@ module.exports = function(options, repo, params, id, dataResolver) {
}
if (format == 'pbf') {
response.data = zlib.unzipSync(data);
try {
response.data = zlib.unzipSync(data);
}
catch (err) {
console.log("Skipping incorrect header for tile mbtiles://%s/%s/%s/%s.pbf", id, z, x, y);
}
if (options.dataDecoratorFunc) {
response.data = options.dataDecoratorFunc(
sourceId, 'data', response.data, z, x, y);
@@ -252,6 +263,18 @@ module.exports = function(options, repo, params, id, dataResolver) {
styleJSON.glyphs = 'fonts://' + styleJSON.glyphs;
}
(styleJSON.layers || []).forEach(function(layer) {
if (layer && layer.paint) {
// Remove (flatten) 3D buildings
if (layer.paint['fill-extrusion-height']) {
layer.paint['fill-extrusion-height'] = 0;
}
if (layer.paint['fill-extrusion-base']) {
layer.paint['fill-extrusion-base'] = 0;
}
}
});
var tileJSON = {
'tilejson': '2.0.0',
'name': styleJSON.name,
@@ -345,18 +368,15 @@ module.exports = function(options, repo, params, id, dataResolver) {
});
var renderersReadyPromise = Promise.all(queue).then(function() {
// TODO: make pool sizes configurable
// standard and @2x tiles are much more usual -> default to larger pools
var minPoolSizes = options.minRendererPoolSizes || [8, 4, 2];
var maxPoolSizes = options.maxRendererPoolSizes || [16, 8, 4];
for (var s = 1; s <= maxScaleFactor; s++) {
var minPoolSize = 2;
// standard and @2x tiles are much more usual -> create larger pools
if (s <= 2) {
minPoolSize *= 2;
if (s <= 1) {
minPoolSize *= 2;
}
}
map.renderers[s] = createPool(s, minPoolSize, 2 * minPoolSize);
var i = Math.min(minPoolSizes.length - 1, s - 1);
var j = Math.min(maxPoolSizes.length - 1, s - 1);
var minPoolSize = minPoolSizes[i];
var maxPoolSize = Math.max(minPoolSize, maxPoolSizes[j]);
map.renderers[s] = createPool(s, minPoolSize, maxPoolSize);
}
});
@@ -451,16 +471,6 @@ module.exports = function(options, repo, params, id, dataResolver) {
return res.status(404).send('Not found');
}
if (format == 'png') {
var usePngQuant =
(options.formatQuality || {}).pngQuantization === true;
if (usePngQuant) {
buffer = pngquant.compress(buffer, {
quality: [0, formatQuality || 90]
});
}
}
res.set({
'Last-Modified': lastModified,
'Content-Type': 'image/' + format
@@ -749,13 +759,12 @@ module.exports = function(options, repo, params, id, dataResolver) {
app.get('/' + id + '.json', function(req, res, next) {
var info = clone(tileJSON);
info.tiles = utils.getTileUrls(req, info.tiles,
'styles/' + id, info.format);
'styles/' + id, info.format, publicUrl);
return res.send(info);
});
return new Promise(function(resolve, reject) {
Promise.all([fontListingPromise, renderersReadyPromise]).then(function() {
resolve(app);
});
return Promise.all([fontListingPromise, renderersReadyPromise]).then(function() {
return app;
});
};

View File

@@ -6,8 +6,9 @@ var path = require('path'),
var clone = require('clone'),
express = require('express');
var utils = require('./utils');
module.exports = function(options, repo, params, id, reportTiles, reportFont) {
module.exports = function(options, repo, params, id, publicUrl, reportTiles, reportFont) {
var app = express().disable('x-powered-by');
var styleFile = path.resolve(options.paths.styles, params.style);
@@ -79,7 +80,7 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
query = '?' + queryParams.join('&');
}
return url.replace(
'local://', req.protocol + '://' + req.headers.host + '/') + query;
'local://', utils.getPublicUrl(publicUrl, req)) + query;
};
var styleJSON_ = clone(styleJSON);

View File

@@ -7,8 +7,7 @@ process.env.UV_THREADPOOL_SIZE =
var fs = require('fs'),
path = require('path');
var base64url = require('base64url'),
clone = require('clone'),
var clone = require('clone'),
cors = require('cors'),
enableShutdown = require('http-shutdown'),
express = require('express'),
@@ -42,10 +41,13 @@ function start(opts) {
app.enable('trust proxy');
if (process.env.NODE_ENV == 'production') {
app.use(morgan('tiny'));
} else if (process.env.NODE_ENV !== 'test') {
app.use(morgan('dev'));
if (process.env.NODE_ENV !== 'test') {
var defaultLogFormat = process.env.NODE_ENV == 'production' ? 'tiny' : 'dev';
var logFormat = opts.logFormat || defaultLogFormat;
app.use(morgan(logFormat, {
stream: opts.logFile ? fs.createWriteStream(opts.logFile, { flags: 'a' }) : process.stdout,
skip: function(req, res) { return opts.silent && (res.statusCode == 200 || res.statusCode == 304) }
}));
}
var config = opts.config || null;
@@ -109,7 +111,7 @@ function start(opts) {
}
if (item.serve_data !== false) {
startupPromises.push(serve_style(options, serving.styles, item, id,
startupPromises.push(serve_style(options, serving.styles, item, id, opts.publicUrl,
function(mbtiles, fromData) {
var dataItemId;
Object.keys(data).forEach(function(id) {
@@ -145,7 +147,7 @@ function start(opts) {
if (item.serve_rendered !== false) {
if (serve_rendered) {
startupPromises.push(
serve_rendered(options, serving.rendered, item, id,
serve_rendered(options, serving.rendered, item, id, opts.publicUrl,
function(mbtiles) {
var mbtilesFile;
Object.keys(data).forEach(function(id) {
@@ -179,7 +181,7 @@ function start(opts) {
}
startupPromises.push(
serve_data(options, serving.data, item, id, serving.styles).then(function(sub) {
serve_data(options, serving.data, item, id, serving.styles, opts.publicUrl).then(function(sub) {
app.use('/data/', sub);
})
);
@@ -194,8 +196,8 @@ function start(opts) {
version: styleJSON.version,
name: styleJSON.name,
id: id,
url: req.protocol + '://' + req.headers.host +
'/styles/' + id + '/style.json' + query
url: utils.getPublicUrl(opts.publicUrl, req) +
'styles/' + id + '/style.json' + query
});
});
res.send(result);
@@ -210,7 +212,7 @@ function start(opts) {
} else {
path = type + '/' + id;
}
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format, {
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format, opts.publicUrl, {
'pbf': options.pbfAlias
});
arr.push(info);
@@ -246,8 +248,9 @@ function start(opts) {
startupPromises.push(new Promise(function(resolve, reject) {
fs.readFile(templateFile, function(err, content) {
if (err) {
console.error('Template not found:', err);
err = new Error('Template not found: ' + err.message);
reject(err);
return;
}
var compiled = handlebars.compile(content.toString());
@@ -260,10 +263,12 @@ function start(opts) {
}
}
data['server_version'] = packageJson.name + ' v' + packageJson.version;
data['public_url'] = opts.publicUrl || '/';
data['is_light'] = isLight;
data['key_query_part'] =
req.query.key ? 'key=' + req.query.key + '&amp;' : '';
data['key_query'] = req.query.key ? '?key=' + req.query.key : '';
if (template === 'wmts') res.set('Content-Type', 'text/xml');
return res.status(200).send(compiled(data));
});
resolve();
@@ -291,14 +296,9 @@ function start(opts) {
Math.floor(centerPx[1] / 256) + '.png';
}
var query = req.query.key ? ('?key=' + req.query.key) : '';
style.wmts_link = 'http://wmts.maptiler.com/' +
base64url('http://' + req.headers.host +
'/styles/' + id + '.json' + query) + '/wmts';
var tiles = utils.getTileUrls(
req, style.serving_rendered.tiles,
'styles/' + id, style.serving_rendered.format);
'styles/' + id, style.serving_rendered.format, opts.publicUrl);
style.xyz_link = tiles[0];
}
});
@@ -320,13 +320,8 @@ function start(opts) {
Math.floor(centerPx[1] / 256) + '.' + data_.format;
}
var query = req.query.key ? ('?key=' + req.query.key) : '';
data_.wmts_link = 'http://wmts.maptiler.com/' +
base64url('http://' + req.headers.host +
'/data/' + id + '.json' + query) + '/wmts';
var tiles = utils.getTileUrls(
req, data_.tiles, 'data/' + id, data_.format, {
req, data_.tiles, 'data/' + id, data_.format, opts.publicUrl, {
'pbf': options.pbfAlias
});
data_.xyz_link = tiles[0];
@@ -369,6 +364,20 @@ function start(opts) {
return res.redirect(301, '/styles/' + req.params.id + '/');
});
*/
serveTemplate('/styles/:id/wmts.xml', 'wmts', function(req) {
var id = req.params.id;
var wmts = clone((config.styles || {})[id]);
if (!wmts) {
return null;
}
if (wmts.hasOwnProperty("serve_rendered") && !wmts.serve_rendered) {
return null;
}
wmts.id = id;
wmts.name = (serving.styles[id] || serving.rendered[id]).name;
wmts.baseUrl = (req.get('X-Forwarded-Protocol')?req.get('X-Forwarded-Protocol'):req.protocol) + '://' + req.get('host');
return wmts;
});
serveTemplate('/data/:id/$', 'data', function(req) {
var id = req.params.id;
@@ -415,6 +424,11 @@ function start(opts) {
module.exports = function(opts) {
var running = start(opts);
running.startupPromise.catch(function(err) {
console.error(err.message);
process.exit(1);
});
process.on('SIGINT', function() {
process.exit();
});

View File

@@ -6,7 +6,12 @@ var path = require('path'),
var clone = require('clone'),
glyphCompose = require('glyph-pbf-composite');
module.exports.getTileUrls = function(req, domains, path, format, aliases) {
module.exports.getPublicUrl = function(publicUrl, req) {
return publicUrl || (req.protocol + '://' + req.headers.host + '/')
}
module.exports.getTileUrls = function(req, domains, path, format, publicUrl, aliases) {
if (domains) {
if (domains.constructor === String && domains.length > 0) {
@@ -49,10 +54,14 @@ module.exports.getTileUrls = function(req, domains, path, format, aliases) {
}
var uris = [];
domains.forEach(function(domain) {
uris.push(req.protocol + '://' + domain + '/' + path +
'/{z}/{x}/{y}.' + format + query);
});
if (!publicUrl) {
domains.forEach(function(domain) {
uris.push(req.protocol + '://' + domain + '/' + path +
'/{z}/{x}/{y}.' + format + query);
});
} else {
uris.push(publicUrl + path + '/{z}/{x}/{y}.' + format + query)
}
return uris;
};
@@ -84,7 +93,20 @@ var getFontPbf = function(allowedFonts, fontPath, name, range, fallbacks) {
if (err) {
console.error('ERROR: Font not found:', name);
if (fallbacks && Object.keys(fallbacks).length) {
var fallbackName = Object.keys(fallbacks)[0];
var fallbackName;
var fontStyle = name.split(' ').pop();
if (['Regular', 'Bold', 'Italic'].indexOf(fontStyle) < 0) {
fontStyle = 'Regular';
}
fallbackName = 'Noto Sans ' + fontStyle;
if (!fallbacks[fallbackName]) {
fallbackName = 'Open Sans ' + fontStyle;
if (!fallbacks[fallbackName]) {
fallbackName = Object.keys(fallbacks)[0];
}
}
console.error('ERROR: Trying to use', fallbackName, 'as a fallback');
delete fallbacks[fallbackName];
getFontPbf(null, fontPath, fallbackName, range, fallbacks).then(resolve, reject);
@@ -110,9 +132,7 @@ module.exports.getFontsPbf = function(allowedFonts, fontPath, names, range, fall
);
});
return new Promise(function(resolve, reject) {
Promise.all(queue).then(function(values) {
return resolve(glyphCompose.combine(values));
}, reject);
return Promise.all(queue).then(function(values) {
return glyphCompose.combine(values);
});
};

View File

@@ -8,7 +8,8 @@ before(function() {
process.chdir('test_data');
var running = require('../src/server')({
configPath: 'config.json',
port: 8888
port: 8888,
publicUrl: '/test/'
});
global.app = running.app;
global.server = running.server;
@@ -17,5 +18,5 @@ before(function() {
after(function() {
console.log('global teardown');
global.server.close(function() { console.log('Done'); });
global.server.close(function() { console.log('Done'); process.exit(); });
});

View File

@@ -23,6 +23,7 @@ describe('Styles', function() {
res.body.sources.should.be.Object();
res.body.glyphs.should.be.String();
res.body.sprite.should.be.String();
res.body.sprite.should.equal('/test/styles/test-style/sprite');
res.body.layers.should.be.Array();
}).end(done);
});

View File

@@ -23,6 +23,6 @@ describe('Vector tiles', function() {
testTile(prefix, 0, 1, 0, 404);
testTile(prefix, 0, 0, 1, 404);
testTile(prefix, 14, 0, 0, 404); // non existent tile
testTile(prefix, 14, 0, 0, 204); // non existent tile
});
});