mirror of
https://github.com/maputnik/editor.git
synced 2026-08-25 22:47:39 +00:00
Compare commits
52 Commits
v2.1.1
..
6655297ddb
| Author | SHA1 | Date | |
|---|---|---|---|
| 6655297ddb | |||
| 7ecd5e847f | |||
| 1890001bf4 | |||
| 79e547dd91 | |||
| 016cb25fad | |||
| c5a98a6c02 | |||
| 9885f1c303 | |||
| 9079bf1730 | |||
| 0de0e52fef | |||
| 3e6994084c | |||
| 891bcf1777 | |||
| 69e4888d71 | |||
| 2a3e7ea4bb | |||
| a97287a66e | |||
| 9a866179b7 | |||
| 84e9a73d86 | |||
| 1b1668cdbf | |||
| 53fbc1ffe9 | |||
| b357e1f352 | |||
| c5f6d51ea1 | |||
| 86a94b9576 | |||
| 117f37139e | |||
| 39aef39b72 | |||
| 1657aa4676 | |||
| b09d41e41d | |||
| f17f529ede | |||
| f12af91a55 | |||
| e87e122067 | |||
| b070cea0a5 | |||
| e104bda7b6 | |||
| 6af3165418 | |||
| b1d4b53548 | |||
| 36d80d5e91 | |||
| 69124d0752 | |||
| 405b8aa951 | |||
| d50ea76347 | |||
| c6174a57d9 | |||
| 43892305a8 | |||
| af01346279 | |||
| dd6b40c943 | |||
| 687f9abaf2 | |||
| 172d4d5278 | |||
| b03af2c039 | |||
| 6089cde302 | |||
| 25cf61a825 | |||
| 0f1000c5b0 | |||
| fa4ece22cf | |||
| d940c02faf | |||
| 00f431c50e | |||
| 60785f53bc | |||
| 32fa02d289 | |||
| bab95cd6b1 |
@@ -1,14 +1,17 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 2
|
||||
open-pull-requests-limit: 20
|
||||
versioning-strategy: increase
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 2
|
||||
versioning-strategy: increase
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Automerge Dependabot
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
dependabot:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.actor == 'dependabot[bot]' }}
|
||||
steps:
|
||||
- name: Dependabot metadata
|
||||
id: metadata
|
||||
uses: dependabot/fetch-metadata@v2.2.0
|
||||
with:
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
- name: Approve Dependabot PRs
|
||||
run: gh pr review --approve "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{github.event.pull_request.html_url}}
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
- name: Enable auto-merge for Dependabot PRs
|
||||
run: gh pr merge --auto --squash "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{github.event.pull_request.html_url}}
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
start: npm run start
|
||||
browser: ${{ matrix.browser }}
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ${{ github.workspace }}/.nyc_output/out.json
|
||||
verbose: true
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
./build/bump-version-changelog.js ${{ inputs.version }}
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
commit-message: Bump version to ${{ inputs.version }}
|
||||
branch: bump-version-to-${{ inputs.version }}
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
run: npm run build
|
||||
|
||||
- name: Upload to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: dist
|
||||
|
||||
@@ -66,7 +66,6 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build
|
||||
npm run build-desktop
|
||||
|
||||
- name: Tag commit and push
|
||||
@@ -78,8 +77,7 @@ jobs:
|
||||
|
||||
- name: Create Archives
|
||||
run: |
|
||||
zip -r dist dist
|
||||
zip -r desktop desktop/bin/
|
||||
zip -r "desktop-${{ steps.package-version.outputs.current-version }}" desktop/bin/
|
||||
|
||||
- name: Build Release Notes
|
||||
id: release_notes
|
||||
@@ -97,7 +95,7 @@ jobs:
|
||||
tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
bodyFile: ${{ steps.release_notes.outputs.release_notes }}
|
||||
artifacts: "dist.zip,desktop.zip"
|
||||
artifacts: "desktop-${{ steps.package-version.outputs.current-version }}.zip"
|
||||
allowUpdates: true
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
@@ -36,3 +36,11 @@ public
|
||||
/cypress/screenshots
|
||||
/dist/
|
||||
/desktop/version.go
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Window metadata files
|
||||
/desktop/winres/winres.json
|
||||
/desktop/*.syso
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
## main
|
||||
|
||||
### ✨ Features and improvements
|
||||
- Add german translation
|
||||
- Use same version number for web and desktop versions
|
||||
- Add scheme type options for vector/raster tile
|
||||
- Add `tileSize` field for raster and raster-dem tile sources
|
||||
- Update Protomaps Light gallery style to v4
|
||||
- Add support to edit local files on the file system if supported by the browser
|
||||
- Upgrade to MapLibre LG JS v5
|
||||
- Upgrade Vite 6 and Cypress 14 ([#970](https://github.com/maplibre/maputnik/pull/970))
|
||||
- Upgrade OpenLayers from v6 to v10
|
||||
- _...Add new stuff here..._
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
@@ -36,6 +36,8 @@ Maputnik is written in typescript and is using [React](https://github.com/facebo
|
||||
|
||||
We ensure building and developing Maputnik works with the [current active LTS Node.js version and above](https://github.com/nodejs/Release#release-schedule).
|
||||
|
||||
Check out our [Internationalization guide](./src/locales/README.md) for UI text related changes.
|
||||
|
||||
### Getting Involved
|
||||
Join the #maplibre or #maputnik slack channel at OSMUS: get an invite at https://slack.openstreetmap.us/ Read the the below guide in order to get familiar with how we do things around here.
|
||||
|
||||
@@ -70,7 +72,6 @@ npm run lint-css
|
||||
npm run sort-styles
|
||||
```
|
||||
|
||||
|
||||
## Tests
|
||||
For E2E testing we use [Cypress](https://www.cypress.io/)
|
||||
|
||||
|
||||
@@ -61,9 +61,42 @@ describe("modals", () => {
|
||||
});
|
||||
|
||||
describe("sources", () => {
|
||||
beforeEach(() => {
|
||||
when.setStyle("layer");
|
||||
when.click("nav:sources");
|
||||
});
|
||||
|
||||
it("active sources");
|
||||
it("public source");
|
||||
it("add new source");
|
||||
|
||||
it("add new source", () => {
|
||||
let sourceId = "n1z2v3r";
|
||||
when.setValue("modal:sources.add.source_id", sourceId);
|
||||
when.select("modal:sources.add.source_type", "tile_vector");
|
||||
when.select("modal:sources.add.scheme_type", "tms");
|
||||
when.click("modal:sources.add.add_source");
|
||||
when.wait(200);
|
||||
then(
|
||||
get.styleFromLocalStorage().then((style) => style.sources[sourceId])
|
||||
).shouldInclude({
|
||||
scheme: "tms",
|
||||
});
|
||||
});
|
||||
|
||||
it("add new raster source", () => {
|
||||
let sourceId = "rastertest";
|
||||
when.setValue("modal:sources.add.source_id", sourceId);
|
||||
when.select("modal:sources.add.source_type", "tile_raster");
|
||||
when.select("modal:sources.add.scheme_type", "xyz");
|
||||
when.setValue("modal:sources.add.tile_size", "128");
|
||||
when.click("modal:sources.add.add_source");
|
||||
when.wait(200);
|
||||
then(
|
||||
get.styleFromLocalStorage().then((style) => style.sources[sourceId])
|
||||
).shouldInclude({
|
||||
tileSize: 128,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("inspect", () => {
|
||||
@@ -160,6 +193,18 @@ describe("modals", () => {
|
||||
).shouldInclude({ "maputnik:thunderforest_access_token": apiKey });
|
||||
});
|
||||
|
||||
it("stadia access token", () => {
|
||||
let apiKey = "testing123";
|
||||
when.setValue(
|
||||
"modal:settings.maputnik:stadia_access_token",
|
||||
apiKey
|
||||
);
|
||||
when.click("modal:settings.name");
|
||||
then(
|
||||
get.styleFromLocalStorage().then((style) => style.metadata)
|
||||
).shouldInclude({ "maputnik:stadia_access_token": apiKey });
|
||||
});
|
||||
|
||||
it("style renderer", () => {
|
||||
cy.on("uncaught:exception", () => false); // this is due to the fact that this is an invalid style for openlayers
|
||||
when.select("modal:settings.maputnik:renderer", "ol");
|
||||
|
||||
+13
-8
@@ -1,16 +1,22 @@
|
||||
SOURCEDIR=.
|
||||
SOURCES := $(shell find $(SOURCEDIR) -name '*.go')
|
||||
BINARY=maputnik
|
||||
DESKTOP_VERSION := 1.1.1
|
||||
EDITOR_VERSION := $(shell node -p "require('../package.json').version")
|
||||
VERSION := $(shell node -p "require('../package.json').version")
|
||||
GOPATH := $(if $(GOPATH),$(GOPATH),$(HOME)/go)
|
||||
GOBIN := $(if $(GOBIN),$(GOBIN),$(HOME)/go/bin)
|
||||
|
||||
all: $(BINARY)
|
||||
|
||||
$(BINARY): $(GOBIN)/gox $(SOURCES) version.go rice-box.go
|
||||
$(BINARY): $(GOBIN)/gox $(GOBIN)/go-winres $(SOURCES) version.go rice-box.go winres/winres.json
|
||||
$(GOBIN)/go-winres make --product-version=$(VERSION)
|
||||
$(GOBIN)/gox -osarch "windows/amd64 linux/amd64 darwin/amd64" -output "bin/{{.OS}}/${BINARY}"
|
||||
|
||||
winres/winres.json: winres/winres_template.json
|
||||
sed 's/{{.Version}}/$(VERSION)/g' winres/winres_template.json > $@
|
||||
|
||||
$(GOBIN)/go-winres:
|
||||
go install github.com/tc-hib/go-winres@latest
|
||||
|
||||
# Copy the current release into ./editor/maputnik so it can be
|
||||
# embedded in the binary
|
||||
editor/pull_release:
|
||||
@@ -23,13 +29,12 @@ $(GOBIN)/gox:
|
||||
$(GOBIN)/rice:
|
||||
go install github.com/GeertJohan/go.rice/rice@v1.0.3
|
||||
|
||||
# Embed the current version numbers in the executable by writing version.go
|
||||
# Embed the current version number in the executable by writing version.go
|
||||
.PHONY: version.go
|
||||
version.go:
|
||||
@echo "// DO NOT EDIT: Autogenerated by Makefile\n" > version.go
|
||||
@echo "package main\n" >> version.go
|
||||
@echo "const DesktopVersion = \"$(DESKTOP_VERSION)\"" >> version.go
|
||||
@echo "const EditorVersion = \"$(EDITOR_VERSION)\"" >> version.go
|
||||
@printf "// DO NOT EDIT: Autogenerated by Makefile\n" > version.go
|
||||
@printf "package main\n" >> version.go
|
||||
@printf "const Version = \"$(VERSION)\"\n" >> version.go
|
||||
|
||||
rice-box.go: $(GOBIN)/rice editor/pull_release
|
||||
$(GOBIN)/rice embed-go
|
||||
|
||||
+9
-8
@@ -1,4 +1,5 @@
|
||||
# Maputnik Desktop [][github-action-ci]
|
||||
|
||||
---
|
||||
|
||||
A Golang based cross platform executable for integrating Maputnik locally.
|
||||
@@ -11,7 +12,7 @@ Report issues on [maplibre/maputnik](https://github.com/maplibre/maputnik).
|
||||
|
||||
## Install
|
||||
|
||||
You can download a single binary for Linux, OSX or Windows from [the latest releases of **maplibre/maputnik**](https://github.com/maplibre/maputnik/editor/releases/latest).
|
||||
You can download a zip file containing desktop binaries for Linux, OSX and Windows from [the latest releases of **maplibre/maputnik**](https://github.com/maplibre/maputnik/releases/latest).
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -53,12 +54,12 @@ maputnik --static ./localFolder
|
||||
|
||||
`maputnik` exposes the configured styles via a HTTP API.
|
||||
|
||||
| Method | Description
|
||||
|---------------------------------|---------------------------------------
|
||||
| `GET /styles` | List the ID of all configured style files
|
||||
| `GET /styles/{filename}` | Get contents of a single style file
|
||||
| `PUT /styles/{filename}` | Update contents of a style file
|
||||
| `WEBSOCKET /ws` | Listen to change events for the configured style files
|
||||
| Method | Description |
|
||||
| ------------------------ | ------------------------------------------------------ |
|
||||
| `GET /styles` | List the ID of all configured style files |
|
||||
| `GET /styles/{filename}` | Get contents of a single style file |
|
||||
| `PUT /styles/{filename}` | Update contents of a style file |
|
||||
| `WEBSOCKET /ws` | Listen to change events for the configured style files |
|
||||
|
||||
### Build
|
||||
|
||||
@@ -69,4 +70,4 @@ npm install
|
||||
npm run build-desktop
|
||||
```
|
||||
|
||||
You should now find the `maputnik` binary in your `bin` directory.
|
||||
You should now find the `maputnik` binary in your `desktop/bin` directory.
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "maputnik"
|
||||
app.Usage = "Server for integrating Maputnik locally"
|
||||
app.Version = "Editor: " + EditorVersion + "; Desktop: " + DesktopVersion
|
||||
app.Version = Version
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"RT_GROUP_ICON": {
|
||||
"APP": {
|
||||
"0000": [
|
||||
"../../src/img/maputnik.png"
|
||||
]
|
||||
}
|
||||
},
|
||||
"RT_MANIFEST": {
|
||||
"#1": {
|
||||
"0409": {
|
||||
"identity": {
|
||||
"name": "Maputnik",
|
||||
"version": "{{.Version}}"
|
||||
},
|
||||
"description": "A MapLibre GL visual style editor",
|
||||
"minimum-os": "win7",
|
||||
"execution-level": "as invoker",
|
||||
"ui-access": false,
|
||||
"auto-elevate": false,
|
||||
"dpi-awareness": "system",
|
||||
"disable-theming": false,
|
||||
"disable-window-filtering": false,
|
||||
"high-resolution-scrolling-aware": false,
|
||||
"ultra-high-resolution-scrolling-aware": false,
|
||||
"long-path-aware": false,
|
||||
"printer-driver-isolation": false,
|
||||
"gdi-scaling": false,
|
||||
"segment-heap": false,
|
||||
"use-common-controls-v6": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"RT_VERSION": {
|
||||
"#1": {
|
||||
"0000": {
|
||||
"fixed": {
|
||||
"file_version": "{{.Version}}",
|
||||
"product_version": "{{.Version}}"
|
||||
},
|
||||
"info": {
|
||||
"0409": {
|
||||
"Comments": "https://github.com/maplibre/maputnik",
|
||||
"CompanyName": "Maputnik",
|
||||
"FileDescription": "A MapLibre GL visual style editor",
|
||||
"FileVersion": "{{.Version}}",
|
||||
"InternalName": "Maputnik",
|
||||
"LegalCopyright": "MIT License",
|
||||
"LegalTrademarks": "",
|
||||
"OriginalFilename": "Maputnik.exe",
|
||||
"PrivateBuild": "",
|
||||
"ProductName": "Maputnik",
|
||||
"ProductVersion": "{{.Version}}",
|
||||
"SpecialBuild": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
export default {
|
||||
output: 'src/locales/$LOCALE/$NAMESPACE.json',
|
||||
locales: [ 'ja', 'he','zh' ],
|
||||
locales: [ 'de', 'fr', 'he', 'ja', 'zh' ],
|
||||
|
||||
// Because some keys are dynamically generated, i18next-parser can't detect them.
|
||||
// We add these keys manually, so we don't want to remove them.
|
||||
|
||||
Generated
+3736
-1774
File diff suppressed because it is too large
Load Diff
+40
-39
@@ -23,25 +23,22 @@
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/maplibre/maputnik#readme",
|
||||
"dependencies": {
|
||||
"@mapbox/mapbox-gl-rtl-text": "^0.2.3",
|
||||
"@maplibre/maplibre-gl-geocoder": "^1.6.0",
|
||||
"@maplibre/maplibre-gl-inspect": "^1.6.3",
|
||||
"@maplibre/maplibre-gl-style-spec": "^20.1.1",
|
||||
"@mapbox/mapbox-gl-rtl-text": "^0.3.0",
|
||||
"@maplibre/maplibre-gl-geocoder": "^1.7.1",
|
||||
"@maplibre/maplibre-gl-inspect": "^1.7.1",
|
||||
"@maplibre/maplibre-gl-style-spec": "^23.1.0",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@mdi/react": "^1.6.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
||||
"@typescript-eslint/parser": "^7.3.1",
|
||||
"array-move": "^4.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"classnames": "^2.5.1",
|
||||
"codemirror": "^5.65.2",
|
||||
"color": "^4.2.3",
|
||||
"cypress-plugin-tab": "^1.0.5",
|
||||
"detect-browser": "^5.3.0",
|
||||
"events": "^3.3.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"i18next": "^24.2.1",
|
||||
"i18next-browser-languagedetector": "^8.0.2",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"json-stringify-pretty-compact": "^4.0.0",
|
||||
"json-to-ast": "^2.1.0",
|
||||
@@ -53,10 +50,10 @@
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"maplibre-gl": "^4.1.2",
|
||||
"maplibre-gl": "^5.0.1",
|
||||
"maputnik-design": "github:maputnik/design#172b06c",
|
||||
"ol": "^6.14.1",
|
||||
"ol-mapbox-style": "^7.1.1",
|
||||
"ol": "^10.3.1",
|
||||
"ol-mapbox-style": "^12.4.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-accessible-accordion": "^5.0.0",
|
||||
@@ -66,17 +63,16 @@
|
||||
"react-autocomplete": "^1.8.1",
|
||||
"react-collapse": "^5.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-file-reader-input": "^2.0.0",
|
||||
"react-i18next": "^15.0.1",
|
||||
"react-i18next": "^15.4.0",
|
||||
"react-icon-base": "^2.1.2",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-sortable-hoc": "^2.0.0",
|
||||
"reconnecting-websocket": "^4.4.0",
|
||||
"sass": "^1.72.0",
|
||||
"slugify": "^1.6.6",
|
||||
"string-hash": "^1.1.3",
|
||||
"url": "^0.11.3"
|
||||
"url": "^0.11.4"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"esversion": 6
|
||||
@@ -96,12 +92,12 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/code-coverage": "^3.12.30",
|
||||
"@cypress/code-coverage": "^3.13.10",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||
"@rollup/plugin-replace": "^5.0.5",
|
||||
"@shellygo/cypress-test-utils": "^2.1.9",
|
||||
"@rollup/plugin-replace": "^6.0.2",
|
||||
"@shellygo/cypress-test-utils": "^4.1.11",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/color": "^3.0.6",
|
||||
"@types/color": "^4.2.0",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/geojson": "^7946.0.14",
|
||||
@@ -112,38 +108,43 @@
|
||||
"@types/lodash.get": "^4.4.9",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/lodash.throttle": "^4.1.9",
|
||||
"@types/mocha": "^10.0.6",
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/randomcolor": "^0.5.9",
|
||||
"@types/react": "^18.2.67",
|
||||
"@types/react-aria-menubutton": "^6.2.14",
|
||||
"@types/react-aria-modal": "^4.0.10",
|
||||
"@types/react-autocomplete": "^1.8.10",
|
||||
"@types/react-aria-modal": "^5.0.0",
|
||||
"@types/react-autocomplete": "^1.8.11",
|
||||
"@types/react-collapse": "^5.0.4",
|
||||
"@types/react-color": "^3.0.12",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@types/react-color": "^3.0.13",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"@types/react-file-reader-input": "^2.0.4",
|
||||
"@types/react-icon-base": "^2.1.6",
|
||||
"@types/string-hash": "^1.1.3",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@types/wicg-file-system-access": "^2023.10.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
||||
"@typescript-eslint/parser": "^7.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"cors": "^2.8.5",
|
||||
"cypress": "^13.13.0",
|
||||
"cypress": "^14.0.0",
|
||||
"cypress-plugin-tab": "^1.0.5",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"i18next-parser": "^9.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.18",
|
||||
"i18next-parser": "^9.1.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"mocha": "^10.3.0",
|
||||
"mocha": "^11.0.1",
|
||||
"postcss": "^8.4.38",
|
||||
"react-hot-loader": "^4.13.1",
|
||||
"stylelint": "^16.2.1",
|
||||
"stylelint-config-recommended-scss": "^14.0.0",
|
||||
"stylelint-scss": "^6.2.1",
|
||||
"sass": "^1.72.0",
|
||||
"stylelint": "^16.13.2",
|
||||
"stylelint-config-recommended-scss": "^14.1.0",
|
||||
"stylelint-scss": "^6.10.1",
|
||||
"typescript": "^5.4.3",
|
||||
"uuid": "^9.0.1",
|
||||
"vite": "^5.2.6",
|
||||
"vite-plugin-istanbul": "^6.0.0"
|
||||
"uuid": "^11.0.5",
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-istanbul": "^6.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -129,6 +129,7 @@ type AppState = {
|
||||
export: boolean
|
||||
debug: boolean
|
||||
}
|
||||
fileHandle: FileSystemFileHandle | null
|
||||
}
|
||||
|
||||
export default class App extends React.Component<any, AppState> {
|
||||
@@ -284,6 +285,7 @@ export default class App extends React.Component<any, AppState> {
|
||||
openlayersDebugOptions: {
|
||||
debugToolbox: false,
|
||||
},
|
||||
fileHandle: null,
|
||||
}
|
||||
|
||||
this.layerWatcher = new LayerWatcher({
|
||||
@@ -611,7 +613,8 @@ export default class App extends React.Component<any, AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
openStyle = (styleObj: StyleSpecification & {id: string}) => {
|
||||
openStyle = (styleObj: StyleSpecification & {id: string}, fileHandle: FileSystemFileHandle | null) => {
|
||||
this.setState({fileHandle: fileHandle});
|
||||
styleObj = this.setDefaultValues(styleObj)
|
||||
this.onStyleChanged(styleObj)
|
||||
}
|
||||
@@ -847,6 +850,10 @@ export default class App extends React.Component<any, AppState> {
|
||||
this.setModal(modalName, !this.state.isOpen[modalName]);
|
||||
}
|
||||
|
||||
onSetFileHandle(fileHandle: FileSystemFileHandle | null) {
|
||||
this.setState({fileHandle: fileHandle});
|
||||
}
|
||||
|
||||
onChangeOpenlayersDebug = (key: keyof AppState["openlayersDebugOptions"], value: boolean) => {
|
||||
this.setState({
|
||||
openlayersDebugOptions: {
|
||||
@@ -949,11 +956,14 @@ export default class App extends React.Component<any, AppState> {
|
||||
onStyleChanged={this.onStyleChanged}
|
||||
isOpen={this.state.isOpen.export}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
||||
fileHandle={this.state.fileHandle}
|
||||
onSetFileHandle={this.onSetFileHandle}
|
||||
/>
|
||||
<ModalOpen
|
||||
isOpen={this.state.isOpen.open}
|
||||
onStyleOpen={this.openStyle}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'open')}
|
||||
fileHandle={this.state.fileHandle}
|
||||
/>
|
||||
<ModalSources
|
||||
mapStyle={this.state.mapStyle}
|
||||
|
||||
@@ -2,7 +2,15 @@ import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import {detect} from 'detect-browser';
|
||||
|
||||
import {MdFileDownload, MdOpenInBrowser, MdSettings, MdLayers, MdHelpOutline, MdFindInPage, MdLanguage} from 'react-icons/md'
|
||||
import {
|
||||
MdOpenInBrowser,
|
||||
MdSettings,
|
||||
MdLayers,
|
||||
MdHelpOutline,
|
||||
MdFindInPage,
|
||||
MdLanguage,
|
||||
MdSave
|
||||
} from 'react-icons/md'
|
||||
import pkgJson from '../../package.json'
|
||||
//@ts-ignore
|
||||
import maputnikLogo from 'maputnik-design/logos/logo-color.svg?inline'
|
||||
@@ -216,8 +224,8 @@ class AppToolbarInternal extends React.Component<AppToolbarInternalProps> {
|
||||
<IconText>{t("Open")}</IconText>
|
||||
</ToolbarAction>
|
||||
<ToolbarAction wdKey="nav:export" onClick={this.props.onToggleModal.bind(this, 'export')}>
|
||||
<MdFileDownload />
|
||||
<IconText>{t("Export")}</IconText>
|
||||
<MdSave />
|
||||
<IconText>{t("Save")}</IconText>
|
||||
</ToolbarAction>
|
||||
<ToolbarAction wdKey="nav:sources" onClick={this.props.onToggleModal.bind(this, 'sources')}>
|
||||
<MdLayers />
|
||||
@@ -230,7 +238,7 @@ class AppToolbarInternal extends React.Component<AppToolbarInternalProps> {
|
||||
|
||||
<ToolbarSelect wdKey="nav:inspect">
|
||||
<MdFindInPage />
|
||||
<label>{t("View")}
|
||||
<IconText>{t("View")}
|
||||
<select
|
||||
className="maputnik-select"
|
||||
data-wd-key="maputnik-select"
|
||||
@@ -254,12 +262,12 @@ class AppToolbarInternal extends React.Component<AppToolbarInternalProps> {
|
||||
})}
|
||||
</optgroup>
|
||||
</select>
|
||||
</label>
|
||||
</IconText>
|
||||
</ToolbarSelect>
|
||||
|
||||
<ToolbarSelect wdKey="nav:language">
|
||||
<MdLanguage />
|
||||
<label>{t("Language")}
|
||||
<IconText>Language
|
||||
<select
|
||||
className="maputnik-select"
|
||||
data-wd-key="maputnik-lang-select"
|
||||
@@ -274,7 +282,7 @@ class AppToolbarInternal extends React.Component<AppToolbarInternalProps> {
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</label>
|
||||
</IconText>
|
||||
</ToolbarSelect>
|
||||
|
||||
<ToolbarLink href={"https://github.com/maplibre/maputnik/wiki"}>
|
||||
|
||||
@@ -56,7 +56,9 @@ export default class Block extends React.Component<BlockProps, BlockState> {
|
||||
if (event.nativeEvent.target.nodeName !== "INPUT" && !contains) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
event.preventDefault();
|
||||
if (event.nativeEvent.target.nodeName !== "A") {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -18,6 +18,8 @@ type DocProps = {
|
||||
'sdk-support'?: {
|
||||
[key: string]: typeof headers
|
||||
}
|
||||
docUrl?: string,
|
||||
docUrlLinkText?: string
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,7 +27,7 @@ export default class Doc extends React.Component<DocProps> {
|
||||
render () {
|
||||
const {fieldSpec} = this.props;
|
||||
|
||||
const {doc, values} = fieldSpec;
|
||||
const {doc, values, docUrl, docUrlLinkText} = fieldSpec;
|
||||
const sdkSupport = fieldSpec['sdk-support'];
|
||||
|
||||
const renderValues = (
|
||||
@@ -85,7 +87,12 @@ export default class Doc extends React.Component<DocProps> {
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
{docUrl && docUrlLinkText &&
|
||||
<div className="SpecDoc__learn-more">
|
||||
<a href={docUrl} target="_blank" rel="noreferrer">{docUrlLinkText}</a>
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,14 +318,7 @@ class LayerListContainerInternal extends React.Component<LayerListContainerInter
|
||||
}
|
||||
}
|
||||
|
||||
// The next two lines have react-refresh/only-export-components disabled because they are
|
||||
// internal components that are not intended to be used outside of this file.
|
||||
// For some reason, the linter is not recognizing these components correctly.
|
||||
// When these components are migrated to functional components, the HOCs will no longer be needed
|
||||
// and the comments can be removed.
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
const LayerListContainer = withTranslation()(LayerListContainerInternal);
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)
|
||||
|
||||
type LayerListProps = LayerListContainerProps & {
|
||||
|
||||
@@ -14,6 +14,7 @@ import '../libs/maplibre-rtl'
|
||||
import MaplibreGeocoder, { MaplibreGeocoderApi, MaplibreGeocoderApiConfig } from '@maplibre/maplibre-gl-geocoder';
|
||||
import '@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css';
|
||||
import { withTranslation, WithTranslation } from 'react-i18next'
|
||||
import i18next from 'i18next'
|
||||
|
||||
function renderPopup(popup: JSX.Element, mountNode: ReactDOM.Container): HTMLElement {
|
||||
ReactDOM.render(popup, mountNode);
|
||||
@@ -67,9 +68,11 @@ type MapMaplibreGlInternalProps = {
|
||||
} & WithTranslation;
|
||||
|
||||
type MapMaplibreGlState = {
|
||||
map: Map | null
|
||||
inspect: MaplibreInspect | null
|
||||
zoom?: number
|
||||
map: Map | null;
|
||||
inspect: MaplibreInspect | null;
|
||||
geocoder: MaplibreGeocoder | null;
|
||||
zoomControl: ZoomControl | null;
|
||||
zoom?: number;
|
||||
};
|
||||
|
||||
class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps, MapMaplibreGlState> {
|
||||
@@ -87,7 +90,12 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
||||
this.state = {
|
||||
map: null,
|
||||
inspect: null,
|
||||
geocoder: null,
|
||||
zoomControl: null,
|
||||
}
|
||||
i18next.on('languageChanged', () => {
|
||||
this.forceUpdate();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +133,7 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
||||
this.state.inspect!.render();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -152,9 +161,9 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
||||
map.showCollisionBoxes = mapOpts.showCollisionBoxes!;
|
||||
map.showOverdrawInspector = mapOpts.showOverdrawInspector!;
|
||||
|
||||
this.initGeocoder(map);
|
||||
let geocoder = this.initGeocoder(map);
|
||||
|
||||
const zoomControl = new ZoomControl(this.props.t("Zoom:"));
|
||||
const zoomControl = new ZoomControl();
|
||||
map.addControl(zoomControl, 'top-right');
|
||||
|
||||
const nav = new MapLibreGl.NavigationControl({visualizePitch:true});
|
||||
@@ -189,6 +198,8 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
||||
this.setState({
|
||||
map,
|
||||
inspect,
|
||||
geocoder,
|
||||
zoomControl,
|
||||
zoom: map.getZoom()
|
||||
});
|
||||
})
|
||||
@@ -261,10 +272,13 @@ class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps,
|
||||
maplibregl: MapLibreGl,
|
||||
});
|
||||
map.addControl(geocoder, 'top-left');
|
||||
return geocoder;
|
||||
}
|
||||
|
||||
render() {
|
||||
const t = this.props.t;
|
||||
this.state.geocoder?.setPlaceholder(t("Search"));
|
||||
this.state.zoomControl?.setLabel(t("Zoom:"));
|
||||
return <div
|
||||
className="maputnik-map__map"
|
||||
role="region"
|
||||
|
||||
@@ -85,10 +85,11 @@ class MapOpenLayersInternal extends React.Component<MapOpenLayersInternalProps,
|
||||
componentDidMount() {
|
||||
this.overlay = new Overlay({
|
||||
element: this.popupContainer!,
|
||||
autoPan: true,
|
||||
autoPanAnimation: {
|
||||
duration: 250
|
||||
}
|
||||
autoPan: {
|
||||
animation: {
|
||||
duration: 250
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
|
||||
@@ -4,8 +4,8 @@ import {saveAs} from 'file-saver'
|
||||
import {version} from 'maplibre-gl/package.json'
|
||||
import {format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import type {StyleSpecification} from 'maplibre-gl'
|
||||
import {MdFileDownload} from 'react-icons/md'
|
||||
import { WithTranslation, withTranslation } from 'react-i18next';
|
||||
import {MdMap, MdSave} from 'react-icons/md'
|
||||
import {WithTranslation, withTranslation} from 'react-i18next';
|
||||
|
||||
import FieldString from './FieldString'
|
||||
import InputButton from './InputButton'
|
||||
@@ -15,6 +15,7 @@ import fieldSpecAdditional from '../libs/field-spec-additional'
|
||||
|
||||
|
||||
const MAPLIBRE_GL_VERSION = version;
|
||||
const showSaveFilePickerAvailable = typeof window.showSaveFilePicker === "function";
|
||||
|
||||
|
||||
type ModalExportInternalProps = {
|
||||
@@ -22,12 +23,14 @@ type ModalExportInternalProps = {
|
||||
onStyleChanged(...args: unknown[]): unknown
|
||||
isOpen: boolean
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
onSetFileHandle(fileHandle: FileSystemFileHandle | null): unknown
|
||||
fileHandle: FileSystemFileHandle | null
|
||||
} & WithTranslation;
|
||||
|
||||
|
||||
class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
|
||||
tokenizedStyle () {
|
||||
tokenizedStyle() {
|
||||
return format(
|
||||
style.stripAccessTokens(
|
||||
style.replaceAccessTokens(this.props.mapStyle)
|
||||
@@ -35,8 +38,8 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
);
|
||||
}
|
||||
|
||||
exportName () {
|
||||
if(this.props.mapStyle.name) {
|
||||
exportName() {
|
||||
if (this.props.mapStyle.name) {
|
||||
return Slugify(this.props.mapStyle.name, {
|
||||
replacement: '_',
|
||||
remove: /[*\-+~.()'"!:]/g,
|
||||
@@ -47,7 +50,7 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
}
|
||||
}
|
||||
|
||||
downloadHtml() {
|
||||
createHtml() {
|
||||
const tokenStyle = this.tokenizedStyle();
|
||||
const htmlTitle = this.props.mapStyle.name || this.props.t("Map");
|
||||
const html = `<!DOCTYPE html>
|
||||
@@ -81,11 +84,58 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
saveAs(blob, exportName + ".html");
|
||||
}
|
||||
|
||||
downloadStyle() {
|
||||
async saveStyle() {
|
||||
const tokenStyle = this.tokenizedStyle();
|
||||
const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"});
|
||||
const exportName = this.exportName();
|
||||
saveAs(blob, exportName + ".json");
|
||||
|
||||
// it is not guaranteed that the File System Access API is available on all
|
||||
// browsers. If the function is not available, a fallback behavior is used.
|
||||
if (!showSaveFilePickerAvailable) {
|
||||
const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"});
|
||||
const exportName = this.exportName();
|
||||
saveAs(blob, exportName + ".json");
|
||||
return;
|
||||
}
|
||||
|
||||
let fileHandle = this.props.fileHandle;
|
||||
if (fileHandle == null) {
|
||||
fileHandle = await this.createFileHandle();
|
||||
this.props.onSetFileHandle(fileHandle)
|
||||
if (fileHandle == null) return;
|
||||
}
|
||||
|
||||
const writable = await fileHandle.createWritable();
|
||||
await writable.write(tokenStyle);
|
||||
await writable.close();
|
||||
this.props.onOpenToggle();
|
||||
}
|
||||
|
||||
async saveStyleAs() {
|
||||
const tokenStyle = this.tokenizedStyle();
|
||||
|
||||
const fileHandle = await this.createFileHandle();
|
||||
this.props.onSetFileHandle(fileHandle)
|
||||
if (fileHandle == null) return;
|
||||
|
||||
const writable = await fileHandle.createWritable();
|
||||
await writable.write(tokenStyle);
|
||||
await writable.close();
|
||||
this.props.onOpenToggle();
|
||||
}
|
||||
|
||||
async createFileHandle(): Promise<FileSystemFileHandle | null> {
|
||||
const pickerOpts: SaveFilePickerOptions = {
|
||||
types: [
|
||||
{
|
||||
description: "json",
|
||||
accept: {"application/json": [".json"]},
|
||||
},
|
||||
],
|
||||
suggestedName: this.exportName(),
|
||||
};
|
||||
|
||||
const fileHandle = await window.showSaveFilePicker(pickerOpts) as FileSystemFileHandle;
|
||||
this.props.onSetFileHandle(fileHandle)
|
||||
return fileHandle;
|
||||
}
|
||||
|
||||
changeMetadataProperty(property: string, value: any) {
|
||||
@@ -107,14 +157,14 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
data-wd-key="modal:export"
|
||||
isOpen={this.props.isOpen}
|
||||
onOpenToggle={this.props.onOpenToggle}
|
||||
title={t('Export Style')}
|
||||
title={t('Save Style')}
|
||||
className="maputnik-export-modal"
|
||||
>
|
||||
|
||||
<section className="maputnik-modal-section">
|
||||
<h1>{t("Download Style")}</h1>
|
||||
<h1>{t("Save Style")}</h1>
|
||||
<p>
|
||||
{t("Download a JSON style to your computer.")}
|
||||
{t("Save the JSON style to your computer.")}
|
||||
</p>
|
||||
|
||||
<div>
|
||||
@@ -130,21 +180,29 @@ class ModalExportInternal extends React.Component<ModalExportInternalProps> {
|
||||
value={(this.props.mapStyle.metadata || {} as any)['maputnik:thunderforest_access_token']}
|
||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
|
||||
/>
|
||||
<FieldString
|
||||
label={fsa.maputnik.stadia_access_token.label}
|
||||
fieldSpec={fsa.maputnik.stadia_access_token}
|
||||
value={(this.props.mapStyle.metadata || {} as any)['maputnik:stadia_access_token']}
|
||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:stadia_access_token")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="maputnik-modal-export-buttons">
|
||||
<InputButton
|
||||
onClick={this.downloadStyle.bind(this)}
|
||||
>
|
||||
<MdFileDownload />
|
||||
{t("Download Style")}
|
||||
<InputButton onClick={this.saveStyle.bind(this)}>
|
||||
<MdSave/>
|
||||
{t("Save")}
|
||||
</InputButton>
|
||||
{showSaveFilePickerAvailable && (
|
||||
<InputButton onClick={this.saveStyleAs.bind(this)}>
|
||||
<MdSave/>
|
||||
{t("Save as")}
|
||||
</InputButton>
|
||||
)}
|
||||
|
||||
<InputButton
|
||||
onClick={this.downloadHtml.bind(this)}
|
||||
>
|
||||
<MdFileDownload />
|
||||
{t("Download HTML")}
|
||||
<InputButton onClick={this.createHtml.bind(this)}>
|
||||
<MdMap/>
|
||||
{t("Create HTML")}
|
||||
</InputButton>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -47,6 +47,7 @@ type ModalOpenInternalProps = {
|
||||
isOpen: boolean
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
onStyleOpen(...args: unknown[]): unknown
|
||||
fileHandle: FileSystemFileHandle | null
|
||||
} & WithTranslation;
|
||||
|
||||
type ModalOpenState = {
|
||||
@@ -135,10 +136,44 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
|
||||
this.onStyleSelect(this.state.styleUrl);
|
||||
}
|
||||
|
||||
onUpload = (_: any, files: Result[]) => {
|
||||
onOpenFile = async () => {
|
||||
this.clearError();
|
||||
|
||||
const pickerOpts: OpenFilePickerOptions = {
|
||||
types: [
|
||||
{
|
||||
description: "json",
|
||||
accept: { "application/json": [".json"] },
|
||||
},
|
||||
],
|
||||
multiple: false,
|
||||
};
|
||||
|
||||
const [fileHandle] = await window.showOpenFilePicker(pickerOpts) as Array<FileSystemFileHandle>;
|
||||
const file = await fileHandle.getFile();
|
||||
const content = await file.text();
|
||||
|
||||
let mapStyle;
|
||||
try {
|
||||
mapStyle = JSON.parse(content)
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: (err as Error).toString()
|
||||
});
|
||||
return;
|
||||
}
|
||||
mapStyle = style.ensureStyleValidity(mapStyle)
|
||||
|
||||
this.props.onStyleOpen(mapStyle, fileHandle);
|
||||
this.onOpenToggle();
|
||||
return file;
|
||||
}
|
||||
|
||||
// it is not guaranteed that the File System Access API is available on all
|
||||
// browsers. If the function is not available, a fallback behavior is used.
|
||||
onFileChanged = async (_: any, files: Result[]) => {
|
||||
const [, file] = files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
this.clearError();
|
||||
|
||||
reader.readAsText(file, "UTF-8");
|
||||
@@ -196,7 +231,7 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
data-wd-key="modal:open"
|
||||
@@ -206,11 +241,20 @@ class ModalOpenInternal extends React.Component<ModalOpenInternalProps, ModalOpe
|
||||
>
|
||||
{errorElement}
|
||||
<section className="maputnik-modal-section">
|
||||
<h1>{t("Upload Style")}</h1>
|
||||
<p>{t("Upload a JSON style from your computer.")}</p>
|
||||
<FileReaderInput onChange={this.onUpload} tabIndex={-1} aria-label={t("Style file")}>
|
||||
<InputButton className="maputnik-upload-button"><MdFileUpload /> {t("Upload")}</InputButton>
|
||||
</FileReaderInput>
|
||||
<h1>{t("Open local Style")}</h1>
|
||||
<p>{t("Open a local JSON style from your computer.")}</p>
|
||||
<div>
|
||||
{typeof window.showOpenFilePicker === "function" ? (
|
||||
<InputButton
|
||||
className="maputnik-big-button"
|
||||
onClick={this.onOpenFile}><MdFileUpload/> {t("Open Style")}
|
||||
</InputButton>
|
||||
) : (
|
||||
<FileReaderInput onChange={this.onFileChanged} tabIndex={-1} aria-label={t("Open Style")}>
|
||||
<InputButton className="maputnik-upload-button"><MdFileUpload /> {t("Open Style")}</InputButton>
|
||||
</FileReaderInput>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="maputnik-modal-section">
|
||||
|
||||
@@ -156,6 +156,14 @@ class ModalSettingsInternal extends React.Component<ModalSettingsInternalProps>
|
||||
onChange={onChangeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
|
||||
/>
|
||||
|
||||
<FieldString
|
||||
label={fsa.maputnik.stadia_access_token.label}
|
||||
fieldSpec={fsa.maputnik.stadia_access_token}
|
||||
data-wd-key="modal:settings.maputnik:stadia_access_token"
|
||||
value={metadata['maputnik:stadia_access_token']}
|
||||
onChange={onChangeMetadataProperty.bind(this, "maputnik:stadia_access_token")}
|
||||
/>
|
||||
|
||||
<FieldArray
|
||||
label={t("Center")}
|
||||
fieldSpec={latest.$root.center}
|
||||
|
||||
@@ -42,7 +42,7 @@ class PublicSource extends React.Component<PublicSourceProps> {
|
||||
|
||||
function editorMode(source: SourceSpecification) {
|
||||
if(source.type === 'raster') {
|
||||
if(source.tiles) return 'tilexyz_raster'
|
||||
if(source.tiles) return 'tile_raster'
|
||||
return 'tilejson_raster'
|
||||
}
|
||||
if(source.type === 'raster-dem') {
|
||||
@@ -50,7 +50,7 @@ function editorMode(source: SourceSpecification) {
|
||||
return 'tilejson_raster-dem'
|
||||
}
|
||||
if(source.type === 'vector') {
|
||||
if(source.tiles) return 'tilexyz_vector'
|
||||
if(source.tiles) return 'tile_vector'
|
||||
return 'tilejson_vector'
|
||||
}
|
||||
if(source.type === 'geojson') {
|
||||
@@ -142,21 +142,24 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
type: 'vector',
|
||||
url: (source as VectorSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
|
||||
}
|
||||
case 'tilexyz_vector': return {
|
||||
case 'tile_vector': return {
|
||||
type: 'vector',
|
||||
tiles: (source as VectorSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`],
|
||||
minzoom: (source as VectorSourceSpecification).minzoom || 0,
|
||||
maxzoom: (source as VectorSourceSpecification).maxzoom || 14
|
||||
maxzoom: (source as VectorSourceSpecification).maxzoom || 14,
|
||||
scheme: (source as VectorSourceSpecification).scheme || 'xyz'
|
||||
}
|
||||
case 'tilejson_raster': return {
|
||||
type: 'raster',
|
||||
url: (source as RasterSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
|
||||
}
|
||||
case 'tilexyz_raster': return {
|
||||
case 'tile_raster': return {
|
||||
type: 'raster',
|
||||
tiles: (source as RasterSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`],
|
||||
tiles: (source as RasterSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
|
||||
minzoom: (source as RasterSourceSpecification).minzoom || 0,
|
||||
maxzoom: (source as RasterSourceSpecification).maxzoom || 14
|
||||
maxzoom: (source as RasterSourceSpecification).maxzoom || 14,
|
||||
scheme: (source as RasterSourceSpecification).scheme || 'xyz',
|
||||
tileSize: (source as RasterSourceSpecification).tileSize || 512,
|
||||
}
|
||||
case 'tilejson_raster-dem': return {
|
||||
type: 'raster-dem',
|
||||
@@ -164,9 +167,10 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
}
|
||||
case 'tilexyz_raster-dem': return {
|
||||
type: 'raster-dem',
|
||||
tiles: (source as RasterDEMSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.pbf`],
|
||||
tiles: (source as RasterDEMSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
|
||||
minzoom: (source as RasterDEMSourceSpecification).minzoom || 0,
|
||||
maxzoom: (source as RasterDEMSourceSpecification).maxzoom || 14
|
||||
maxzoom: (source as RasterDEMSourceSpecification).maxzoom || 14,
|
||||
tileSize: (source as RasterDEMSourceSpecification).tileSize || 512
|
||||
}
|
||||
case 'image': return {
|
||||
type: 'image',
|
||||
@@ -222,6 +226,7 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
fieldSpec={{doc: t("Unique ID that identifies the source and is used in the layer to reference the source.")}}
|
||||
value={this.state.sourceId}
|
||||
onChange={(v: string) => this.setState({ sourceId: v})}
|
||||
data-wd-key="modal:sources.add.source_id"
|
||||
/>
|
||||
<FieldSelect
|
||||
label={t("Source Type")}
|
||||
@@ -230,9 +235,9 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
['geojson_json', t('GeoJSON (JSON)')],
|
||||
['geojson_url', t('GeoJSON (URL)')],
|
||||
['tilejson_vector', t('Vector (TileJSON URL)')],
|
||||
['tilexyz_vector', t('Vector (XYZ URLs)')],
|
||||
['tile_vector', t('Vector (Tile URLs)')],
|
||||
['tilejson_raster', t('Raster (TileJSON URL)')],
|
||||
['tilexyz_raster', t('Raster (XYZ URL)')],
|
||||
['tile_raster', t('Raster (Tile URLs)')],
|
||||
['tilejson_raster-dem', t('Raster DEM (TileJSON URL)')],
|
||||
['tilexyz_raster-dem', t('Raster DEM (XYZ URLs)')],
|
||||
['image', t('Image')],
|
||||
@@ -240,6 +245,7 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
]}
|
||||
onChange={mode => this.setState({mode: mode as EditorMode, source: this.defaultSource(mode as EditorMode)})}
|
||||
value={this.state.mode as string}
|
||||
data-wd-key="modal:sources.add.source_type"
|
||||
/>
|
||||
<ModalSourcesTypeEditor
|
||||
onChange={this.onChangeSource}
|
||||
@@ -249,6 +255,7 @@ class AddSource extends React.Component<AddSourceProps, AddSourceState> {
|
||||
<InputButton
|
||||
className="maputnik-add-source-button"
|
||||
onClick={this.onAdd}
|
||||
data-wd-key="modal:sources.add.add_source"
|
||||
>
|
||||
{t("Add Source")}
|
||||
</InputButton>
|
||||
|
||||
@@ -11,7 +11,7 @@ import FieldCheckbox from './FieldCheckbox'
|
||||
import { WithTranslation, withTranslation } from 'react-i18next';
|
||||
import { TFunction } from 'i18next'
|
||||
|
||||
export type EditorMode = "video" | "image" | "tilejson_vector" | "tilexyz_raster" | "tilejson_raster" | "tilexyz_raster-dem" | "tilejson_raster-dem" | "tilexyz_vector" | "geojson_url" | "geojson_json" | null;
|
||||
export type EditorMode = "video" | "image" | "tilejson_vector" | "tile_raster" | "tilejson_raster" | "tilexyz_raster-dem" | "tilejson_raster-dem" | "tile_vector" | "geojson_url" | "geojson_json" | null;
|
||||
|
||||
type TileJSONSourceEditorProps = {
|
||||
source: {
|
||||
@@ -45,6 +45,7 @@ type TileURLSourceEditorProps = {
|
||||
tiles: string[]
|
||||
minzoom: number
|
||||
maxzoom: number
|
||||
scheme: 'xyz' | 'tms'
|
||||
}
|
||||
onChange(...args: unknown[]): unknown
|
||||
children?: React.ReactNode
|
||||
@@ -73,6 +74,20 @@ class TileURLSourceEditor extends React.Component<TileURLSourceEditorProps> {
|
||||
const t = this.props.t;
|
||||
return <div>
|
||||
{this.renderTileUrls()}
|
||||
<FieldSelect
|
||||
label={t("Scheme Type")}
|
||||
fieldSpec={latest.source_vector.scheme}
|
||||
options={[
|
||||
['xyz', 'xyz (Slippy map tilenames scheme)'],
|
||||
['tms', 'tms (OSGeo spec scheme)'],
|
||||
]}
|
||||
onChange={scheme => this.props.onChange({
|
||||
...this.props.source,
|
||||
scheme
|
||||
})}
|
||||
value={this.props.source.scheme}
|
||||
data-wd-key="modal:sources.add.scheme_type"
|
||||
/>
|
||||
<FieldNumber
|
||||
label={t("Min Zoom")}
|
||||
fieldSpec={latest.source_vector.minzoom}
|
||||
@@ -291,11 +306,32 @@ class ModalSourcesTypeEditorInternal extends React.Component<ModalSourcesTypeEdi
|
||||
case 'geojson_url': return <GeoJSONSourceUrlEditor {...commonProps} />
|
||||
case 'geojson_json': return <GeoJSONSourceFieldJsonEditor {...commonProps} />
|
||||
case 'tilejson_vector': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_vector': return <TileURLSourceEditor {...commonProps} />
|
||||
case 'tile_vector': return <TileURLSourceEditor {...commonProps} />
|
||||
case 'tilejson_raster': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_raster': return <TileURLSourceEditor {...commonProps} />
|
||||
case 'tile_raster': return <TileURLSourceEditor {...commonProps}>
|
||||
<FieldNumber
|
||||
label={t("Tile Size")}
|
||||
fieldSpec={latest.source_raster.tileSize}
|
||||
onChange={tileSize => this.props.onChange({
|
||||
...this.props.source,
|
||||
tileSize: tileSize
|
||||
})}
|
||||
value={this.props.source.tileSize || latest.source_raster.tileSize.default}
|
||||
data-wd-key="modal:sources.add.tile_size"
|
||||
/>
|
||||
</TileURLSourceEditor>
|
||||
case 'tilejson_raster-dem': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_raster-dem': return <TileURLSourceEditor {...commonProps}>
|
||||
<FieldNumber
|
||||
label={t("Tile Size")}
|
||||
fieldSpec={latest.source_raster_dem.tileSize}
|
||||
onChange={tileSize => this.props.onChange({
|
||||
...this.props.source,
|
||||
tileSize: tileSize
|
||||
})}
|
||||
value={this.props.source.tileSize || latest.source_raster_dem.tileSize.default}
|
||||
data-wd-key="modal:sources.add.tile_size"
|
||||
/>
|
||||
<FieldSelect
|
||||
label={t("Encoding")}
|
||||
fieldSpec={latest.source_raster_dem.encoding}
|
||||
|
||||
+19
-1
@@ -5,6 +5,12 @@
|
||||
"url": "https://cdn.jsdelivr.net/gh/maputnik/editor@9cf74ca405d2be0608b57db8109cf3a6af5b9f49/src/config/empty-style.json",
|
||||
"thumbnail": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAQAAAAHDYbIAAAAEUlEQVR42mP8/58BDhiJ4wAA974H/U5Xe1oAAAAASUVORK5CYII="
|
||||
},
|
||||
{
|
||||
"id": "americana",
|
||||
"title": "Americana",
|
||||
"url": "https://americanamap.org/style.json",
|
||||
"thumbnail": "https://github.com/maplibre/maputnik/assets/649392/23fa75ad-63e6-43f5-8837-03cdb0428bac"
|
||||
},
|
||||
{
|
||||
"id": "dark-matter",
|
||||
"title": "Dark Matter",
|
||||
@@ -13,7 +19,7 @@
|
||||
},
|
||||
{
|
||||
"id": "maptiler-basic-gl-style",
|
||||
"title": "Maptiler Basic",
|
||||
"title": "MapTiler Basic",
|
||||
"url": "https://cdn.jsdelivr.net/gh/openmaptiles/klokantech-basic-gl-style@v1.10/style.json",
|
||||
"thumbnail": "https://maputnik.github.io/thumbnails/klokantech-basic.png"
|
||||
},
|
||||
@@ -59,12 +65,24 @@
|
||||
"url": "https://maputnik.github.io/osm-liberty/style.json",
|
||||
"thumbnail": "https://maputnik.github.io/thumbnails/osm-liberty.png"
|
||||
},
|
||||
{
|
||||
"id": "osm-openmaptiles",
|
||||
"title": "OSM OpenMapTiles",
|
||||
"url": "https://api.maptiler.com/maps/openstreetmap/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL",
|
||||
"thumbnail": "https://openmaptiles.org/img/styles/openmaptiles.png"
|
||||
},
|
||||
{
|
||||
"id": "positron",
|
||||
"title": "Positron",
|
||||
"url": "https://cdn.jsdelivr.net/gh/openmaptiles/positron-gl-style@v1.9/style.json",
|
||||
"thumbnail": "https://maputnik.github.io/thumbnails/positron.png"
|
||||
},
|
||||
{
|
||||
"id": "protomaps-light",
|
||||
"title": "Protomaps Light",
|
||||
"url": "https://api.protomaps.com/styles/v4/light/en.json?key=d828297496b11844",
|
||||
"thumbnail": "https://github.com/user-attachments/assets/911f9765-4a7d-4736-9ec0-f2d4c90ae587"
|
||||
},
|
||||
{
|
||||
"id": "stadia-outdoors",
|
||||
"title": "Stadia Outdoors",
|
||||
|
||||
+3
-1
@@ -4,9 +4,11 @@ import resourcesToBackend from "i18next-resources-to-backend";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
export const supportedLanguages = {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
"ja": "日本語",
|
||||
"fr": "Français",
|
||||
"he": "עברית",
|
||||
"ja": "日本語",
|
||||
"zh": "简体中文"
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -4,15 +4,25 @@ const spec = (t: TFunction) => ({
|
||||
maputnik: {
|
||||
maptiler_access_token: {
|
||||
label: t("MapTiler Access Token"),
|
||||
doc: t("Public access token for MapTiler Cloud.")
|
||||
doc: t("Public access token for MapTiler Cloud."),
|
||||
docUrl: "https://docs.maptiler.com/cloud/api/authentication-key/",
|
||||
docUrlLinkText: t("Learn More")
|
||||
},
|
||||
thunderforest_access_token: {
|
||||
label: t("Thunderforest Access Token"),
|
||||
doc: t("Public access token for Thunderforest services.")
|
||||
doc: t("Public access token for Thunderforest services."),
|
||||
docUrl: "https://www.thunderforest.com/docs/apikeys/",
|
||||
docUrlLinkText: t("Learn More")
|
||||
},
|
||||
stadia_access_token: {
|
||||
label: t("Stadia Maps API Key"),
|
||||
doc: t("API key for Stadia Maps."),
|
||||
docUrl: "https://docs.stadiamaps.com/authentication/",
|
||||
docUrlLinkText: t("Learn More")
|
||||
},
|
||||
style_renderer: {
|
||||
label: t("Style Renderer"),
|
||||
doc: t("Choose the default Maputnik renderer for this style."),
|
||||
doc: t("Choose the default Maputnik renderer for this style.")
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
+24
-6
@@ -55,10 +55,6 @@ function indexOfLayer(layers: LayerSpecification[], layerId: string) {
|
||||
}
|
||||
|
||||
function getAccessToken(sourceName: string, mapStyle: StyleSpecification, opts: {allowFallback?: boolean}) {
|
||||
if(sourceName === "thunderforest_transport" || sourceName === "thunderforest_outdoors") {
|
||||
sourceName = "thunderforest"
|
||||
}
|
||||
|
||||
const metadata = mapStyle.metadata || {} as any;
|
||||
let accessToken = metadata[`maputnik:${sourceName}_access_token`]
|
||||
|
||||
@@ -74,18 +70,38 @@ function replaceSourceAccessToken(mapStyle: StyleSpecification, sourceName: stri
|
||||
if(!source) return mapStyle
|
||||
if(!("url" in source) || !source.url) return mapStyle
|
||||
|
||||
const accessToken = getAccessToken(sourceName, mapStyle, opts)
|
||||
let authSourceName = sourceName
|
||||
if(sourceName === "thunderforest_transport" || sourceName === "thunderforest_outdoors") {
|
||||
authSourceName = "thunderforest"
|
||||
}
|
||||
else if (("url" in source) && source.url?.match(/\.stadiamaps\.com/)) {
|
||||
// The code currently usually assumes openmaptiles == MapTiler,
|
||||
// so we need to check the source URL.
|
||||
authSourceName = "stadia"
|
||||
}
|
||||
|
||||
const accessToken = getAccessToken(authSourceName, mapStyle, opts)
|
||||
|
||||
if(!accessToken) {
|
||||
// Early exit.
|
||||
return mapStyle;
|
||||
}
|
||||
|
||||
let sourceUrl: string
|
||||
if (authSourceName == "stadia") {
|
||||
// Stadia Maps does not always require an API key,
|
||||
// so there is no placeholder in our styles.
|
||||
// We append it at the end of the URL when exporting if necessary.
|
||||
sourceUrl = `${source.url}?api_key=${accessToken}`
|
||||
} else {
|
||||
sourceUrl = source.url.replace('{key}', accessToken)
|
||||
}
|
||||
|
||||
const changedSources = {
|
||||
...mapStyle.sources,
|
||||
[sourceName]: {
|
||||
...source,
|
||||
url: source.url.replace('{key}', accessToken)
|
||||
url: sourceUrl
|
||||
}
|
||||
}
|
||||
const changedStyle = {
|
||||
@@ -120,6 +136,8 @@ function stripAccessTokens(mapStyle: StyleSpecification) {
|
||||
...mapStyle.metadata as any
|
||||
};
|
||||
delete changedMetadata['maputnik:openmaptiles_access_token'];
|
||||
delete changedMetadata['maputnik:thunderforest_access_token'];
|
||||
delete changedMetadata['maputnik:stadia_access_token'];
|
||||
return {
|
||||
...mapStyle,
|
||||
metadata: changedMetadata
|
||||
|
||||
+10
-6
@@ -5,18 +5,14 @@ export default class ZoomControl {
|
||||
_container: HTMLDivElement | undefined = undefined;
|
||||
_textEl: HTMLSpanElement | null = null;
|
||||
|
||||
constructor(public label: string) {}
|
||||
constructor() {}
|
||||
|
||||
onAdd(map: Map) {
|
||||
this._map = map;
|
||||
this._container = document.createElement('div');
|
||||
this._container.className = 'maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-zoom';
|
||||
this._container.setAttribute("data-wd-key", "maplibre:ctrl-zoom");
|
||||
this._container.innerHTML = `
|
||||
${this.label} <span></span>
|
||||
`;
|
||||
this._textEl = this._container.querySelector("span");
|
||||
|
||||
this.setLabel("Zoom:");
|
||||
this.addEventListeners();
|
||||
|
||||
return this._container;
|
||||
@@ -25,6 +21,14 @@ export default class ZoomControl {
|
||||
updateZoomLevel() {
|
||||
this._textEl!.innerHTML = this._map!.getZoom().toFixed(2);
|
||||
}
|
||||
|
||||
setLabel(label: string) {
|
||||
this._container!.innerHTML = `
|
||||
${label} <span></span>
|
||||
`;
|
||||
this._textEl = this._container!.querySelector("span");
|
||||
this.updateZoomLevel();
|
||||
}
|
||||
|
||||
addEventListeners (){
|
||||
this._map!.on('render', () => this.updateZoomLevel());
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
## Internationalization
|
||||
|
||||
The process of internationalization is pretty straight forward for Maputnik.
|
||||
|
||||
## Add a new language
|
||||
|
||||
#### 1. Edit configuration
|
||||
|
||||
In order to add a new translation you'll need to add it to the configuration files. Please put it in alphabetical order.
|
||||
|
||||
- Open [/i18next-parser.config.ts](/i18next-parser.config.ts) and add the ISO Code of your language to the `locales` array.
|
||||
- Now, open [/src/i18n.ts](/src/i18n.ts) and add the ISO Code and localized name to the supported languages.
|
||||
|
||||
#### 2. Add the localized strings
|
||||
|
||||
Refresh the localization to generate a new directory under `/src/locales/` for your new language.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run i18n:refresh
|
||||
```
|
||||
|
||||
Replace every `__STRING_NOT_TRANSLATED__` value in the newly generated `translation.json` file with the according translation.
|
||||
Make sure all the keys are translated.
|
||||
|
||||
#### 3. Test your new locale
|
||||
|
||||
Finally, test your language locally by starting a local instance of Maputnik.
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
Consider adding your name as a helping person for the translation of new features.
|
||||
|
||||
## Add localization for a new feature
|
||||
|
||||
If you happen to add a feature which needs some text to be translated, update the translation files.
|
||||
After running, check your working copy for files and add/correct as needed.
|
||||
|
||||
```bash
|
||||
npm run i18n:refresh
|
||||
```
|
||||
|
||||
The following users can help you with the relevant languages:
|
||||
|
||||
| ISO Code | Language | User |
|
||||
|----------|--------------------|--------------------------------------------|
|
||||
| de | German | [@josxha](https://github.com/josxha) |
|
||||
| en | English | [@HarelM](https://github.com/HarelM) |
|
||||
| fr | French | [@lhapaipai](https://github.com/lhapaipai) |
|
||||
| hr | Hebrew | [@HarelM](https://github.com/HarelM) |
|
||||
| ja | Japanese | [@keichan34](https://github.com/keichan34) |
|
||||
| zh | Simplified Chinese | [@jieme](https://github.com/jieme) |
|
||||
|
||||
You can test the UI in different languages using the dropdown in the top menu
|
||||
Note that Maputnik automatically localize based on browser language settings and stores this language in local storage.
|
||||
You can use incognito mode to check a first time usage.
|
||||
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"Input value": "Eingabewert",
|
||||
"Data value": "Datenwert",
|
||||
"Output value": "Ausgabewert",
|
||||
"Function": "Funktion",
|
||||
"Select a type of data scale (default is 'categorical').": "Wähle eine Art Datenskala (Standard ist 'kategorisch').",
|
||||
"Base": "Basis",
|
||||
"Input a data property to base styles off of.": "Gib eine Dateneigenschaft ein, um Stile darauf zu basieren.",
|
||||
"Default": "Standard",
|
||||
"Stops": "Stopps",
|
||||
"Zoom": "Zoom",
|
||||
"Add stop": "Stopp hinzufügen",
|
||||
"Convert to expression": "In Ausdruck umwandeln",
|
||||
"Remove zoom level from stop": "Zoom-Stufe vom Stopp entfernen",
|
||||
"Revert from expression": "Vom Ausdruck zurücksetzen",
|
||||
"Delete expression": "Ausdruck löschen",
|
||||
"Convert property into a zoom function": "Eigenschaft in eine Zoom-Funktion umwandeln",
|
||||
"Convert property to data function": "Eigenschaft in eine Datenfunktion umwandeln",
|
||||
"Layer <1>{formatLayerId(layerId)}</1>: {parsed.data.message}": "Ebene <1>{formatLayerId(layerId)}</1>: {parsed.data.message}",
|
||||
"switch to layer": "zur Ebene wechseln",
|
||||
"Map": "Karte",
|
||||
"Inspect": "Untersuchen",
|
||||
"Deuteranopia filter": "Deuteranopie-Filter",
|
||||
"Protanopia filter": "Protanopie-Filter",
|
||||
"Tritanopia filter": "Tritanopie-Filter",
|
||||
"Achromatopsia filter": "Achromatopsie-Filter",
|
||||
"Layers list": "Ebenenliste",
|
||||
"Layer editor": "Ebenen-Editor",
|
||||
"Map view": "Kartenansicht",
|
||||
"Maputnik on GitHub": "Maputnik auf GitHub",
|
||||
"Open": "Öffnen",
|
||||
"Save": "Speichern",
|
||||
"Data Sources": "Datenquellen",
|
||||
"Style Settings": "Stileinstellungen",
|
||||
"View": "Ansicht",
|
||||
"Color accessibility": "Farbzugänglichkeit",
|
||||
"Help": "Hilfe",
|
||||
"Comments for the current layer. This is non-standard and not in the spec.": "Kommentare zur aktuellen Ebene. Das ist nicht standardmäßig und nicht in der Spezifikation.",
|
||||
"Comments": "Kommentare",
|
||||
"Comment...": "Dein Kommentar...",
|
||||
"Max Zoom": "Max-Zoom",
|
||||
"Min Zoom": "Min-Zoom",
|
||||
"Source": "Quelle",
|
||||
"Source Layer": "Quellenebene",
|
||||
"Type": "Typ",
|
||||
"Nested filters are not supported.": "Verschachtelte Filter werden nicht unterstützt.",
|
||||
"Upgrade to expression": "Aufrüsten zu Ausdruck",
|
||||
"Filter": "Filter",
|
||||
"every filter matches": "alle Filter passen",
|
||||
"no filter matches": "kein Filter passt",
|
||||
"any filter matches": "irgendein Filter passt",
|
||||
"Add filter": "Filter hinzufügen",
|
||||
"You've entered an old style filter.": "Du hast einen alten Filter-Stil eingegeben.",
|
||||
"Switch to filter editor.": "Zum Filter-Editor wechseln.",
|
||||
"Delete filter block": "Filterblock löschen",
|
||||
"Add value": "Wert hinzufügen",
|
||||
"Remove array item": "Element aus Array entfernen",
|
||||
"Press <1>ESC</1> to lose focus": "Drück <1>ESC</1>, um den Fokus zu verlieren",
|
||||
"Must provide protocol: <1>https://</1>": "Protokoll erforderlich: <1>https://</1>",
|
||||
"Must provide protocol: <1>http://</1> or <3>https://</3>": "Protokoll erforderlich: <1>http://</1> oder <3>https://</3>",
|
||||
"CORS policy won't allow fetching resources served over http from https, use a <1>https://</1> domain": "Die CORS-Politik erlaubt es nicht, Ressourcen über http von https zu laden, benutze eine <1>https://</1>-Domain",
|
||||
"Layer": "Ebene",
|
||||
"JSON Editor": "JSON-Editor",
|
||||
"Delete": "Löschen",
|
||||
"Duplicate": "Duplizieren",
|
||||
"Show": "Anzeigen",
|
||||
"Hide": "Verstecken",
|
||||
"Move layer up": "Ebene nach oben verschieben",
|
||||
"Move layer down": "Ebene nach unten verschieben",
|
||||
"Layer: {{layerId}}": "Ebene: {{layerId}}",
|
||||
"Layers": "Ebenen",
|
||||
"Collapse": "Einklappen",
|
||||
"Expand": "Ausklappen",
|
||||
"Add Layer": "Ebene hinzufügen",
|
||||
"Search": "Suche",
|
||||
"Zoom:": "Zoom:",
|
||||
"Close popup": "Popup schließen",
|
||||
"cursor:": "Mauszeiger:",
|
||||
"center:": "Zentrum:",
|
||||
"rotation:": "Rotation:",
|
||||
"Close modal": "Modale Fenster schließen",
|
||||
"Debug": "Debug",
|
||||
"Options": "Optionen",
|
||||
"Save Style": "Stil Speichern",
|
||||
"Save the JSON style to your computer.": "Speichere den JSON Stil auf deinem Computer.",
|
||||
"Save as": "Speichern unter",
|
||||
"Create HTML": "HTML erstellen",
|
||||
"Cancel": "Abbrechen",
|
||||
"Open Style": "Stil öffnen",
|
||||
"Open local Style": "Lokalen Stil öffnen",
|
||||
"Open a local JSON style from your computer.": "Öffne einen lokalen JSON Stil von deinem Computer.",
|
||||
"Load from URL": "Von URL laden",
|
||||
"Load from a URL. Note that the URL must have <1>CORS enabled</1>.": "Von einer URL laden. Beachte, dass die URL <1>CORS aktiviert</1> haben muss.",
|
||||
"Style URL": "Stil-URL",
|
||||
"Enter URL...": "URL eingeben...",
|
||||
"Gallery Styles": "Galerie-Stile",
|
||||
"Open one of the publicly available styles to start from.": "Öffne einen der öffentlich verfügbaren Stile, um zu starten.",
|
||||
"Loading style": "Stil wird geladen",
|
||||
"Loading: {{requestUrl}}": "Lädt: {{requestUrl}}",
|
||||
"Name": "Name",
|
||||
"Owner": "Besitzer",
|
||||
"Owner ID of the style. Used by Mapbox or future style APIs.": "Besitzer-ID des Stils. Wird von Mapbox oder zukünftigen Style-APIs verwendet.",
|
||||
"Sprite URL": "Sprite-URL",
|
||||
"Glyphs URL": "Glyphen-URL",
|
||||
"Center": "Mittelpunkt",
|
||||
"Bearing": "Ausrichtung",
|
||||
"Pitch": "Neigung",
|
||||
"Light anchor": "Lichtanker",
|
||||
"Light color": "Lichtfarbe",
|
||||
"Light intensity": "Lichtintensität",
|
||||
"Light position": "Lichtposition",
|
||||
"Terrain source": "Geländequelle",
|
||||
"Terrain exaggeration": "Gelände-Übertreibung",
|
||||
"Transition delay": "Übergangsverzögerung",
|
||||
"Transition duration": "Übergangsdauer",
|
||||
"Open Layers (experimental)": "Ebenen öffnen (experimentell)",
|
||||
"Shortcuts menu": "Shortcuts-Menü",
|
||||
"Open modal": "Modale Fenster öffnen",
|
||||
"Export modal": "Modale Fenster exportieren",
|
||||
"Data Sources modal": "Modale Datenquellen",
|
||||
"Style Settings modal": "Modale Stileinstellungen",
|
||||
"Toggle inspect": "Inspektion umschalten",
|
||||
"Focus map": "Karte fokussieren",
|
||||
"Debug modal": "Debug (modale Fenster)",
|
||||
"Increase the zoom level by 1.": "Zoom-Stufe um 1 erhöhen.",
|
||||
"Increase the zoom level by 2.": "Zoom-Stufe um 2 erhöhen.",
|
||||
"Decrease the zoom level by 1.": "Zoom-Stufe um 1 verringern.",
|
||||
"Decrease the zoom level by 2.": "Zoom-Stufe um 2 verringern.",
|
||||
"Pan up by 100 pixels.": "Um 100 Pixel nach oben schwenken.",
|
||||
"Pan down by 100 pixels.": "Um 100 Pixel nach unten schwenken.",
|
||||
"Pan left by 100 pixels.": "Um 100 Pixel nach links schwenken.",
|
||||
"Pan right by 100 pixels.": "Um 100 Pixel nach rechts schwenken.",
|
||||
"Increase the rotation by 15 degrees.": "Rotation um 15 Grad erhöhen.",
|
||||
"Decrease the rotation by 15 degrees.": "Rotation um 15 Grad verringern.",
|
||||
"Increase the pitch by 10 degrees.": "Neigung um 10 Grad erhöhen.",
|
||||
"Decrease the pitch by 10 degrees.": "Neigung um 10 Grad verringern.",
|
||||
"Shortcuts": "Shortcuts",
|
||||
"Press <1>ESC</1> to lose focus of any active elements, then press one of:": "Drück <1>ESC</1>, um den Fokus von aktiven Elementen zu verlieren, und dann drück eine der folgenden Tasten:",
|
||||
"If the Map is in focused you can use the following shortcuts": "Wenn die Karte fokussiert ist, kannst du die folgenden Shortcuts benutzen",
|
||||
"Remove '{{sourceId}}' source": "Quelle '{{sourceId}}' entfernen",
|
||||
"Source ID": "Quellen-ID",
|
||||
"Unique ID that identifies the source and is used in the layer to reference the source.": "Eindeutige ID, die die Quelle identifiziert und in der Ebene verwendet wird, um auf die Quelle zu verweisen.",
|
||||
"Source Type": "Quellentyp",
|
||||
"GeoJSON (JSON)": "GeoJSON (JSON)",
|
||||
"GeoJSON (URL)": "GeoJSON (URL)",
|
||||
"Vector (TileJSON URL)": "Vektor (TileJSON URL)",
|
||||
"Vector (Tile URLs)": "Vektor (Tile URLs)",
|
||||
"Raster (TileJSON URL)": "Raster (TileJSON URL)",
|
||||
"Raster (Tile URLs)": "Raster (Tile URLs)",
|
||||
"Raster DEM (TileJSON URL)": "Raster DEM (TileJSON URL)",
|
||||
"Raster DEM (XYZ URLs)": "Raster DEM (XYZ URLs)",
|
||||
"Image": "Bild",
|
||||
"Video": "Video",
|
||||
"Add Source": "Quelle hinzufügen",
|
||||
"Sources": "Quellen",
|
||||
"Active Sources": "Aktive Quellen",
|
||||
"Choose Public Source": "Öffentliche Quelle auswählen",
|
||||
"Add one of the publicly available sources to your style.": "Füge eine der öffentlich verfügbaren Quellen zu deinem Stil hinzu.",
|
||||
"Add New Source": "Neue Quelle hinzufügen",
|
||||
"Add a new source to your style. You can only choose the source type and id at creation time!": "Füge eine neue Quelle zu deinem Stil hinzu. Du kannst den Quellentyp und die ID nur bei der Erstellung auswählen!",
|
||||
"TileJSON URL": "TileJSON URL",
|
||||
"Tile URL": "Kachel-URL",
|
||||
"Scheme Type": "Schema-Typ",
|
||||
"Coord top left": "Koordinate oben links",
|
||||
"Coord top right": "Koordinate oben rechts",
|
||||
"Coord bottom right": "Koordinate unten rechts",
|
||||
"Coord bottom left": "Koordinate unten links",
|
||||
"Image URL": "Bild-URL",
|
||||
"Video URL": "Video-URL",
|
||||
"GeoJSON URL": "GeoJSON URL",
|
||||
"GeoJSON": "GeoJSON",
|
||||
"Cluster": "Cluster",
|
||||
"Tile Size": "Kachelgröße",
|
||||
"Encoding": "Kodierung",
|
||||
"Error:": "Fehler:",
|
||||
"MapTiler Access Token": "MapTiler Zugriffstoken",
|
||||
"Public access token for MapTiler Cloud.": "Öffentlicher Zugriffstoken für MapTiler Cloud.",
|
||||
"Learn More": "Mehr erfahren",
|
||||
"Thunderforest Access Token": "Thunderforest Zugriffstoken",
|
||||
"Public access token for Thunderforest services.": "Öffentlicher Zugriffstoken für Thunderforest-Dienste.",
|
||||
"Stadia Maps API Key": "Stadia Maps API-Schlüssel",
|
||||
"API key for Stadia Maps.": "API-Schlüssel für Stadia Maps.",
|
||||
"Style Renderer": "Stil-Renderer",
|
||||
"Choose the default Maputnik renderer for this style.": "Wähle den Standard-Renderer für diesen Stil aus.",
|
||||
"Language": "Sprache",
|
||||
"Press <1>ESC</1> to lose focus of any input box": "Drück <1>ESC</1>, um den Fokus von jedem Eingabefeld zu verlieren"
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"Input value": "Valeur d'entrée",
|
||||
"Data value": "Valeur des données",
|
||||
"Output value": "Valeur de sortie",
|
||||
"Function": "Fonction",
|
||||
"Select a type of data scale (default is 'categorical').": "Sélectionnez un type d'échelle de données (par défaut 'categorical').",
|
||||
"Base": "Base",
|
||||
"Input a data property to base styles off of.": "Entrez une propriété de données pour baser les styles.",
|
||||
"Default": "Par défaut",
|
||||
"Stops": "Arrêts",
|
||||
"Zoom": "Zoom",
|
||||
"Add stop": "Ajouter un arrêt",
|
||||
"Convert to expression": "Convertir en expression",
|
||||
"Remove zoom level from stop": "Supprimer le niveau de zoom de l'arrêt",
|
||||
"Revert from expression": "Annuler l'expression",
|
||||
"Delete expression": "Supprimer l'expression",
|
||||
"Convert property into a zoom function": "Convertir la propriété en fonction de zoom",
|
||||
"Convert property to data function": "Convertir la propriété en fonction de données",
|
||||
"Layer <1>{formatLayerId(layerId)}</1>: {parsed.data.message}": "Calque <1>{formatLayerId(layerId)}</1> : {parsed.data.message}",
|
||||
"switch to layer": "changer de calque",
|
||||
"Map": "Carte",
|
||||
"Inspect": "Inspecter",
|
||||
"Deuteranopia filter": "Filtre Deutéranopie",
|
||||
"Protanopia filter": "Filtre Protanopie",
|
||||
"Tritanopia filter": "Filtre Tritanopie",
|
||||
"Achromatopsia filter": "Filtre Achromatopsie",
|
||||
"Layers list": "Liste des calques",
|
||||
"Layer editor": "Éditeur de calque",
|
||||
"Map view": "Vue de la carte",
|
||||
"Maputnik on GitHub": "Maputnik sur GitHub",
|
||||
"Open": "Ouvrir",
|
||||
"Save": "Enregistrer",
|
||||
"Data Sources": "Sources de données",
|
||||
"Style Settings": "Paramètres du style",
|
||||
"View": "Vue",
|
||||
"Color accessibility": "Accessibilité des couleurs",
|
||||
"Help": "Aide",
|
||||
"Comments for the current layer. This is non-standard and not in the spec.": "Commentaires pour le calque actuel. Ceci n'est pas standard et n'est pas dans la spécification.",
|
||||
"Comments": "Commentaires",
|
||||
"Comment...": "Votre commentaire...",
|
||||
"Max Zoom": "Zoom max",
|
||||
"Min Zoom": "Zoom min",
|
||||
"Source": "Source",
|
||||
"Source Layer": "Calque Source",
|
||||
"Type": "Type",
|
||||
"Nested filters are not supported.": "Les filtres imbriqués ne sont pas pris en charge.",
|
||||
"Upgrade to expression": "Mettre à niveau vers une expression",
|
||||
"Filter": "Filtre",
|
||||
"every filter matches": "tous les filtres correspondent",
|
||||
"no filter matches": "aucun filtre ne correspond",
|
||||
"any filter matches": "l'un des filtres correspond",
|
||||
"Add filter": "Ajouter un filtre",
|
||||
"You've entered an old style filter.": "Vous avez entré un ancien style de filtre.",
|
||||
"Switch to filter editor.": "Passer à l'éditeur de filtre.",
|
||||
"Delete filter block": "Supprimer le bloc de filtre",
|
||||
"Add value": "Ajouter une valeur",
|
||||
"Remove array item": "Supprimer l'élément de tableau",
|
||||
"Press <1>ESC</1> to lose focus": "Appuyez sur <1>Échap</1> pour perdre le focus",
|
||||
"Must provide protocol: <1>https://</1>": "Protocole requis : <1>https://</1>",
|
||||
"Must provide protocol: <1>http://</1> or <3>https://</3>": "Protocole requis : <1>http://</1> ou <3>https://</3>",
|
||||
"CORS policy won't allow fetching resources served over http from https, use a <1>https://</1> domain": "La politique CORS ne permet pas de récupérer des ressources servies sur http depuis https, utilisez un protocole <1>https://</1>",
|
||||
"Layer": "Calque",
|
||||
"JSON Editor": "Éditeur JSON",
|
||||
"Delete": "Supprimer",
|
||||
"Duplicate": "Dupliquer",
|
||||
"Show": "Afficher",
|
||||
"Hide": "Cacher",
|
||||
"Move layer up": "Monter le calque",
|
||||
"Move layer down": "Descendre le calque",
|
||||
"Layer: {{layerId}}": "Calque : {{layerId}}",
|
||||
"Layers": "Calques",
|
||||
"Collapse": "Réduire",
|
||||
"Expand": "Développer",
|
||||
"Add Layer": "Ajouter un calque",
|
||||
"Search": "Recherche",
|
||||
"Zoom:": "Zoom :",
|
||||
"Close popup": "Fermer la fenêtre",
|
||||
"cursor:": "curseur :",
|
||||
"center:": "centre :",
|
||||
"rotation:": "rotation :",
|
||||
"Close modal": "Fermer la fenêtre modale",
|
||||
"Debug": "Déboguer",
|
||||
"Options": "Options",
|
||||
"Save Style": "Enregistrer le style",
|
||||
"Save the JSON style to your computer.": "Enregistrer le style JSON sur votre ordinateur.",
|
||||
"Save as": "Enregistrer sous",
|
||||
"Create HTML": "Créer le HTML",
|
||||
"Cancel": "Annuler",
|
||||
"Open Style": "Ouvrir le style",
|
||||
"Open local Style": "Ouvrir un style local",
|
||||
"Open a local JSON style from your computer.": "Ouvrir un style JSON local depuis votre ordinateur.",
|
||||
"Load from URL": "Charger depuis une URL",
|
||||
"Load from a URL. Note that the URL must have <1>CORS enabled</1>.": "Charger depuis une URL. Notez que l'URL doit avoir les <1>CORS activés</1>.",
|
||||
"Style URL": "URL du style",
|
||||
"Enter URL...": "Entrez l'URL...",
|
||||
"Gallery Styles": "Styles de la galerie",
|
||||
"Open one of the publicly available styles to start from.": "Ouvrez l'un des styles publics disponibles pour commencer.",
|
||||
"Loading style": "Chargement du style",
|
||||
"Loading: {{requestUrl}}": "Chargement : {{requestUrl}}",
|
||||
"Name": "Nom",
|
||||
"Owner": "Propriétaire",
|
||||
"Owner ID of the style. Used by Mapbox or future style APIs.": "ID du propriétaire du style. Utilisé par Mapbox ou les futures API de style.",
|
||||
"Sprite URL": "URL du sprite",
|
||||
"Glyphs URL": "URL des glyphes",
|
||||
"Center": "Centre",
|
||||
"Bearing": "Orientation",
|
||||
"Pitch": "Inclinaison",
|
||||
"Light anchor": "Ancrage de la lumière",
|
||||
"Light color": "Couleur de la lumière",
|
||||
"Light intensity": "Intensité de la lumière",
|
||||
"Light position": "Position de la lumière",
|
||||
"Terrain source": "Source du terrain",
|
||||
"Terrain exaggeration": "Exagération du terrain",
|
||||
"Transition delay": "Délai de transition",
|
||||
"Transition duration": "Durée de transition",
|
||||
"Open Layers (experimental)": "Open Layers (expérimental)",
|
||||
"Shortcuts menu": "Menu des raccourcis",
|
||||
"Open modal": "Ouvrir (modale)",
|
||||
"Export modal": "Exporter (modale)",
|
||||
"Data Sources modal": "Sources de données (modale)",
|
||||
"Style Settings modal": "Paramètres de style (modale)",
|
||||
"Toggle inspect": "Activer/désactiver l'inspection",
|
||||
"Focus map": "Focus sur la carte",
|
||||
"Debug modal": "Déboguer (modale)",
|
||||
"Increase the zoom level by 1.": "Augmenter le niveau de zoom de 1.",
|
||||
"Increase the zoom level by 2.": "Augmenter le niveau de zoom de 2.",
|
||||
"Decrease the zoom level by 1.": "Diminuer le niveau de zoom de 1.",
|
||||
"Decrease the zoom level by 2.": "Diminuer le niveau de zoom de 2.",
|
||||
"Pan up by 100 pixels.": "Déplacer vers le haut de 100 pixels.",
|
||||
"Pan down by 100 pixels.": "Déplacer vers le bas de 100 pixels.",
|
||||
"Pan left by 100 pixels.": "Déplacer vers la gauche de 100 pixels.",
|
||||
"Pan right by 100 pixels.": "Déplacer vers la droite de 100 pixels.",
|
||||
"Increase the rotation by 15 degrees.": "Augmenter l'angle de rotation de 15 degrés.",
|
||||
"Decrease the rotation by 15 degrees.": "Diminuer l'angle de rotation de 15 degrés.",
|
||||
"Increase the pitch by 10 degrees.": "Augmenter l'inclinaison de 10 degrés.",
|
||||
"Decrease the pitch by 10 degrees.": "Diminuer l'inclinaison de 10 degrés.",
|
||||
"Shortcuts": "Raccourcis",
|
||||
"Press <1>ESC</1> to lose focus of any active elements, then press one of:": "Appuyez sur <1>Échap</1> pour perdre le focus des éléments actifs, puis appuyez sur l'un des éléments suivants :",
|
||||
"If the Map is in focused you can use the following shortcuts": "Si la carte a le focus, vous pouvez utiliser les raccourcis suivants",
|
||||
"Remove '{{sourceId}}' source": "Supprimer la source '{{sourceId}}'",
|
||||
"Source ID": "ID de la source",
|
||||
"Unique ID that identifies the source and is used in the layer to reference the source.": "ID unique qui identifie la source et est utilisé dans le calque pour référencer la source.",
|
||||
"Source Type": "Type de source",
|
||||
"GeoJSON (JSON)": "GeoJSON (JSON)",
|
||||
"GeoJSON (URL)": "GeoJSON (URL)",
|
||||
"Vector (TileJSON URL)": "Vecteur (URL TileJSON)",
|
||||
"Vector (Tile URLs)": "Vecteur (URLs Tile)",
|
||||
"Raster (TileJSON URL)": "Raster (URL TileJSON)",
|
||||
"Raster (Tile URLs)": "Raster (URLs Tile)",
|
||||
"Raster DEM (TileJSON URL)": "Raster DEM (URL TileJSON)",
|
||||
"Raster DEM (XYZ URLs)": "Raster DEM (URLs XYZ)",
|
||||
"Image": "Image",
|
||||
"Video": "Vidéo",
|
||||
"Add Source": "Ajouter une source",
|
||||
"Sources": "Sources",
|
||||
"Active Sources": "Sources actives",
|
||||
"Choose Public Source": "Choisir une source publique",
|
||||
"Add one of the publicly available sources to your style.": "Ajoutez l'une des sources publiques disponibles à votre style.",
|
||||
"Add New Source": "Ajouter une nouvelle source",
|
||||
"Add a new source to your style. You can only choose the source type and id at creation time!": "Ajoutez une nouvelle source à votre style. Vous ne pouvez choisir le type et l'ID de la source qu'au moment de la création !",
|
||||
"TileJSON URL": "URL TileJSON",
|
||||
"Tile URL": "URL de la tuile",
|
||||
"Scheme Type": "Type de schéma",
|
||||
"Coord top left": "Coordonnée en haut à gauche",
|
||||
"Coord top right": "Coordonnée en haut à droite",
|
||||
"Coord bottom right": "Coordonnée en bas à droite",
|
||||
"Coord bottom left": "Coordonnée en bas à gauche",
|
||||
"Image URL": "URL de l'image",
|
||||
"Video URL": "URL de la vidéo",
|
||||
"GeoJSON URL": "URL GeoJSON",
|
||||
"GeoJSON": "GeoJSON",
|
||||
"Cluster": "Cluster",
|
||||
"Tile Size": "Dimension d'une tuile",
|
||||
"Encoding": "Encodage",
|
||||
"Error:": "Erreur :",
|
||||
"MapTiler Access Token": "Jeton d'accès MapTiler",
|
||||
"Public access token for MapTiler Cloud.": "Jeton d'accès public pour MapTiler Cloud.",
|
||||
"Learn More": "En savoir plus",
|
||||
"Thunderforest Access Token": "Jeton d'accès Thunderforest",
|
||||
"Public access token for Thunderforest services.": "Jeton d'accès public pour les services Thunderforest.",
|
||||
"Stadia Maps API Key": "Clé d'API Stadia Maps",
|
||||
"API key for Stadia Maps.": "Clé d'API pour Stadia Maps.",
|
||||
"Style Renderer": "Moteur de rendu pour le style",
|
||||
"Choose the default Maputnik renderer for this style.": "Choisissez le moteur de rendu Maputnik par défaut pour ce style.",
|
||||
"Language": "Langue",
|
||||
"Layer options": "Options du calque",
|
||||
"Paint properties": "Propriétés de peinture",
|
||||
"Layout properties": "Propriétés de mise en page",
|
||||
"General layout properties": "Propriétés générales de mise en page",
|
||||
"Text layout properties": "Propriétés de mise en page du texte",
|
||||
"Icon layout properties": "Propriétés de mise en page de l'icône",
|
||||
"Text paint properties": "Propriétés de peinture du texte",
|
||||
"Icon paint properties": "Propriétés de peinture de l'icône"
|
||||
}
|
||||
@@ -29,12 +29,11 @@
|
||||
"Map view": "תצוגת מפה",
|
||||
"Maputnik on GitHub": "מפוטניק בגיטהב",
|
||||
"Open": "פתיחה",
|
||||
"Export": "ייצוא",
|
||||
"Save": "שמור",
|
||||
"Data Sources": "מקורות מידע",
|
||||
"Style Settings": "הגדרות הסטייל",
|
||||
"View": "תצוגה",
|
||||
"Color accessibility": "נגישות צבעים",
|
||||
"Language": "שפה",
|
||||
"Help": "עזרה",
|
||||
"Comments for the current layer. This is non-standard and not in the spec.": "הערות על השכבה הנוכחית. זה לא חלק מהספסיפיקציות",
|
||||
"Comments": "הערות",
|
||||
@@ -73,8 +72,8 @@
|
||||
"Collapse": "הקטנה",
|
||||
"Expand": "הגדלה",
|
||||
"Add Layer": "הוספת שכבה",
|
||||
"Zoom:": "זום:",
|
||||
"Search": "חיפוש",
|
||||
"Zoom:": "זום:",
|
||||
"Close popup": "סגירת החלון",
|
||||
"cursor:": "סמן",
|
||||
"center:": "מרכז:",
|
||||
@@ -82,17 +81,14 @@
|
||||
"Close modal": "סגירת חלונית",
|
||||
"Debug": "דיבאג",
|
||||
"Options": "אפשרויות",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "<0>פתיחה ב-OSM</0> - פתיחה של התצוגה הנוכחית ב- openstreetmap.org",
|
||||
"Export Style": "ייצוא של הסטייל",
|
||||
"Download Style": "הורדה של הסטייל",
|
||||
"Download a JSON style to your computer.": "הורדה של הסטייל למחשב",
|
||||
"Download HTML": "הורדה כ-HTML",
|
||||
"Save Style": "שמירת הסטייל",
|
||||
"Save the JSON style to your computer.": "שמירת הסטייל JSON במחשב שלך.",
|
||||
"Save as": "שמירה בשם",
|
||||
"Create HTML": "צור HTML",
|
||||
"Cancel": "ביטול",
|
||||
"Open Style": "פתיחת סטייל",
|
||||
"Upload Style": "העלאה של סטייל",
|
||||
"Upload a JSON style from your computer.": "העלאה של סטייל מהמחשב",
|
||||
"Style file": "קובץ סטייל",
|
||||
"Upload": "העלאה",
|
||||
"Open local Style": "פתיחת סטייל מקומי",
|
||||
"Open a local JSON style from your computer.": "פתיחת סטייל JSON מקומי מהמחשב שלך.",
|
||||
"Load from URL": "פתיחה מתוך כתובת",
|
||||
"Load from a URL. Note that the URL must have <1>CORS enabled</1>.": "פתיחה מכתובת, שימו לב: הכתובת צריכה לתמוך ב- CORS",
|
||||
"Style URL": "כתוסת סטייל",
|
||||
@@ -148,9 +144,9 @@
|
||||
"GeoJSON (JSON)": "GeoJSON (JSON)",
|
||||
"GeoJSON (URL)": "GeoJSON (URL)",
|
||||
"Vector (TileJSON URL)": "Vector (TileJSON URL)",
|
||||
"Vector (XYZ URLs)": "Vector (XYZ URLs)",
|
||||
"Vector (Tile URLs)": "Vector (Tile URLs)",
|
||||
"Raster (TileJSON URL)": "Raster (TileJSON URL)",
|
||||
"Raster (XYZ URL)": "Raster (XYZ URL)",
|
||||
"Raster (Tile URLs)": "Raster (Tile URLs)",
|
||||
"Raster DEM (TileJSON URL)": "Raster DEM (TileJSON URL)",
|
||||
"Raster DEM (XYZ URLs)": "Raster DEM (XYZ URLs)",
|
||||
"Image": "תמונה",
|
||||
@@ -164,6 +160,7 @@
|
||||
"Add a new source to your style. You can only choose the source type and id at creation time!": "הוספת מקור לסטייל, ביכולתכם לעשות זאת רק בזמן מסויים",
|
||||
"TileJSON URL": "כתובת TileJSON",
|
||||
"Tile URL": "כתובת אריחים",
|
||||
"Scheme Type": "סוג סכמה",
|
||||
"Coord top left": "מיקום שמאלי עליון",
|
||||
"Coord top right": "מיקום ימני עליון",
|
||||
"Coord bottom right": "מיקום ימני תחתון",
|
||||
@@ -173,12 +170,18 @@
|
||||
"GeoJSON URL": "כתובת GeoJSON",
|
||||
"GeoJSON": "GeoJSON",
|
||||
"Cluster": "קיבוץ",
|
||||
"Tile Size": "גודל אריח",
|
||||
"Encoding": "קידוד",
|
||||
"Error:": "שגיאה",
|
||||
"MapTiler Access Token": "MapTiler Access Token",
|
||||
"Public access token for MapTiler Cloud.": "Public access token for MapTiler Cloud.",
|
||||
"Learn More": "מידע נוסף",
|
||||
"Thunderforest Access Token": "Thunderforest Access Token",
|
||||
"Public access token for Thunderforest services.": "Public access token for Thunderforest services.",
|
||||
"Stadia Maps API Key": "Stadia Maps API Key",
|
||||
"API key for Stadia Maps.": "API key for Stadia Maps",
|
||||
"Style Renderer": "צייר הסטייל",
|
||||
"Choose the default Maputnik renderer for this style.": "בחירת צייר ברירת המחדל של מפוטניק עבור הסטייל הזה"
|
||||
"Choose the default Maputnik renderer for this style.": "בחירת צייר ברירת המחדל של מפוטניק עבור הסטייל הזה",
|
||||
"Language": "שפה",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "<0>פתיחה ב-OSM</0> - פתיחה של התצוגה הנוכחית ב- openstreetmap.org"
|
||||
}
|
||||
|
||||
@@ -29,12 +29,11 @@
|
||||
"Map view": "地図画面",
|
||||
"Maputnik on GitHub": "GitHubのMaputnik",
|
||||
"Open": "開く",
|
||||
"Export": "エクスポート",
|
||||
"Save": "保存",
|
||||
"Data Sources": "データソース",
|
||||
"Style Settings": "スタイル設定",
|
||||
"View": "表示",
|
||||
"Color accessibility": "色のアクセシビリティ",
|
||||
"Language": "言語",
|
||||
"Help": "ヘルプ",
|
||||
"Comments for the current layer. This is non-standard and not in the spec.": "現在のレイヤーのコメント。注意:この機能は標準ではないため、他のライブラリとの互換性状況はわかりません。",
|
||||
"Comments": "コメント",
|
||||
@@ -73,8 +72,8 @@
|
||||
"Collapse": "畳む",
|
||||
"Expand": "展開",
|
||||
"Add Layer": "レイヤー追加",
|
||||
"Zoom:": "ズーム:",
|
||||
"Search": "検索",
|
||||
"Zoom:": "ズーム:",
|
||||
"Close popup": "ポップアップを閉じる",
|
||||
"cursor:": "カーソル",
|
||||
"center:": "中央:",
|
||||
@@ -82,17 +81,14 @@
|
||||
"Close modal": "モーダルを閉じる",
|
||||
"Debug": "デバッグ",
|
||||
"Options": "設定",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "現在のビューを <0>openstreetmap.org で開く</0>",
|
||||
"Export Style": "スタイルをエクスポート",
|
||||
"Download Style": "スタイルをダウンロード",
|
||||
"Download a JSON style to your computer.": "パソコンにJSONスタイルをダウンロードします。",
|
||||
"Download HTML": "HTMLをダウンロード",
|
||||
"Save Style": "スタイルを保存",
|
||||
"Save the JSON style to your computer.": "JSONスタイルをコンピュータに保存します。",
|
||||
"Save as": "名前を付けて保存",
|
||||
"Create HTML": "HTMLを作成",
|
||||
"Cancel": "キャンセル",
|
||||
"Open Style": "スタイルを開く",
|
||||
"Upload Style": "スタイルをアップロードする",
|
||||
"Upload a JSON style from your computer.": "JSONスタイルをパソコンからアップロードする",
|
||||
"Style file": "スタイルファイル",
|
||||
"Upload": "アップロード",
|
||||
"Open local Style": "ローカルスタイルを開く",
|
||||
"Open a local JSON style from your computer.": "コンピュータからローカルJSONスタイルを開きます。",
|
||||
"Load from URL": "URLから読み込む",
|
||||
"Load from a URL. Note that the URL must have <1>CORS enabled</1>.": "URLから読み込む。注意: URLは <1>CORSを有効にする</1> 必要があります。",
|
||||
"Style URL": "スタイルURL",
|
||||
@@ -148,9 +144,9 @@
|
||||
"GeoJSON (JSON)": "GeoJSON (JSON)",
|
||||
"GeoJSON (URL)": "GeoJSON (URL)",
|
||||
"Vector (TileJSON URL)": "ベクトル (TileJSON URL)",
|
||||
"Vector (XYZ URLs)": "ベクトル (XYZ URL)",
|
||||
"Vector (Tile URLs)": "ベクトル (Tile URLs)",
|
||||
"Raster (TileJSON URL)": "ラスタ (TileJSON URL)",
|
||||
"Raster (XYZ URL)": "ラスタ (XYZ URL)",
|
||||
"Raster (Tile URLs)": "ラスタ (Tile URLs)",
|
||||
"Raster DEM (TileJSON URL)": "ラスタ DEM (TileJSON URL)",
|
||||
"Raster DEM (XYZ URLs)": "ラスタ DEM (XYZ URL)",
|
||||
"Image": "画像",
|
||||
@@ -164,6 +160,7 @@
|
||||
"Add a new source to your style. You can only choose the source type and id at creation time!": "スタイルに新規ソースを追加します。注意: 作成時にソースタイプとIDのみを選択できます。",
|
||||
"TileJSON URL": "TileJSON URL",
|
||||
"Tile URL": "タイルURL",
|
||||
"Scheme Type": "スキーマ",
|
||||
"Coord top left": "左上座標",
|
||||
"Coord top right": "右上座標",
|
||||
"Coord bottom right": "右下座標",
|
||||
@@ -173,14 +170,20 @@
|
||||
"GeoJSON URL": "GeoJSON URL",
|
||||
"GeoJSON": "GeoJSON",
|
||||
"Cluster": "クラスタ",
|
||||
"Tile Size": "タイルサイズ",
|
||||
"Encoding": "エンコーディング",
|
||||
"Error:": "エラー:",
|
||||
"MapTiler Access Token": "MapTiler アクセストークン",
|
||||
"Public access token for MapTiler Cloud.": "MapTiler Cloud の公開用アクセストークン",
|
||||
"Learn More": "詳細はこちら",
|
||||
"Thunderforest Access Token": "Thunderforest アクセストークン",
|
||||
"Public access token for Thunderforest services.": "Thunderforest サービスの公開用アクセストークン",
|
||||
"Stadia Maps API Key": "Stadia Maps API キー",
|
||||
"API key for Stadia Maps.": "Stadia Maps の API キー",
|
||||
"Style Renderer": "スタイルレンダラ",
|
||||
"Choose the default Maputnik renderer for this style.": "このスタイルのデフォルトの Maputnik レンダラを選択してください",
|
||||
"Language": "言語",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "現在のビューを <0>openstreetmap.org で開く</0>",
|
||||
"Layer options": "レイヤー設定",
|
||||
"Paint properties": "ペイントプロパティ",
|
||||
"Layout properties": "レイアウトプロパティ",
|
||||
|
||||
@@ -29,12 +29,11 @@
|
||||
"Map view": "地图视图",
|
||||
"Maputnik on GitHub": "GitHub上的Maputnik",
|
||||
"Open": "打开",
|
||||
"Export": "导出",
|
||||
"Save": "保存",
|
||||
"Data Sources": "数据源",
|
||||
"Style Settings": "样式设置",
|
||||
"View": "视图",
|
||||
"Color accessibility": "颜色可访问性",
|
||||
"Language": "语言",
|
||||
"Help": "帮助",
|
||||
"Comments for the current layer. This is non-standard and not in the spec.": "当前图层的注释。注意:这不是标准功能,可能与其他库不兼容。",
|
||||
"Comments": "注释",
|
||||
@@ -73,8 +72,8 @@
|
||||
"Collapse": "折叠",
|
||||
"Expand": "展开",
|
||||
"Add Layer": "添加图层",
|
||||
"Zoom:": "缩放:",
|
||||
"Search": "搜索",
|
||||
"Zoom:": "缩放:",
|
||||
"Close popup": "关闭弹出窗口",
|
||||
"cursor:": "光标:",
|
||||
"center:": "中心:",
|
||||
@@ -82,17 +81,14 @@
|
||||
"Close modal": "关闭模态框",
|
||||
"Debug": "调试",
|
||||
"Options": "选项",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "在 openstreetmap.org 打开当前视图",
|
||||
"Export Style": "导出样式",
|
||||
"Download Style": "下载样式",
|
||||
"Download a JSON style to your computer.": "将JSON样式下载到您的电脑。",
|
||||
"Download HTML": "下载HTML",
|
||||
"Save Style": "保存样式",
|
||||
"Save the JSON style to your computer.": "将JSON样式保存到您的计算机。",
|
||||
"Save as": "另存为",
|
||||
"Create HTML": "创建HTML",
|
||||
"Cancel": "取消",
|
||||
"Open Style": "打开样式",
|
||||
"Upload Style": "上传样式",
|
||||
"Upload a JSON style from your computer.": "从您的电脑上传JSON样式。",
|
||||
"Style file": "样式文件",
|
||||
"Upload": "上传",
|
||||
"Open local Style": "打开本地样式",
|
||||
"Open a local JSON style from your computer.": "从您的计算机打开本地JSON样式。",
|
||||
"Load from URL": "从URL加载",
|
||||
"Load from a URL. Note that the URL must have <1>CORS enabled</1>.": "从URL加载。注意:URL必须启用 <1>CORS</1>。",
|
||||
"Style URL": "样式URL",
|
||||
@@ -148,9 +144,9 @@
|
||||
"GeoJSON (JSON)": "GeoJSON (JSON格式)",
|
||||
"GeoJSON (URL)": "GeoJSON (URL格式)",
|
||||
"Vector (TileJSON URL)": "矢量数据 (TileJSON URL)",
|
||||
"Vector (XYZ URLs)": "矢量数据 (XYZ URLs)",
|
||||
"Vector (Tile URLs)": "矢量数据 (Tile URLs)",
|
||||
"Raster (TileJSON URL)": "栅格数据 (TileJSON URL)",
|
||||
"Raster (XYZ URL)": "栅格数据 (XYZ URL)",
|
||||
"Raster (Tile URLs)": "栅格数据 (Tile URLs)",
|
||||
"Raster DEM (TileJSON URL)": "栅格高程数据 (TileJSON URL)",
|
||||
"Raster DEM (XYZ URLs)": "栅格高程数据 (XYZ URLs)",
|
||||
"Image": "图像",
|
||||
@@ -164,6 +160,7 @@
|
||||
"Add a new source to your style. You can only choose the source type and id at creation time!": "向您的样式添加新源。在创建时,您只能选择源类型和ID!",
|
||||
"TileJSON URL": "TileJSON URL",
|
||||
"Tile URL": "瓦片URL",
|
||||
"Scheme Type": "__STRING_NOT_TRANSLATED__",
|
||||
"Coord top left": "左上角坐标",
|
||||
"Coord top right": "右上角坐标",
|
||||
"Coord bottom right": "右下角坐标",
|
||||
@@ -173,14 +170,20 @@
|
||||
"GeoJSON URL": "GeoJSON URL",
|
||||
"GeoJSON": "GeoJSON",
|
||||
"Cluster": "聚合",
|
||||
"Tile Size": "__STRING_NOT_TRANSLATED__",
|
||||
"Encoding": "编码",
|
||||
"Error:": "错误:",
|
||||
"MapTiler Access Token": "MapTiler 访问令牌",
|
||||
"Public access token for MapTiler Cloud.": "MapTiler Cloud 的公共访问令牌。",
|
||||
"Learn More": "__STRING_NOT_TRANSLATED__",
|
||||
"Thunderforest Access Token": "Thunderforest 访问令牌",
|
||||
"Public access token for Thunderforest services.": "Thunderforest 服务的公共访问令牌。",
|
||||
"Stadia Maps API Key": "Stadia Maps API 密钥",
|
||||
"API key for Stadia Maps.": "Stadia Maps 的 API 密钥",
|
||||
"Style Renderer": "样式渲染器",
|
||||
"Choose the default Maputnik renderer for this style.": "为这种样式选择默认的Maputnik渲染器。",
|
||||
"Language": "语言",
|
||||
"<0>Open in OSM</0> — Opens the current view on openstreetmap.org": "在 openstreetmap.org 打开当前视图",
|
||||
"Layer options": "图层选项",
|
||||
"Paint properties": "绘制属性",
|
||||
"Layout properties": "布局属性",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
}
|
||||
|
||||
input.maputnik-string {
|
||||
margin-left: 5px;
|
||||
margin: 0 5px;
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
.maputnik-filter-editor-operator {
|
||||
margin-left: 2%;
|
||||
margin: 0 2%;
|
||||
display: inline-block;
|
||||
width: 17%;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
.maputnik-filter-editor-args {
|
||||
display: inline-block;
|
||||
width: 54%;
|
||||
margin-left: 2%;
|
||||
margin: 0 2%;
|
||||
|
||||
.maputnik-string,
|
||||
.maputnik-number {
|
||||
|
||||
@@ -107,6 +107,9 @@
|
||||
|
||||
height: 24px;
|
||||
}
|
||||
[dir="rtl"] .maputnik-select {
|
||||
background: $color-gray url("#{$icon-down-arrow}") left center no-repeat;
|
||||
}
|
||||
|
||||
// MULTIBUTTON
|
||||
.maputnik-multibutton {
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
}
|
||||
|
||||
&-group-content {
|
||||
margin-left: $margin-3;
|
||||
margin: 0 $margin-3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
.maputnik-popup-layer-id {
|
||||
padding-left: $margin-2;
|
||||
padding-right: 1.6em;
|
||||
padding-right: $margin-2;
|
||||
background-color: $color-midgray;
|
||||
color: $color-white;
|
||||
}
|
||||
@@ -33,6 +33,7 @@
|
||||
.maputnik-input-block {
|
||||
margin: 0;
|
||||
margin-left: $margin-2;
|
||||
margin-right: $margin-2;
|
||||
margin-top: $margin-2;
|
||||
}
|
||||
}
|
||||
@@ -44,4 +45,5 @@
|
||||
.maputnik-popup-table-cell {
|
||||
color: $color-lowgray;
|
||||
padding-left: $margin-2;
|
||||
padding-right: $margin-2;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
.maputnik-toolbar-version {
|
||||
font-size: 10px;
|
||||
margin-left: 4px;
|
||||
margin: 0 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -103,8 +103,7 @@
|
||||
@extend .maputnik-toolbar-link; /* stylelint-disable-line */
|
||||
|
||||
select {
|
||||
margin-left: 6px;
|
||||
border-width: 0;
|
||||
margin: 0 6px;
|
||||
display: inline;
|
||||
width: auto;
|
||||
border: solid 1px $color-midgray;
|
||||
@@ -114,12 +113,12 @@
|
||||
}
|
||||
|
||||
.maputnik-icon-text {
|
||||
padding-left: $margin-1;
|
||||
padding: 0 $margin-1;
|
||||
}
|
||||
|
||||
.maputnik-icon-action {
|
||||
display: inline;
|
||||
margin-left: $margin-1;
|
||||
margin: 0 $margin-1;
|
||||
}
|
||||
|
||||
.maputnik-toolbar__inner {
|
||||
|
||||
@@ -102,8 +102,7 @@
|
||||
|
||||
&:not(:first-child)
|
||||
{
|
||||
padding-top: $margin-1;
|
||||
padding-left: $margin-2;
|
||||
padding: $margin-1;
|
||||
}
|
||||
|
||||
&:nth-child(1) {
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"types": ["geojson"],
|
||||
"types": ["geojson", "@types/wicg-file-system-access"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node"
|
||||
"moduleResolution": "Node",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user