Compare commits
15 commits
Author | SHA1 | Date | |
---|---|---|---|
4b1ffd489f | |||
![]() |
cd613e2fb5 | ||
![]() |
3e521a7d92 | ||
![]() |
d88fbb7c55 | ||
![]() |
6d4ab40b96 | ||
![]() |
5441a10488 | ||
![]() |
8a7d9957fb | ||
![]() |
6d1c617752 | ||
![]() |
3881219fee | ||
![]() |
3110cab18f | ||
![]() |
f2b48acb61 | ||
![]() |
6e0006ffcf | ||
![]() |
6ef12fba6c | ||
![]() |
3d8bf78974 | ||
![]() |
1d60dd6afc |
33 changed files with 3957 additions and 5324 deletions
1
.github/workflows/automerger.yml
vendored
1
.github/workflows/automerger.yml
vendored
|
@ -14,3 +14,4 @@ jobs:
|
||||||
- uses: fastify/github-action-merge-dependabot@v3
|
- uses: fastify/github-action-merge-dependabot@v3
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
target: minor
|
||||||
|
|
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
@ -21,6 +21,11 @@ jobs:
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Install dependencies (Ubuntu) 🚀
|
||||||
|
run: >-
|
||||||
|
sudo apt-get install -qq libcairo2-dev libjpeg8-dev libpango1.0-dev
|
||||||
|
libgif-dev build-essential
|
||||||
|
|
||||||
- name: Setup node env 📦
|
- name: Setup node env 📦
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
|
|
18
.github/workflows/ct.yml
vendored
18
.github/workflows/ct.yml
vendored
|
@ -65,6 +65,22 @@ jobs:
|
||||||
context: .
|
context: .
|
||||||
push: false
|
push: false
|
||||||
platforms: linux/arm64,linux/amd64
|
platforms: linux/arm64,linux/amd64
|
||||||
# experimental: https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#cache-backend-api
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Create Tileserver Light Directory
|
||||||
|
run: node publish.js --no-publish
|
||||||
|
|
||||||
|
- name: Install node dependencies
|
||||||
|
run: npm ci --prefer-offline --no-audit
|
||||||
|
working-directory: ./light
|
||||||
|
|
||||||
|
- name: Test Light Version to Docker Hub
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ./light
|
||||||
|
file: ./light/Dockerfile
|
||||||
|
push: false
|
||||||
|
platforms: linux/arm64,linux/amd64
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -1,4 +1,15 @@
|
||||||
docs/_build
|
docs/_build
|
||||||
|
public/resources/leaflet-hash.js
|
||||||
|
public/resources/leaflet.css
|
||||||
|
public/resources/leaflet.js
|
||||||
|
public/resources/leaflet.js.map
|
||||||
|
public/resources/mapbox-gl-rtl-text.js
|
||||||
|
public/resources/maplibre-gl-inspect.css
|
||||||
|
public/resources/maplibre-gl-inspect.js
|
||||||
|
public/resources/maplibre-gl-inspect.js.map
|
||||||
|
public/resources/maplibre-gl.css
|
||||||
|
public/resources/maplibre-gl.js
|
||||||
|
public/resources/maplibre-gl.js.map
|
||||||
node_modules
|
node_modules
|
||||||
test_data
|
test_data
|
||||||
test_data.zip
|
test_data.zip
|
||||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,15 @@
|
||||||
# tileserver-gl changelog
|
# tileserver-gl changelog
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
* Use npm packages for public/resources (https://github.com/maptiler/tileserver-gl/pull/1427) by @okimiko
|
||||||
|
* use ttf files of googlefonts/opensans (https://github.com/maptiler/tileserver-gl/pull/1447) by @okimiko
|
||||||
|
* Limit Elevation Lat/Long Output Length (https://github.com/maptiler/tileserver-gl/pull/1457) by @okimiko
|
||||||
|
* Fetch style from url (https://github.com/maptiler/tileserver-gl/pull/1462) by @YoelRidgway
|
||||||
|
* fix: memory leak on SIGHUP (https://github.com/maptiler/tileserver-gl/pull/1455) by @okimiko
|
||||||
|
* fix: resolves Unimplemented type: 3 error for geojson format (https://github.com/maptiler/tileserver-gl/pull/1465) by @rjdjohnston
|
||||||
|
* fix: Test light version in ct workflow - fix sqlite build in light (https://github.com/maptiler/tileserver-gl/pull/1477) by @acalcutt
|
||||||
|
* fix: light version docker entrypoint permissions (https://github.com/maptiler/tileserver-gl/pull/1478) by @acalcutt
|
||||||
|
|
||||||
## 5.1.3
|
## 5.1.3
|
||||||
* Fix SIGHUP (broken since 5.1.x) (https://github.com/maptiler/tileserver-gl/pull/1452) by @okimiko
|
* Fix SIGHUP (broken since 5.1.x) (https://github.com/maptiler/tileserver-gl/pull/1452) by @okimiko
|
||||||
|
|
||||||
|
|
90
Dockerfile
90
Dockerfile
|
@ -2,10 +2,11 @@ FROM ubuntu:jammy AS builder
|
||||||
|
|
||||||
ENV NODE_ENV="production"
|
ENV NODE_ENV="production"
|
||||||
|
|
||||||
RUN set -ex; \
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
export DEBIAN_FRONTEND=noninteractive; \
|
|
||||||
apt-get -qq update; \
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
apt-get -y --no-install-recommends install \
|
apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
build-essential \
|
build-essential \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
|
@ -26,23 +27,17 @@ RUN set -ex; \
|
||||||
librsvg2-common \
|
librsvg2-common \
|
||||||
libcurl4-openssl-dev \
|
libcurl4-openssl-dev \
|
||||||
libpixman-1-dev \
|
libpixman-1-dev \
|
||||||
libpixman-1-0; \
|
libpixman-1-0 && \
|
||||||
apt-get -y --purge autoremove; \
|
mkdir -p /etc/apt/keyrings && \
|
||||||
apt-get clean; \
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
rm -rf /var/lib/apt/lists/*;
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
|
apt-get -qq update && \
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
apt-get install -y --no-install-recommends --no-install-suggests nodejs && \
|
||||||
|
npm i -g npm@latest && \
|
||||||
RUN mkdir -p /etc/apt/keyrings; \
|
apt-get -y remove curl gnupg && \
|
||||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
|
apt-get -y --purge autoremove && \
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \
|
apt-get clean && \
|
||||||
apt-get -qq update; \
|
rm -rf /var/lib/apt/lists/*
|
||||||
apt-get install -y nodejs; \
|
|
||||||
npm i -g npm@latest; \
|
|
||||||
apt-get -y remove curl gnupg; \
|
|
||||||
apt-get -y --purge autoremove; \
|
|
||||||
apt-get clean; \
|
|
||||||
rm -rf /var/lib/apt/lists/*;
|
|
||||||
|
|
||||||
RUN mkdir -p /usr/src/app
|
RUN mkdir -p /usr/src/app
|
||||||
|
|
||||||
|
@ -51,12 +46,12 @@ WORKDIR /usr/src/app
|
||||||
COPY package.json /usr/src/app
|
COPY package.json /usr/src/app
|
||||||
COPY package-lock.json /usr/src/app
|
COPY package-lock.json /usr/src/app
|
||||||
|
|
||||||
RUN npm config set maxsockets 1; \
|
RUN npm config set maxsockets 1 && \
|
||||||
npm config set fetch-retries 5; \
|
npm config set fetch-retries 5 && \
|
||||||
npm config set fetch-retry-mintimeout 100000; \
|
npm config set fetch-retry-mintimeout 100000 && \
|
||||||
npm config set fetch-retry-maxtimeout 600000; \
|
npm config set fetch-retry-maxtimeout 600000 && \
|
||||||
npm ci --omit=dev; \
|
npm ci --omit=dev && \
|
||||||
chown -R root:root /usr/src/app;
|
chown -R root:root /usr/src/app
|
||||||
|
|
||||||
FROM ubuntu:jammy AS final
|
FROM ubuntu:jammy AS final
|
||||||
|
|
||||||
|
@ -65,12 +60,13 @@ ENV \
|
||||||
CHOKIDAR_USEPOLLING=1 \
|
CHOKIDAR_USEPOLLING=1 \
|
||||||
CHOKIDAR_INTERVAL=500
|
CHOKIDAR_INTERVAL=500
|
||||||
|
|
||||||
RUN set -ex; \
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
export DEBIAN_FRONTEND=noninteractive; \
|
|
||||||
groupadd -r node; \
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
useradd -r -g node node; \
|
groupadd -r node && \
|
||||||
apt-get -qq update; \
|
useradd -r -g node node && \
|
||||||
apt-get -y --no-install-recommends install \
|
apt-get -qq update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
gnupg \
|
gnupg \
|
||||||
|
@ -85,23 +81,17 @@ RUN set -ex; \
|
||||||
libpixman-1-0 \
|
libpixman-1-0 \
|
||||||
libcurl4 \
|
libcurl4 \
|
||||||
librsvg2-2 \
|
librsvg2-2 \
|
||||||
libpango-1.0-0; \
|
libpango-1.0-0 && \
|
||||||
apt-get -y --purge autoremove; \
|
mkdir -p /etc/apt/keyrings && \
|
||||||
apt-get clean; \
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
rm -rf /var/lib/apt/lists/*;
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
|
apt-get -qq update && \
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
apt-get install -y --no-install-recommends --no-install-suggests nodejs && \
|
||||||
|
npm i -g npm@latest && \
|
||||||
RUN mkdir -p /etc/apt/keyrings; \
|
apt-get -y remove curl gnupg && \
|
||||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
|
apt-get -y --purge autoremove && \
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \
|
apt-get clean && \
|
||||||
apt-get -qq update; \
|
rm -rf /var/lib/apt/lists/*
|
||||||
apt-get install -y nodejs; \
|
|
||||||
npm i -g npm@latest; \
|
|
||||||
apt-get -y remove curl gnupg; \
|
|
||||||
apt-get -y --purge autoremove; \
|
|
||||||
apt-get clean; \
|
|
||||||
rm -rf /var/lib/apt/lists/*;
|
|
||||||
|
|
||||||
COPY --from=builder /usr/src/app /usr/src/app
|
COPY --from=builder /usr/src/app /usr/src/app
|
||||||
|
|
||||||
|
|
38
Dockerfile_build
Normal file
38
Dockerfile_build
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
FROM ubuntu:jammy AS builder
|
||||||
|
|
||||||
|
ENV NODE_ENV="devel"
|
||||||
|
|
||||||
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
|
build-essential \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
gnupg \
|
||||||
|
pkg-config \
|
||||||
|
xvfb \
|
||||||
|
libglfw3-dev \
|
||||||
|
libuv1-dev \
|
||||||
|
libjpeg-turbo8 \
|
||||||
|
libicu70 \
|
||||||
|
libcairo2-dev \
|
||||||
|
libpango1.0-dev \
|
||||||
|
libjpeg-dev \
|
||||||
|
libgif-dev \
|
||||||
|
librsvg2-dev \
|
||||||
|
gir1.2-rsvg-2.0 \
|
||||||
|
librsvg2-2 \
|
||||||
|
librsvg2-common \
|
||||||
|
libcurl4-openssl-dev \
|
||||||
|
libpixman-1-dev \
|
||||||
|
libpixman-1-0 && \
|
||||||
|
mkdir -p /etc/apt/keyrings && \
|
||||||
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
|
apt-get -qq update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests nodejs && \
|
||||||
|
npm i -g npm@latest && \
|
||||||
|
apt-get -y remove curl gnupg && \
|
||||||
|
apt-get -y --purge autoremove && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
|
@ -1,53 +1,84 @@
|
||||||
FROM ubuntu:jammy
|
FROM ubuntu:jammy AS builder
|
||||||
|
|
||||||
|
ENV NODE_ENV="production"
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
|
build-essential \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
gnupg && \
|
||||||
|
mkdir -p /etc/apt/keyrings && \
|
||||||
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
|
apt-get -qq update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests nodejs && \
|
||||||
|
npm i -g npm@latest && \
|
||||||
|
apt-get -y remove curl gnupg && \
|
||||||
|
apt-get -y --purge autoremove && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/src/app
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package.json /usr/src/app
|
||||||
|
COPY package-lock.json /usr/src/app
|
||||||
|
|
||||||
|
RUN npm config set maxsockets 1 && \
|
||||||
|
npm config set fetch-retries 5 && \
|
||||||
|
npm config set fetch-retry-mintimeout 100000 && \
|
||||||
|
npm config set fetch-retry-maxtimeout 600000 && \
|
||||||
|
npm ci --omit=dev && \
|
||||||
|
chown -R root:root /usr/src/app
|
||||||
|
|
||||||
|
FROM ubuntu:jammy AS final
|
||||||
|
|
||||||
ENV \
|
ENV \
|
||||||
NODE_ENV="production" \
|
NODE_ENV="production" \
|
||||||
CHOKIDAR_USEPOLLING=1 \
|
CHOKIDAR_USEPOLLING=1 \
|
||||||
CHOKIDAR_INTERVAL=500
|
CHOKIDAR_INTERVAL=500
|
||||||
|
|
||||||
RUN set -ex; \
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
export DEBIAN_FRONTEND=noninteractive; \
|
|
||||||
groupadd -r node; \
|
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||||
useradd -r -g node node; \
|
groupadd -r node && \
|
||||||
apt-get -qq update; \
|
useradd -r -g node node && \
|
||||||
apt-get -y --no-install-recommends install \
|
apt-get -qq update && \
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
gnupg; \
|
gnupg && \
|
||||||
mkdir -p /etc/apt/keyrings; \
|
mkdir -p /etc/apt/keyrings && \
|
||||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
|
||||||
apt-get -qq update; \
|
apt-get -qq update && \
|
||||||
apt-get install -y nodejs; \
|
apt-get install -y --no-install-recommends --no-install-suggests nodejs && \
|
||||||
npm i -g npm@latest; \
|
npm i -g npm@latest && \
|
||||||
apt-get -y remove curl gnupg; \
|
apt-get -y remove curl gnupg && \
|
||||||
apt-get -y --purge autoremove; \
|
apt-get -y --purge autoremove && \
|
||||||
apt-get clean; \
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/*;
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
EXPOSE 8080
|
COPY --from=builder /usr/src/app /usr/src/app
|
||||||
|
|
||||||
RUN mkdir -p /data; \
|
COPY . /usr/src/app
|
||||||
chown node:node /data; \
|
|
||||||
mkdir -p /usr/src/app;
|
RUN mkdir -p /data && \
|
||||||
|
chown node:node /data && \
|
||||||
|
chmod +x /usr/src/app/docker-entrypoint.sh
|
||||||
|
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
|
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
COPY / /usr/src/app
|
EXPOSE 8080
|
||||||
|
|
||||||
RUN cd /usr/src/app; \
|
|
||||||
npm config set maxsockets 1; \
|
|
||||||
npm config set fetch-retries 5; \
|
|
||||||
npm config set fetch-retry-mintimeout 100000; \
|
|
||||||
npm config set fetch-retry-maxtimeout 600000; \
|
|
||||||
npm install --omit=dev; \
|
|
||||||
chown -R root:root /usr/src/app; \
|
|
||||||
chmod +x /usr/src/app/docker-entrypoint.sh;
|
|
||||||
|
|
||||||
USER node:node
|
USER node:node
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]
|
||||||
|
|
||||||
HEALTHCHECK CMD node /usr/src/app/src/healthcheck.js
|
HEALTHCHECK CMD node /usr/src/app/src/healthcheck.js
|
||||||
|
|
115
PUBLISHING.md
115
PUBLISHING.md
|
@ -1,19 +1,112 @@
|
||||||
# Publishing new version
|
# Publishing a New Version
|
||||||
|
|
||||||
1.) Change the version number in package.json. Run the following command in the package root directory, replacing <update_type> with one of the semantic versioning release types (prerelease, prepatch, preminor, premajor, patch, minor, major):
|
This document outlines the process for publishing new versions of this project. We use a GitHub workflow for automated releases, but also provide manual steps for specific situations.
|
||||||
npm version <update_type> --preid pre --no-git-tag-version
|
|
||||||
|
|
||||||
--preid specifies which suffix to use in the release such as pre, next, beta, rc, etc.
|
## Automated Publishing via GitHub Workflow (Recommended)
|
||||||
|
|
||||||
prepatch, preminor, and premajor start a new series of pre-releases while bumping the patch, minor, or major version. E.g. premajor with --preid pre would do a prerelease for a new major using the -pre suffix (i.e. it would be a new major with -pre.0)
|
This is the preferred method for publishing new versions. It automates the entire process, including version bumping, tagging, building, and publishing.
|
||||||
|
|
||||||
You can use prerelease to bump the version for a new pre-release version. E.g. you could run npm version prerelease --preid pre --no-git-tag-version to go from -pre.0 to -pre.1.
|
1. **Prepare the Release:**
|
||||||
|
|
||||||
For regular versions, you can use patch, minor, or major. E.g. npm version major --no-git-tag-version.
|
* **Choose the Version Increment:** Determine the appropriate semantic versioning increment (prerelease, prepatch, preminor, premajor, patch, minor, major).
|
||||||
|
|
||||||
2.) Update the changelog, which can be found in CHANGELOG.md. The heading must match ## <VERSION> exactly, or it will not be picked up. For example, for version 5.0.0:
|
* **Update `package.json`:** Use the `npm version` command to bump the version number. This command also supports creating pre-release versions using the `--preid pre` flag.
|
||||||
```## 5.0.0```
|
|
||||||
|
|
||||||
3.) Commit and push the changes.
|
```bash
|
||||||
|
# Example: Increment to a new patch version
|
||||||
|
npm version patch --no-git-tag-version
|
||||||
|
|
||||||
4.) Run the 'Build, Test, Release' github workflow. The workflow will create a NPM, Docker, and Github release and Tag.
|
# Example: Increment to a new minor version
|
||||||
|
npm version minor --no-git-tag-version
|
||||||
|
|
||||||
|
# Example: Increment to a new major version
|
||||||
|
npm version major --no-git-tag-version
|
||||||
|
|
||||||
|
# Example: Create a pre-release (e.g., -pre.0) version
|
||||||
|
npm version prepatch --preid pre --no-git-tag-version
|
||||||
|
# OR
|
||||||
|
npm version preminor --preid pre --no-git-tag-version
|
||||||
|
# OR
|
||||||
|
npm version premajor --preid pre --no-git-tag-version
|
||||||
|
|
||||||
|
# Example: Increment an existing pre-release version (e.g., -pre.0 to -pre.1)
|
||||||
|
npm version prerelease --preid pre --no-git-tag-version
|
||||||
|
```
|
||||||
|
|
||||||
|
* `--no-git-tag-version`: This prevents `npm version` from automatically creating a git tag, as the GitHub workflow will handle this later.
|
||||||
|
* `--preid pre`: Specifies that "pre" is the pre-release identifier.
|
||||||
|
|
||||||
|
* **Update the Changelog (`CHANGELOG.md`):** Add a new section for the release. The heading *must* exactly match the format `## <VERSION>`, where `<VERSION>` is the full version number from `package.json`. Describe the changes included in the release.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 1.2.3
|
||||||
|
* Added new feature X.
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Commit and Push:** Commit the changes to `package.json`, `package-lock.json` and `CHANGELOG.md` to a the `master` branch. Create a pull request (PR) for review. If you are an administrator, you may push directly, but a PR is generally recommended for code review.
|
||||||
|
|
||||||
|
3. **Run the GitHub Workflow:** Once the PR is merged (or changes pushed directly), trigger the "Build, Test, Release" GitHub workflow. This workflow is responsible for:
|
||||||
|
|
||||||
|
* Building the project.
|
||||||
|
* Running tests.
|
||||||
|
* Creating an NPM package.
|
||||||
|
* Building and pushing Docker images.
|
||||||
|
* Creating a GitHub Release.
|
||||||
|
* Creating a Git tag for the release.
|
||||||
|
|
||||||
|
## Manual Publishing (For Special Cases)
|
||||||
|
|
||||||
|
Use the following steps *only* when the automated workflow is not suitable (e.g., for debugging, specific environment needs).
|
||||||
|
|
||||||
|
1. **Update Version in `package.json`:** Modify the `version` field in `package.json` to the desired version number.
|
||||||
|
|
||||||
|
2. **Create and Push Git Tag:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag vX.X.X # Replace X.X.X with the version number
|
||||||
|
git push origin --tags
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **NPM Publish Options (Choose ONE):**
|
||||||
|
|
||||||
|
* **Option A: Publish only the full `tileserver-gl` version:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm publish --access public
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Option B: Build and Publish both `tileserver-gl` and `tileserver-gl-light` using `publish.js`:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# This script builds the light version and publishes both tileserver-gl and tileserver-gl-light to NPM.
|
||||||
|
node publish.js
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Option C: Build only the `tileserver-gl-light` version (no publish):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# This script ONLY builds the light version (e.g., for local testing or Docker image creation) without publishing.
|
||||||
|
node publish.js --no-publish
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Build and Push Docker Images:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the main image
|
||||||
|
docker buildx build --platform linux/amd64 -t maptiler/tileserver-gl:latest -t maptiler/tileserver-gl:X.X.X . # Replace X.X.X
|
||||||
|
docker push maptiler/tileserver-gl --all-tags
|
||||||
|
|
||||||
|
# Build the light image
|
||||||
|
cd light
|
||||||
|
docker buildx build --platform linux/amd64 -t maptiler/tileserver-gl-light:latest -t maptiler/tileserver-gl-light:X.X.X . # Replace X.X.X
|
||||||
|
docker push maptiler/tileserver-gl-light --all-tags
|
||||||
|
cd .. # Return to the project root
|
||||||
|
```
|
||||||
|
* Make sure you are logged into the docker registry before pushing. `docker login`
|
||||||
|
|
||||||
|
**Important Considerations for Manual Publishing:**
|
||||||
|
|
||||||
|
* **Consistency:** Ensure the version number in `package.json`, the Git tag, and the Docker image tags are identical.
|
||||||
|
* **Credentials:** Verify that you have the necessary permissions to push Docker images and publish to NPM.
|
||||||
|
* **Cleanliness:** Before building Docker images, ensure your working directory is clean to avoid including unwanted files in the image.
|
||||||
|
* **Error Handling:** Manually publishing is more prone to errors. Double-check each step to avoid issues.
|
||||||
|
|
27
README.md
27
README.md
|
@ -1,5 +1,32 @@
|
||||||

|

|
||||||
|
|
||||||
|
# My TileServer GL
|
||||||
|
|
||||||
|
creare un folder dove mettere la mappa e i layers
|
||||||
|
|
||||||
|
Download vector tiles from [OpenMapTiles](https://data.maptiler.com/downloads/planet/).
|
||||||
|
|
||||||
|
scaricare i layers
|
||||||
|
|
||||||
|
wget https://github.com/maptiler/tileserver-gl/releases/download/v1.3.0/test_data.zip
|
||||||
|
unzip test_data.zip
|
||||||
|
|
||||||
|
modificare nano config.json per inserire il nome del file .mbtiles (x es planetOSM.mbtiles )
|
||||||
|
|
||||||
|
far partire il docker
|
||||||
|
|
||||||
|
services:
|
||||||
|
tileserver-gl:
|
||||||
|
volumes:
|
||||||
|
- /home/nvme/dockerdata/tileserver:/data
|
||||||
|
ports:
|
||||||
|
- 8115:8080
|
||||||
|
image: maptiler/tileserver-gl:latest
|
||||||
|
|
||||||
|
oppure
|
||||||
|
|
||||||
|
sudo docker run -d -v /home/nvme/dockerdata/tileserver:/data -p 8115:8080 maptiler/tileserver-gl:latest
|
||||||
|
|
||||||
# TileServer GL
|
# TileServer GL
|
||||||
[](https://github.com/maptiler/tileserver-gl/actions/workflows/pipeline.yml)
|
[](https://github.com/maptiler/tileserver-gl/actions/workflows/pipeline.yml)
|
||||||
[](https://hub.docker.com/r/maptiler/tileserver-gl/)
|
[](https://hub.docker.com/r/maptiler/tileserver-gl/)
|
||||||
|
|
|
@ -57,6 +57,9 @@ Example:
|
||||||
"tilejson": {
|
"tilejson": {
|
||||||
"format": "webp"
|
"format": "webp"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"style": "https://demotiles.maplibre.org/style.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -209,7 +212,7 @@ Not used by default.
|
||||||
|
|
||||||
Each item in this object defines one style (map). It can have the following options:
|
Each item in this object defines one style (map). It can have the following options:
|
||||||
|
|
||||||
* ``style`` -- name of the style json file [required]
|
* ``style`` -- name of the style json file or url of a remote hosted style [required]
|
||||||
* ``serve_rendered`` -- whether to render the raster tiles for this style or not
|
* ``serve_rendered`` -- whether to render the raster tiles for this style or not
|
||||||
* ``serve_data`` -- whether to allow access to the original tiles, sprites and required glyphs
|
* ``serve_data`` -- whether to allow access to the original tiles, sprites and required glyphs
|
||||||
* ``tilejson`` -- properties to add to the TileJSON created for the raster data
|
* ``tilejson`` -- properties to add to the TileJSON created for the raster data
|
||||||
|
|
4944
package-lock.json
generated
4944
package-lock.json
generated
File diff suppressed because it is too large
Load diff
16
package.json
16
package.json
|
@ -1,11 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "tileserver-gl",
|
"name": "tileserver-gl",
|
||||||
"version": "5.1.3",
|
"version": "5.2.0",
|
||||||
"description": "Map tile server for JSON GL styles - vector and server side generated raster tiles",
|
"description": "Map tile server for JSON GL styles - vector and server side generated raster tiles",
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"bin": "src/main.js",
|
"bin": "src/main.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prepare": "npm run copy:maplibre && npm run copy:maplibre-inspect && npm run copy:mapbox-rtl-text && npm run copy:leaflet && npm run copy:leaflet-hash",
|
||||||
|
"copy:maplibre": "copyfiles -EVf node_modules/maplibre-gl/dist/maplibre-gl.js node_modules/maplibre-gl/dist/maplibre-gl.js.map node_modules/maplibre-gl/dist/maplibre-gl.css public/resources/",
|
||||||
|
"copy:maplibre-inspect": "copyfiles -EVf node_modules/@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.js node_modules/@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.js.map node_modules/@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.css public/resources/",
|
||||||
|
"copy:mapbox-rtl-text": "copyfiles -EVf node_modules/@mapbox/mapbox-gl-rtl-text/dist/mapbox-gl-rtl-text.js public/resources/",
|
||||||
|
"copy:leaflet": "copyfiles -EVf node_modules/leaflet/dist/leaflet.js node_modules/leaflet/dist/leaflet.js.map node_modules/leaflet/dist/leaflet.css node_modules/leaflet/dist/leaflet-hash.js public/resources/",
|
||||||
|
"copy:leaflet-hash": "copyfiles -EVf node_modules/leaflet-hash/leaflet-hash.js public/resources/",
|
||||||
"test": "mocha test/**.js --timeout 10000 --exit",
|
"test": "mocha test/**.js --timeout 10000 --exit",
|
||||||
"test-docker": "xvfb-run npm test",
|
"test-docker": "xvfb-run npm test",
|
||||||
"lint:yml": "yamllint --schema=CORE_SCHEMA *.{yml,yaml}",
|
"lint:yml": "yamllint --schema=CORE_SCHEMA *.{yml,yaml}",
|
||||||
|
@ -19,24 +25,30 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsse/pbfont": "^0.2.2",
|
"@jsse/pbfont": "^0.2.2",
|
||||||
|
"@mapbox/mapbox-gl-rtl-text": "0.3.0",
|
||||||
"@mapbox/mbtiles": "0.12.1",
|
"@mapbox/mbtiles": "0.12.1",
|
||||||
"@mapbox/polyline": "^1.2.1",
|
"@mapbox/polyline": "^1.2.1",
|
||||||
"@mapbox/sphericalmercator": "1.2.0",
|
"@mapbox/sphericalmercator": "1.2.0",
|
||||||
"@mapbox/vector-tile": "2.0.3",
|
"@mapbox/vector-tile": "2.0.3",
|
||||||
|
"@maplibre/maplibre-gl-inspect": "1.7.0",
|
||||||
"@maplibre/maplibre-gl-native": "6.0.0",
|
"@maplibre/maplibre-gl-native": "6.0.0",
|
||||||
"@maplibre/maplibre-gl-style-spec": "20.3.1",
|
"@maplibre/maplibre-gl-style-spec": "20.3.1",
|
||||||
"@sindresorhus/fnv1a": "3.1.0",
|
"@sindresorhus/fnv1a": "3.1.0",
|
||||||
"advanced-pool": "0.3.3",
|
"advanced-pool": "0.3.3",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.8.2",
|
||||||
"canvas": "3.0.1",
|
"canvas": "3.0.1",
|
||||||
"chokidar": "3.6.0",
|
"chokidar": "3.6.0",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"color": "4.2.3",
|
"color": "4.2.3",
|
||||||
"commander": "12.1.0",
|
"commander": "12.1.0",
|
||||||
|
"copyfiles": "2.4.1",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"express": "5.0.1",
|
"express": "5.0.1",
|
||||||
"handlebars": "4.7.8",
|
"handlebars": "4.7.8",
|
||||||
"http-shutdown": "1.2.2",
|
"http-shutdown": "1.2.2",
|
||||||
|
"leaflet": "1.9.4",
|
||||||
|
"leaflet-hash": "0.2.1",
|
||||||
|
"maplibre-gl": "4.7.1",
|
||||||
"morgan": "1.10.0",
|
"morgan": "1.10.0",
|
||||||
"pbf": "4.0.1",
|
"pbf": "4.0.1",
|
||||||
"pmtiles": "3.0.7",
|
"pmtiles": "3.0.7",
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ElevationInfoControl {
|
||||||
|
|
||||||
map.on('click', (e) => {
|
map.on('click', (e) => {
|
||||||
var url = this.url;
|
var url = this.url;
|
||||||
var coord = {"z": Math.floor(map.getZoom()), "x": e.lngLat["lng"], "y": e.lngLat["lat"]};
|
var coord = {"z": Math.floor(map.getZoom()), "x": e.lngLat["lng"].toFixed(7), "y": e.lngLat["lat"].toFixed(7)};
|
||||||
for(var key in coord) {
|
for(var key in coord) {
|
||||||
url = url.replace(new RegExp('{'+ key +'}','g'), coord[key]);
|
url = url.replace(new RegExp('{'+ key +'}','g'), coord[key]);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,162 +0,0 @@
|
||||||
(function(window) {
|
|
||||||
var HAS_HASHCHANGE = (function() {
|
|
||||||
var doc_mode = window.documentMode;
|
|
||||||
return ('onhashchange' in window) &&
|
|
||||||
(doc_mode === undefined || doc_mode > 7);
|
|
||||||
})();
|
|
||||||
|
|
||||||
L.Hash = function(map) {
|
|
||||||
this.onHashChange = L.Util.bind(this.onHashChange, this);
|
|
||||||
|
|
||||||
if (map) {
|
|
||||||
this.init(map);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
L.Hash.parseHash = function(hash) {
|
|
||||||
if(hash.indexOf('#') === 0) {
|
|
||||||
hash = hash.substr(1);
|
|
||||||
}
|
|
||||||
var args = hash.split("/");
|
|
||||||
if (args.length == 3) {
|
|
||||||
var zoom = parseInt(args[0], 10),
|
|
||||||
lat = parseFloat(args[1]),
|
|
||||||
lon = parseFloat(args[2]);
|
|
||||||
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
center: new L.LatLng(lat, lon),
|
|
||||||
zoom: zoom
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
L.Hash.formatHash = function(map) {
|
|
||||||
var center = map.getCenter(),
|
|
||||||
zoom = map.getZoom(),
|
|
||||||
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
|
|
||||||
|
|
||||||
return "#" + [zoom,
|
|
||||||
center.lat.toFixed(precision),
|
|
||||||
center.lng.toFixed(precision)
|
|
||||||
].join("/");
|
|
||||||
},
|
|
||||||
|
|
||||||
L.Hash.prototype = {
|
|
||||||
map: null,
|
|
||||||
lastHash: null,
|
|
||||||
|
|
||||||
parseHash: L.Hash.parseHash,
|
|
||||||
formatHash: L.Hash.formatHash,
|
|
||||||
|
|
||||||
init: function(map) {
|
|
||||||
this.map = map;
|
|
||||||
|
|
||||||
// reset the hash
|
|
||||||
this.lastHash = null;
|
|
||||||
this.onHashChange();
|
|
||||||
|
|
||||||
if (!this.isListening) {
|
|
||||||
this.startListening();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeFrom: function(map) {
|
|
||||||
if (this.changeTimeout) {
|
|
||||||
clearTimeout(this.changeTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isListening) {
|
|
||||||
this.stopListening();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.map = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
onMapMove: function() {
|
|
||||||
// bail if we're moving the map (updating from a hash),
|
|
||||||
// or if the map is not yet loaded
|
|
||||||
|
|
||||||
if (this.movingMap || !this.map._loaded) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash = this.formatHash(this.map);
|
|
||||||
if (this.lastHash != hash) {
|
|
||||||
location.replace(hash);
|
|
||||||
this.lastHash = hash;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
movingMap: false,
|
|
||||||
update: function() {
|
|
||||||
var hash = location.hash;
|
|
||||||
if (hash === this.lastHash) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var parsed = this.parseHash(hash);
|
|
||||||
if (parsed) {
|
|
||||||
this.movingMap = true;
|
|
||||||
|
|
||||||
this.map.setView(parsed.center, parsed.zoom);
|
|
||||||
|
|
||||||
this.movingMap = false;
|
|
||||||
} else {
|
|
||||||
this.onMapMove(this.map);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// defer hash change updates every 100ms
|
|
||||||
changeDefer: 100,
|
|
||||||
changeTimeout: null,
|
|
||||||
onHashChange: function() {
|
|
||||||
// throttle calls to update() so that they only happen every
|
|
||||||
// `changeDefer` ms
|
|
||||||
if (!this.changeTimeout) {
|
|
||||||
var that = this;
|
|
||||||
this.changeTimeout = setTimeout(function() {
|
|
||||||
that.update();
|
|
||||||
that.changeTimeout = null;
|
|
||||||
}, this.changeDefer);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isListening: false,
|
|
||||||
hashChangeInterval: null,
|
|
||||||
startListening: function() {
|
|
||||||
this.map.on("moveend", this.onMapMove, this);
|
|
||||||
|
|
||||||
if (HAS_HASHCHANGE) {
|
|
||||||
L.DomEvent.addListener(window, "hashchange", this.onHashChange);
|
|
||||||
} else {
|
|
||||||
clearInterval(this.hashChangeInterval);
|
|
||||||
this.hashChangeInterval = setInterval(this.onHashChange, 50);
|
|
||||||
}
|
|
||||||
this.isListening = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
stopListening: function() {
|
|
||||||
this.map.off("moveend", this.onMapMove, this);
|
|
||||||
|
|
||||||
if (HAS_HASHCHANGE) {
|
|
||||||
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
|
|
||||||
} else {
|
|
||||||
clearInterval(this.hashChangeInterval);
|
|
||||||
}
|
|
||||||
this.isListening = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
L.hash = function(map) {
|
|
||||||
return new L.Hash(map);
|
|
||||||
};
|
|
||||||
L.Map.prototype.addHash = function() {
|
|
||||||
this._hash = L.hash(this);
|
|
||||||
};
|
|
||||||
L.Map.prototype.removeHash = function() {
|
|
||||||
this._hash.removeFrom();
|
|
||||||
};
|
|
||||||
})(window);
|
|
|
@ -1,661 +0,0 @@
|
||||||
/* required styles */
|
|
||||||
|
|
||||||
.leaflet-pane,
|
|
||||||
.leaflet-tile,
|
|
||||||
.leaflet-marker-icon,
|
|
||||||
.leaflet-marker-shadow,
|
|
||||||
.leaflet-tile-container,
|
|
||||||
.leaflet-pane > svg,
|
|
||||||
.leaflet-pane > canvas,
|
|
||||||
.leaflet-zoom-box,
|
|
||||||
.leaflet-image-layer,
|
|
||||||
.leaflet-layer {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.leaflet-container {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.leaflet-tile,
|
|
||||||
.leaflet-marker-icon,
|
|
||||||
.leaflet-marker-shadow {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-user-drag: none;
|
|
||||||
}
|
|
||||||
/* Prevents IE11 from highlighting tiles in blue */
|
|
||||||
.leaflet-tile::selection {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
|
||||||
.leaflet-safari .leaflet-tile {
|
|
||||||
image-rendering: -webkit-optimize-contrast;
|
|
||||||
}
|
|
||||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
|
||||||
.leaflet-safari .leaflet-tile-container {
|
|
||||||
width: 1600px;
|
|
||||||
height: 1600px;
|
|
||||||
-webkit-transform-origin: 0 0;
|
|
||||||
}
|
|
||||||
.leaflet-marker-icon,
|
|
||||||
.leaflet-marker-shadow {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
|
||||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
|
||||||
.leaflet-container .leaflet-overlay-pane svg {
|
|
||||||
max-width: none !important;
|
|
||||||
max-height: none !important;
|
|
||||||
}
|
|
||||||
.leaflet-container .leaflet-marker-pane img,
|
|
||||||
.leaflet-container .leaflet-shadow-pane img,
|
|
||||||
.leaflet-container .leaflet-tile-pane img,
|
|
||||||
.leaflet-container img.leaflet-image-layer,
|
|
||||||
.leaflet-container .leaflet-tile {
|
|
||||||
max-width: none !important;
|
|
||||||
max-height: none !important;
|
|
||||||
width: auto;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-container img.leaflet-tile {
|
|
||||||
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
|
||||||
mix-blend-mode: plus-lighter;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-container.leaflet-touch-zoom {
|
|
||||||
-ms-touch-action: pan-x pan-y;
|
|
||||||
touch-action: pan-x pan-y;
|
|
||||||
}
|
|
||||||
.leaflet-container.leaflet-touch-drag {
|
|
||||||
-ms-touch-action: pinch-zoom;
|
|
||||||
/* Fallback for FF which doesn't support pinch-zoom */
|
|
||||||
touch-action: none;
|
|
||||||
touch-action: pinch-zoom;
|
|
||||||
}
|
|
||||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
|
||||||
-ms-touch-action: none;
|
|
||||||
touch-action: none;
|
|
||||||
}
|
|
||||||
.leaflet-container {
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
}
|
|
||||||
.leaflet-container a {
|
|
||||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
|
||||||
}
|
|
||||||
.leaflet-tile {
|
|
||||||
filter: inherit;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
.leaflet-tile-loaded {
|
|
||||||
visibility: inherit;
|
|
||||||
}
|
|
||||||
.leaflet-zoom-box {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
z-index: 800;
|
|
||||||
}
|
|
||||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
|
||||||
.leaflet-overlay-pane svg {
|
|
||||||
-moz-user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-pane { z-index: 400; }
|
|
||||||
|
|
||||||
.leaflet-tile-pane { z-index: 200; }
|
|
||||||
.leaflet-overlay-pane { z-index: 400; }
|
|
||||||
.leaflet-shadow-pane { z-index: 500; }
|
|
||||||
.leaflet-marker-pane { z-index: 600; }
|
|
||||||
.leaflet-tooltip-pane { z-index: 650; }
|
|
||||||
.leaflet-popup-pane { z-index: 700; }
|
|
||||||
|
|
||||||
.leaflet-map-pane canvas { z-index: 100; }
|
|
||||||
.leaflet-map-pane svg { z-index: 200; }
|
|
||||||
|
|
||||||
.leaflet-vml-shape {
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
}
|
|
||||||
.lvml {
|
|
||||||
behavior: url(#default#VML);
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* control positioning */
|
|
||||||
|
|
||||||
.leaflet-control {
|
|
||||||
position: relative;
|
|
||||||
z-index: 800;
|
|
||||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
.leaflet-top,
|
|
||||||
.leaflet-bottom {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1000;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.leaflet-top {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
.leaflet-right {
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
.leaflet-bottom {
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
.leaflet-left {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.leaflet-control {
|
|
||||||
float: left;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.leaflet-right .leaflet-control {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.leaflet-top .leaflet-control {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.leaflet-bottom .leaflet-control {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.leaflet-left .leaflet-control {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
.leaflet-right .leaflet-control {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* zoom and fade animations */
|
|
||||||
|
|
||||||
.leaflet-fade-anim .leaflet-popup {
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-transition: opacity 0.2s linear;
|
|
||||||
-moz-transition: opacity 0.2s linear;
|
|
||||||
transition: opacity 0.2s linear;
|
|
||||||
}
|
|
||||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.leaflet-zoom-animated {
|
|
||||||
-webkit-transform-origin: 0 0;
|
|
||||||
-ms-transform-origin: 0 0;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
}
|
|
||||||
svg.leaflet-zoom-animated {
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
|
||||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
||||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
||||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
||||||
}
|
|
||||||
.leaflet-zoom-anim .leaflet-tile,
|
|
||||||
.leaflet-pan-anim .leaflet-tile {
|
|
||||||
-webkit-transition: none;
|
|
||||||
-moz-transition: none;
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* cursors */
|
|
||||||
|
|
||||||
.leaflet-interactive {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.leaflet-grab {
|
|
||||||
cursor: -webkit-grab;
|
|
||||||
cursor: -moz-grab;
|
|
||||||
cursor: grab;
|
|
||||||
}
|
|
||||||
.leaflet-crosshair,
|
|
||||||
.leaflet-crosshair .leaflet-interactive {
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
.leaflet-popup-pane,
|
|
||||||
.leaflet-control {
|
|
||||||
cursor: auto;
|
|
||||||
}
|
|
||||||
.leaflet-dragging .leaflet-grab,
|
|
||||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
|
||||||
.leaflet-dragging .leaflet-marker-draggable {
|
|
||||||
cursor: move;
|
|
||||||
cursor: -webkit-grabbing;
|
|
||||||
cursor: -moz-grabbing;
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* marker & overlays interactivity */
|
|
||||||
.leaflet-marker-icon,
|
|
||||||
.leaflet-marker-shadow,
|
|
||||||
.leaflet-image-layer,
|
|
||||||
.leaflet-pane > svg path,
|
|
||||||
.leaflet-tile-container {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-marker-icon.leaflet-interactive,
|
|
||||||
.leaflet-image-layer.leaflet-interactive,
|
|
||||||
.leaflet-pane > svg path.leaflet-interactive,
|
|
||||||
svg.leaflet-image-layer.leaflet-interactive path {
|
|
||||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* visual tweaks */
|
|
||||||
|
|
||||||
.leaflet-container {
|
|
||||||
background: #ddd;
|
|
||||||
outline-offset: 1px;
|
|
||||||
}
|
|
||||||
.leaflet-container a {
|
|
||||||
color: #0078A8;
|
|
||||||
}
|
|
||||||
.leaflet-zoom-box {
|
|
||||||
border: 2px dotted #38f;
|
|
||||||
background: rgba(255,255,255,0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* general typography */
|
|
||||||
.leaflet-container {
|
|
||||||
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* general toolbar styles */
|
|
||||||
|
|
||||||
.leaflet-bar {
|
|
||||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.leaflet-bar a {
|
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
line-height: 26px;
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
.leaflet-bar a,
|
|
||||||
.leaflet-control-layers-toggle {
|
|
||||||
background-position: 50% 50%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.leaflet-bar a:hover,
|
|
||||||
.leaflet-bar a:focus {
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
}
|
|
||||||
.leaflet-bar a:first-child {
|
|
||||||
border-top-left-radius: 4px;
|
|
||||||
border-top-right-radius: 4px;
|
|
||||||
}
|
|
||||||
.leaflet-bar a:last-child {
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.leaflet-bar a.leaflet-disabled {
|
|
||||||
cursor: default;
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
color: #bbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-touch .leaflet-bar a {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
.leaflet-touch .leaflet-bar a:first-child {
|
|
||||||
border-top-left-radius: 2px;
|
|
||||||
border-top-right-radius: 2px;
|
|
||||||
}
|
|
||||||
.leaflet-touch .leaflet-bar a:last-child {
|
|
||||||
border-bottom-left-radius: 2px;
|
|
||||||
border-bottom-right-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* zoom control */
|
|
||||||
|
|
||||||
.leaflet-control-zoom-in,
|
|
||||||
.leaflet-control-zoom-out {
|
|
||||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
|
||||||
text-indent: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* layers control */
|
|
||||||
|
|
||||||
.leaflet-control-layers {
|
|
||||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-toggle {
|
|
||||||
background-image: url(images/layers.png);
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
.leaflet-retina .leaflet-control-layers-toggle {
|
|
||||||
background-image: url(images/layers-2x.png);
|
|
||||||
background-size: 26px 26px;
|
|
||||||
}
|
|
||||||
.leaflet-touch .leaflet-control-layers-toggle {
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers .leaflet-control-layers-list,
|
|
||||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-expanded {
|
|
||||||
padding: 6px 10px 6px 6px;
|
|
||||||
color: #333;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-scrollbar {
|
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-selector {
|
|
||||||
margin-top: 2px;
|
|
||||||
position: relative;
|
|
||||||
top: 1px;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers label {
|
|
||||||
display: block;
|
|
||||||
font-size: 13px;
|
|
||||||
font-size: 1.08333em;
|
|
||||||
}
|
|
||||||
.leaflet-control-layers-separator {
|
|
||||||
height: 0;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
margin: 5px -10px 5px -6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default icon URLs */
|
|
||||||
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
|
||||||
background-image: url(images/marker-icon.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* attribution and scale controls */
|
|
||||||
|
|
||||||
.leaflet-container .leaflet-control-attribution {
|
|
||||||
background: #fff;
|
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.leaflet-control-attribution,
|
|
||||||
.leaflet-control-scale-line {
|
|
||||||
padding: 0 5px;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
.leaflet-control-attribution a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.leaflet-control-attribution a:hover,
|
|
||||||
.leaflet-control-attribution a:focus {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
.leaflet-attribution-flag {
|
|
||||||
display: inline !important;
|
|
||||||
vertical-align: baseline !important;
|
|
||||||
width: 1em;
|
|
||||||
height: 0.6669em;
|
|
||||||
}
|
|
||||||
.leaflet-left .leaflet-control-scale {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
.leaflet-bottom .leaflet-control-scale {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
.leaflet-control-scale-line {
|
|
||||||
border: 2px solid #777;
|
|
||||||
border-top: none;
|
|
||||||
line-height: 1.1;
|
|
||||||
padding: 2px 5px 1px;
|
|
||||||
white-space: nowrap;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: rgba(255, 255, 255, 0.8);
|
|
||||||
text-shadow: 1px 1px #fff;
|
|
||||||
}
|
|
||||||
.leaflet-control-scale-line:not(:first-child) {
|
|
||||||
border-top: 2px solid #777;
|
|
||||||
border-bottom: none;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
|
||||||
border-bottom: 2px solid #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-touch .leaflet-control-attribution,
|
|
||||||
.leaflet-touch .leaflet-control-layers,
|
|
||||||
.leaflet-touch .leaflet-bar {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
.leaflet-touch .leaflet-control-layers,
|
|
||||||
.leaflet-touch .leaflet-bar {
|
|
||||||
border: 2px solid rgba(0,0,0,0.2);
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* popup */
|
|
||||||
|
|
||||||
.leaflet-popup {
|
|
||||||
position: absolute;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.leaflet-popup-content-wrapper {
|
|
||||||
padding: 1px;
|
|
||||||
text-align: left;
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
|
||||||
.leaflet-popup-content {
|
|
||||||
margin: 13px 24px 13px 20px;
|
|
||||||
line-height: 1.3;
|
|
||||||
font-size: 13px;
|
|
||||||
font-size: 1.08333em;
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
.leaflet-popup-content p {
|
|
||||||
margin: 17px 0;
|
|
||||||
margin: 1.3em 0;
|
|
||||||
}
|
|
||||||
.leaflet-popup-tip-container {
|
|
||||||
width: 40px;
|
|
||||||
height: 20px;
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
margin-top: -1px;
|
|
||||||
margin-left: -20px;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.leaflet-popup-tip {
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
padding: 1px;
|
|
||||||
|
|
||||||
margin: -10px auto 0;
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
-webkit-transform: rotate(45deg);
|
|
||||||
-moz-transform: rotate(45deg);
|
|
||||||
-ms-transform: rotate(45deg);
|
|
||||||
transform: rotate(45deg);
|
|
||||||
}
|
|
||||||
.leaflet-popup-content-wrapper,
|
|
||||||
.leaflet-popup-tip {
|
|
||||||
background: white;
|
|
||||||
color: #333;
|
|
||||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
|
||||||
}
|
|
||||||
.leaflet-container a.leaflet-popup-close-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
border: none;
|
|
||||||
text-align: center;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
||||||
color: #757575;
|
|
||||||
text-decoration: none;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.leaflet-container a.leaflet-popup-close-button:hover,
|
|
||||||
.leaflet-container a.leaflet-popup-close-button:focus {
|
|
||||||
color: #585858;
|
|
||||||
}
|
|
||||||
.leaflet-popup-scrolled {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
|
||||||
-ms-zoom: 1;
|
|
||||||
}
|
|
||||||
.leaflet-oldie .leaflet-popup-tip {
|
|
||||||
width: 24px;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
|
||||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-oldie .leaflet-control-zoom,
|
|
||||||
.leaflet-oldie .leaflet-control-layers,
|
|
||||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
|
||||||
.leaflet-oldie .leaflet-popup-tip {
|
|
||||||
border: 1px solid #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* div icon */
|
|
||||||
|
|
||||||
.leaflet-div-icon {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Tooltip */
|
|
||||||
/* Base styles for the element that has a tooltip */
|
|
||||||
.leaflet-tooltip {
|
|
||||||
position: absolute;
|
|
||||||
padding: 6px;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #222;
|
|
||||||
white-space: nowrap;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: none;
|
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
|
||||||
}
|
|
||||||
.leaflet-tooltip.leaflet-interactive {
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-top:before,
|
|
||||||
.leaflet-tooltip-bottom:before,
|
|
||||||
.leaflet-tooltip-left:before,
|
|
||||||
.leaflet-tooltip-right:before {
|
|
||||||
position: absolute;
|
|
||||||
pointer-events: none;
|
|
||||||
border: 6px solid transparent;
|
|
||||||
background: transparent;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Directions */
|
|
||||||
|
|
||||||
.leaflet-tooltip-bottom {
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-top {
|
|
||||||
margin-top: -6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-bottom:before,
|
|
||||||
.leaflet-tooltip-top:before {
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-top:before {
|
|
||||||
bottom: 0;
|
|
||||||
margin-bottom: -12px;
|
|
||||||
border-top-color: #fff;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-bottom:before {
|
|
||||||
top: 0;
|
|
||||||
margin-top: -12px;
|
|
||||||
margin-left: -6px;
|
|
||||||
border-bottom-color: #fff;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-left {
|
|
||||||
margin-left: -6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-right {
|
|
||||||
margin-left: 6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-left:before,
|
|
||||||
.leaflet-tooltip-right:before {
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -6px;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-left:before {
|
|
||||||
right: 0;
|
|
||||||
margin-right: -12px;
|
|
||||||
border-left-color: #fff;
|
|
||||||
}
|
|
||||||
.leaflet-tooltip-right:before {
|
|
||||||
left: 0;
|
|
||||||
margin-left: -12px;
|
|
||||||
border-right-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Printing */
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
/* Prevent printers from removing background-images of controls. */
|
|
||||||
.leaflet-control {
|
|
||||||
-webkit-print-color-adjust: exact;
|
|
||||||
print-color-adjust: exact;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,40 +0,0 @@
|
||||||
.maplibregl-inspect_popup {
|
|
||||||
color: #333;
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_feature:not(:last-child) {
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_layer:before {
|
|
||||||
content: '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_layer {
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_property {
|
|
||||||
display: table-row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_property-value {
|
|
||||||
display: table-cell;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-inspect_property-name {
|
|
||||||
display: table-cell;
|
|
||||||
padding-right: 10px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-inspect {
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333333' preserveAspectRatio='xMidYMid meet' viewBox='-10 -10 60 60'%3E%3Cg%3E%3Cpath d='m15 21.6q0-2 1.5-3.5t3.5-1.5 3.5 1.5 1.5 3.5-1.5 3.6-3.5 1.4-3.5-1.4-1.5-3.6z m18.4 11.1l-6.4-6.5q1.4-2.1 1.4-4.6 0-3.4-2.5-5.8t-5.9-2.4-5.9 2.4-2.5 5.8 2.5 5.9 5.9 2.5q2.4 0 4.6-1.4l7.4 7.4q-0.9 0.6-2 0.6h-20q-1.3 0-2.3-0.9t-1.1-2.3l0.1-26.8q0-1.3 1-2.3t2.3-0.9h13.4l10 10v19.3z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
|
|
||||||
}
|
|
||||||
|
|
||||||
.maplibregl-ctrl-map {
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333333' viewBox='-10 -10 60 60' preserveAspectRatio='xMidYMid meet'%3E%3Cg%3E%3Cpath d='m25 31.640000000000004v-19.766666666666673l-10-3.511666666666663v19.766666666666666z m9.140000000000008-26.640000000000004q0.8599999999999923 0 0.8599999999999923 0.8600000000000003v25.156666666666666q0 0.625-0.625 0.783333333333335l-9.375 3.1999999999999993-10-3.5133333333333354-8.906666666666668 3.4383333333333326-0.2333333333333334 0.07833333333333314q-0.8616666666666664 0-0.8616666666666664-0.8599999999999994v-25.156666666666663q0-0.625 0.6233333333333331-0.7833333333333332l9.378333333333334-3.198333333333334 10 3.5133333333333336 8.905000000000001-3.4383333333333344z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@ import { openMbTilesWrapper } from './mbtiles_wrapper.js';
|
||||||
|
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
const packageJson = JSON.parse(
|
const packageJson = JSON.parse(
|
||||||
fs.readFileSync(
|
fs.readFileSync(
|
||||||
path.dirname(fileURLToPath(import.meta.url)) + '/../package.json',
|
path.dirname(fileURLToPath(import.meta.url)) + '/../package.json',
|
||||||
|
@ -113,12 +114,13 @@ export const serve_data = {
|
||||||
let headers = fetchTile.headers;
|
let headers = fetchTile.headers;
|
||||||
let isGzipped = data.slice(0, 2).indexOf(Buffer.from([0x1f, 0x8b])) === 0;
|
let isGzipped = data.slice(0, 2).indexOf(Buffer.from([0x1f, 0x8b])) === 0;
|
||||||
|
|
||||||
|
if (isGzipped) {
|
||||||
|
data = await gunzipP(data);
|
||||||
|
isGzipped = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (tileJSONFormat === 'pbf') {
|
if (tileJSONFormat === 'pbf') {
|
||||||
if (options.dataDecoratorFunc) {
|
if (options.dataDecoratorFunc) {
|
||||||
if (isGzipped) {
|
|
||||||
data = await gunzipP(data);
|
|
||||||
isGzipped = false;
|
|
||||||
}
|
|
||||||
data = options.dataDecoratorFunc(
|
data = options.dataDecoratorFunc(
|
||||||
req.params.id,
|
req.params.id,
|
||||||
'data',
|
'data',
|
||||||
|
@ -259,8 +261,8 @@ export const serve_data = {
|
||||||
|
|
||||||
let data = fetchTile.data;
|
let data = fetchTile.data;
|
||||||
var param = {
|
var param = {
|
||||||
long: bbox[0],
|
long: bbox[0].toFixed(7),
|
||||||
lat: bbox[1],
|
lat: bbox[1].toFixed(7),
|
||||||
encoding,
|
encoding,
|
||||||
format,
|
format,
|
||||||
tile_size: TILE_SIZE,
|
tile_size: TILE_SIZE,
|
||||||
|
|
|
@ -6,6 +6,7 @@ export const serve_rendered = {
|
||||||
init: (options, repo, programOpts) => {},
|
init: (options, repo, programOpts) => {},
|
||||||
add: (options, repo, params, id, programOpts, dataResolver) => {},
|
add: (options, repo, params, id, programOpts, dataResolver) => {},
|
||||||
remove: (repo, id) => {},
|
remove: (repo, id) => {},
|
||||||
|
clear: (repo) => {},
|
||||||
getTerrainElevation: (data, param) => {
|
getTerrainElevation: (data, param) => {
|
||||||
param['elevation'] = 'not supported in light';
|
param['elevation'] = 'not supported in light';
|
||||||
return param;
|
return param;
|
||||||
|
|
|
@ -15,7 +15,6 @@ import '@maplibre/maplibre-gl-native';
|
||||||
import advancedPool from 'advanced-pool';
|
import advancedPool from 'advanced-pool';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import util from 'util';
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import clone from 'clone';
|
import clone from 'clone';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
|
@ -1028,10 +1027,19 @@ export const serve_rendered = {
|
||||||
* @param {object} params Parameters object.
|
* @param {object} params Parameters object.
|
||||||
* @param {string} id ID of the item.
|
* @param {string} id ID of the item.
|
||||||
* @param {object} programOpts - An object containing the program options
|
* @param {object} programOpts - An object containing the program options
|
||||||
|
* @param {object} style pre-fetched/read StyleJSON object.
|
||||||
* @param {Function} dataResolver Function to resolve data.
|
* @param {Function} dataResolver Function to resolve data.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
add: async function (options, repo, params, id, programOpts, dataResolver) {
|
add: async function (
|
||||||
|
options,
|
||||||
|
repo,
|
||||||
|
params,
|
||||||
|
id,
|
||||||
|
programOpts,
|
||||||
|
style,
|
||||||
|
dataResolver,
|
||||||
|
) {
|
||||||
const map = {
|
const map = {
|
||||||
renderers: [],
|
renderers: [],
|
||||||
renderersStatic: [],
|
renderersStatic: [],
|
||||||
|
@ -1041,7 +1049,7 @@ export const serve_rendered = {
|
||||||
|
|
||||||
const { publicUrl, verbose } = programOpts;
|
const { publicUrl, verbose } = programOpts;
|
||||||
|
|
||||||
let styleJSON;
|
const styleJSON = clone(style);
|
||||||
/**
|
/**
|
||||||
* Creates a pool of renderers.
|
* Creates a pool of renderers.
|
||||||
* @param {number} ratio Pixel ratio
|
* @param {number} ratio Pixel ratio
|
||||||
|
@ -1230,12 +1238,6 @@ export const serve_rendered = {
|
||||||
|
|
||||||
const styleFile = params.style;
|
const styleFile = params.style;
|
||||||
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
||||||
try {
|
|
||||||
styleJSON = JSON.parse(await fsp.readFile(styleJSONPath));
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Error parsing style file');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (styleJSON.sprite) {
|
if (styleJSON.sprite) {
|
||||||
if (!Array.isArray(styleJSON.sprite)) {
|
if (!Array.isArray(styleJSON.sprite)) {
|
||||||
|
@ -1458,7 +1460,25 @@ export const serve_rendered = {
|
||||||
}
|
}
|
||||||
delete repo[id];
|
delete repo[id];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Removes all items from the repository.
|
||||||
|
* @param {object} repo Repository object.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
clear: function (repo) {
|
||||||
|
Object.keys(repo).forEach((id) => {
|
||||||
|
const item = repo[id];
|
||||||
|
if (item) {
|
||||||
|
item.map.renderers.forEach((pool) => {
|
||||||
|
pool.close();
|
||||||
|
});
|
||||||
|
item.map.renderersStatic.forEach((pool) => {
|
||||||
|
pool.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
delete repo[id];
|
||||||
|
});
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Get the elevation of terrain tile data by rendering it to a canvas image
|
* Get the elevation of terrain tile data by rendering it to a canvas image
|
||||||
* @param {object} data The background color (or empty string for transparent).
|
* @param {object} data The background color (or empty string for transparent).
|
||||||
|
|
|
@ -196,9 +196,10 @@ export const serve_style = {
|
||||||
* @param {object} params Parameters object containing style path
|
* @param {object} params Parameters object containing style path
|
||||||
* @param {string} id ID of the style.
|
* @param {string} id ID of the style.
|
||||||
* @param {object} programOpts - An object containing the program options
|
* @param {object} programOpts - An object containing the program options
|
||||||
|
* @param {object} style pre-fetched/read StyleJSON object.
|
||||||
* @param {Function} reportTiles Function for reporting tile sources.
|
* @param {Function} reportTiles Function for reporting tile sources.
|
||||||
* @param {Function} reportFont Function for reporting font usage
|
* @param {Function} reportFont Function for reporting font usage
|
||||||
* @returns {boolean} true if add is succesful
|
* @returns {boolean} true if add is successful
|
||||||
*/
|
*/
|
||||||
add: function (
|
add: function (
|
||||||
options,
|
options,
|
||||||
|
@ -206,21 +207,14 @@ export const serve_style = {
|
||||||
params,
|
params,
|
||||||
id,
|
id,
|
||||||
programOpts,
|
programOpts,
|
||||||
|
style,
|
||||||
reportTiles,
|
reportTiles,
|
||||||
reportFont,
|
reportFont,
|
||||||
) {
|
) {
|
||||||
const { publicUrl } = programOpts;
|
const { publicUrl } = programOpts;
|
||||||
const styleFile = path.resolve(options.paths.styles, params.style);
|
const styleFile = path.resolve(options.paths.styles, params.style);
|
||||||
|
const styleJSON = clone(style);
|
||||||
|
|
||||||
let styleFileData;
|
|
||||||
try {
|
|
||||||
styleFileData = fs.readFileSync(styleFile); // TODO: could be made async if this function was
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`Error reading style file "${params.style}"`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styleJSON = JSON.parse(styleFileData);
|
|
||||||
const validationErrors = validateStyleMin(styleJSON);
|
const validationErrors = validateStyleMin(styleJSON);
|
||||||
if (validationErrors.length > 0) {
|
if (validationErrors.length > 0) {
|
||||||
console.log(`The file "${params.style}" is not a valid style file:`);
|
console.log(`The file "${params.style}" is not a valid style file:`);
|
||||||
|
|
|
@ -178,10 +178,29 @@ async function start(opts) {
|
||||||
* @param {object} item - The style configuration object.
|
* @param {object} item - The style configuration object.
|
||||||
* @param {boolean} allowMoreData - Whether to allow adding more data sources.
|
* @param {boolean} allowMoreData - Whether to allow adding more data sources.
|
||||||
* @param {boolean} reportFonts - Whether to report fonts.
|
* @param {boolean} reportFonts - Whether to report fonts.
|
||||||
* @returns {void}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
function addStyle(id, item, allowMoreData, reportFonts) {
|
async function addStyle(id, item, allowMoreData, reportFonts) {
|
||||||
let success = true;
|
let success = true;
|
||||||
|
|
||||||
|
let styleJSON;
|
||||||
|
try {
|
||||||
|
if (isValidHttpUrl(item.style)) {
|
||||||
|
const res = await fetch(item.style);
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`fetch error ${res.status}`);
|
||||||
|
}
|
||||||
|
styleJSON = await res.json();
|
||||||
|
} else {
|
||||||
|
const styleFile = path.resolve(options.paths.styles, item.style);
|
||||||
|
const styleFileData = await fs.promises.readFile(styleFile);
|
||||||
|
styleJSON = JSON.parse(styleFileData);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`Error getting style file "${item.style}"`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (item.serve_data !== false) {
|
if (item.serve_data !== false) {
|
||||||
success = serve_style.add(
|
success = serve_style.add(
|
||||||
options,
|
options,
|
||||||
|
@ -189,6 +208,7 @@ async function start(opts) {
|
||||||
item,
|
item,
|
||||||
id,
|
id,
|
||||||
opts,
|
opts,
|
||||||
|
styleJSON,
|
||||||
(styleSourceId, protocol) => {
|
(styleSourceId, protocol) => {
|
||||||
let dataItemId;
|
let dataItemId;
|
||||||
for (const id of Object.keys(data)) {
|
for (const id of Object.keys(data)) {
|
||||||
|
@ -246,6 +266,7 @@ async function start(opts) {
|
||||||
item,
|
item,
|
||||||
id,
|
id,
|
||||||
opts,
|
opts,
|
||||||
|
styleJSON,
|
||||||
function dataResolver(styleSourceId) {
|
function dataResolver(styleSourceId) {
|
||||||
let fileType;
|
let fileType;
|
||||||
let inputFile;
|
let inputFile;
|
||||||
|
@ -271,6 +292,7 @@ async function start(opts) {
|
||||||
item.serve_rendered = false;
|
item.serve_rendered = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of Object.keys(config.styles || {})) {
|
for (const id of Object.keys(config.styles || {})) {
|
||||||
|
@ -279,8 +301,7 @@ async function start(opts) {
|
||||||
console.log(`Missing "style" property for ${id}`);
|
console.log(`Missing "style" property for ${id}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
startupPromises.push(addStyle(id, item, true, true));
|
||||||
addStyle(id, item, true, true);
|
|
||||||
}
|
}
|
||||||
startupPromises.push(
|
startupPromises.push(
|
||||||
serve_font(options, serving.fonts, opts).then((sub) => {
|
serve_font(options, serving.fonts, opts).then((sub) => {
|
||||||
|
@ -743,6 +764,7 @@ async function start(opts) {
|
||||||
app,
|
app,
|
||||||
server,
|
server,
|
||||||
startupPromise,
|
startupPromise,
|
||||||
|
serving,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -777,8 +799,13 @@ export async function server(opts) {
|
||||||
|
|
||||||
running.server.shutdown(async () => {
|
running.server.shutdown(async () => {
|
||||||
const restarted = await start(opts);
|
const restarted = await start(opts);
|
||||||
|
if (!isLight) {
|
||||||
|
serve_rendered.clear(running.serving.rendered);
|
||||||
|
}
|
||||||
running.server = restarted.server;
|
running.server = restarted.server;
|
||||||
running.app = restarted.app;
|
running.app = restarted.app;
|
||||||
|
running.startupPromise = restarted.startupPromise;
|
||||||
|
running.serving = restarted.serving;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return running;
|
return running;
|
||||||
|
|
Loading…
Reference in a new issue