Compare commits

..

17 commits

Author SHA1 Message Date
4b1ffd489f Aggiorna README.md
Some checks failed
CodeQL / Analyze (push) Has been cancelled
The Pipeline / Fetch branch (push) Has been cancelled
The Pipeline / CI (push) Has been cancelled
The Pipeline / CT (push) Has been cancelled
The Pipeline / Automerge Dependabot PRs (push) Has been cancelled
2025-03-27 16:44:48 +08:00
Andrew Calcutt
cd613e2fb5
Update PUBLISHING.md (#1480) 2025-03-17 09:58:26 -04:00
Andrew Calcutt
3e521a7d92
v5.2.0 (#1479) 2025-03-17 09:18:40 -04:00
Andrew Calcutt
d88fbb7c55
Fix light version docker entrypoint permissions (#1478)
* put back entrypoint chmod

* bump to 5.2.0-pre.3

* move chown

* put back manual build steps

* Update PUBLISHING.md
2025-03-16 23:25:45 -04:00
Andrew Calcutt
6d4ab40b96
Test light version in ct workflow - fix sqlite build in light (#1477)
* Test light version in ct workflow
* make light builder two part
2025-03-16 19:12:09 -04:00
Andrew Calcutt
5441a10488
v5.2.0 pre.1 (#1476)
* 5.2.0-pre.1

* Update CHANGELOG.md
2025-03-16 15:04:12 -04:00
RJ Johnston
8a7d9957fb
fix: resolves Unimplemented type: 3 error for geojson format (#1465)
* fix: resolves Unimplemented type: 3 error for geojson format

* fix: removing duplicate zlib import

* fix: remove redundant change to headers

* revert fix decimal length

* lint fix

---------

Co-authored-by: Andrew Calcutt <acalcutt@techidiots.net>
2025-03-16 14:51:12 -04:00
dependabot[bot]
6d1c617752
fix(deps): bump axios from 1.7.9 to 1.8.2 (#1475)
Bumps [axios](https://github.com/axios/axios) from 1.7.9 to 1.8.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.9...v1.8.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-16 18:01:08 +00:00
Andrew Calcutt
3881219fee
fix ci - add canvas build dependencies to ci workflow (#1474)
* add canvas depends
2025-03-16 13:43:51 -04:00
Yoel Ridgway-Lopez
3110cab18f
feat: Fetch style from url (#1462)
* made the serve_style.add and addStyle functions async and return promises

* added fetching to addStyle() function and parsed it into serve_style and serve_rendered

* fixed linting issues

* removed async from synchronous functions

* added fetch example to docs
2025-02-28 23:45:51 -05:00
Andrew Calcutt
f2b48acb61
v5.2.0-pre.0 (#1461)
* Update .gitignore

* v5.2.0-pre.0

* Update CHANGELOG.md
2025-02-08 22:50:26 -05:00
Miko
6e0006ffcf
limit elevation lat/long decimal places to 7 (#1457) 2025-02-08 22:32:51 -05:00
Miko
6ef12fba6c
Use npm packages for public/resources (#1427)
* refactor dockerfile

* add build dockerfile

* use node_module files instead of local mirrors

* add copyfiles to global scope

* add leaflet-hash

* re-add pipefail

* refactor dockerfile

* add build dockerfile

* use node_module files instead of local mirrors

* add copyfiles to global scope

* add leaflet-hash

* re-add pipefail

* set automerge target to minor

* fix invalid node version

* refactor light dockerfile

---------

Co-authored-by: Miko <miko@local.host>
Co-authored-by: Miko <miko@none>
Co-authored-by: Andrew Calcutt <acalcutt@techidiots.net>
2025-02-08 22:09:25 -05:00
Miko
3d8bf78974
fix memory leak on SIGHUP (#1455) 2025-02-06 15:55:09 -05:00
Miko
1d60dd6afc
use ttf files of googlefonts/opensans (#1447)
- fixes browser console warning on the index page regarding too large kerning table included in the original font

Co-authored-by: Miko <miko@none>
2025-01-26 15:31:34 -05:00
Andrew Calcutt
7662cb84ce
v5.1.3 (#1453) 2025-01-26 12:49:53 -05:00
Miko
467203e125
fix sighup (#1452) 2025-01-25 14:14:57 -05:00
33 changed files with 3962 additions and 5326 deletions

View file

@ -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

View file

@ -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:

View file

@ -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
View file

@ -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

View file

@ -1,5 +1,18 @@
# 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
* Fix SIGHUP (broken since 5.1.x) (https://github.com/maptiler/tileserver-gl/pull/1452) by @okimiko
## 5.1.2 ## 5.1.2
* Fix broken light (invalid use of heavy dependencies) (https://github.com/maptiler/tileserver-gl/pull/1449) by @okimiko * Fix broken light (invalid use of heavy dependencies) (https://github.com/maptiler/tileserver-gl/pull/1449) by @okimiko

View file

@ -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
View 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/*

View file

@ -1,50 +1,81 @@
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

View file

@ -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.

View file

@ -1,5 +1,32 @@
![tileserver-gl](https://cloud.githubusercontent.com/assets/59284/18173467/fa3aa2ca-7069-11e6-86b1-0f1266befeb6.jpeg) ![tileserver-gl](https://cloud.githubusercontent.com/assets/59284/18173467/fa3aa2ca-7069-11e6-86b1-0f1266befeb6.jpeg)
# 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
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/maptiler/tileserver-gl/pipeline.yml)](https://github.com/maptiler/tileserver-gl/actions/workflows/pipeline.yml) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/maptiler/tileserver-gl/pipeline.yml)](https://github.com/maptiler/tileserver-gl/actions/workflows/pipeline.yml)
[![Docker Hub](https://img.shields.io/badge/docker-hub-blue.svg)](https://hub.docker.com/r/maptiler/tileserver-gl/) [![Docker Hub](https://img.shields.io/badge/docker-hub-blue.svg)](https://hub.docker.com/r/maptiler/tileserver-gl/)

View file

@ -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

4938
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,17 @@
{ {
"name": "tileserver-gl", "name": "tileserver-gl",
"version": "5.1.2", "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",

View file

@ -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]);
} }

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 (tileJSONFormat === 'pbf') {
if (options.dataDecoratorFunc) {
if (isGzipped) { if (isGzipped) {
data = await gunzipP(data); data = await gunzipP(data);
isGzipped = false; isGzipped = false;
} }
if (tileJSONFormat === 'pbf') {
if (options.dataDecoratorFunc) {
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,

View file

@ -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;

View file

@ -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).

View file

@ -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:`);

View 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,
}; };
} }
/** /**
@ -775,10 +797,15 @@ export async function server(opts) {
console.log(`Caught signal ${signal}, refreshing`); console.log(`Caught signal ${signal}, refreshing`);
console.log('Stopping server and reloading config'); console.log('Stopping server and reloading config');
running.server.shutdown(() => { running.server.shutdown(async () => {
const restarted = 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;