From 5fe38bb6ff30e7af2c51f89ee912f2686cd46d4d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 13 Sep 2025 18:45:03 +0000
Subject: [PATCH] chore(deps-dev): Bump typescript from 5.8.3 to 5.9.2 (#1301)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3
to 5.9.2.
Release notes
Sourced from typescript's
releases.
TypeScript 5.9
Release notes pending.
Downloads are available on:
TypeScript 5.9 RC
For release notes, check out the release
announcement
Downloads are available on:
TypeScript 5.9 Beta
For release notes, check out the release
announcement.
Downloads are available on:
Commits
be86783
Give more specific errors for verbatimModuleSyntax (#62113)
22ef577
LEGO: Pull request from
lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250714...
d5a414c
Don't use noErrorTruncation when printing types with
maximumLength set (#...
f14b5c8
Remove unused and confusing dom.iterable.d.ts file (#62037)
2778e84
Restore AbortSignal.abort (#62086)
65cb4bd
LEGO: Pull request from
lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250710...
9e20e03
Clear out checker-level stacks on pop (#62016)
87740bc
Fix for Issue 61081 (#61221)
833a8d4
Fix Symbol completion priority and cursor positioning (#61945)
0018c9f
LEGO: Pull request from
lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250702...
- Additional commits viewable in compare
view
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
You can trigger a rebase of this PR by commenting `@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.
---------
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Harel M
---
build/bump-version-changelog.js | 12 +-
build/release-notes.js | 14 +-
cypress/e2e/layers.cy.ts | 20 +-
cypress/e2e/map.cy.ts | 4 +-
cypress/e2e/maputnik-cypress-helper.ts | 4 +-
cypress/e2e/maputnik-driver.ts | 34 +-
cypress/e2e/modals.cy.ts | 6 +-
cypress/support/component.ts | 6 +-
eslint.config.js | 69 ++--
i18next-parser.config.ts | 8 +-
package-lock.json | 56 +++-
package.json | 3 +-
src/components/App.tsx | 312 +++++++++---------
src/components/AppLayout.tsx | 12 +-
src/components/AppMessagePanel.tsx | 20 +-
src/components/AppToolbar.tsx | 46 +--
src/components/Block.tsx | 24 +-
src/components/Collapse.tsx | 12 +-
src/components/Collapser.tsx | 8 +-
src/components/Doc.tsx | 6 +-
src/components/FieldArray.tsx | 4 +-
src/components/FieldAutocomplete.tsx | 4 +-
src/components/FieldCheckbox.tsx | 4 +-
src/components/FieldColor.tsx | 4 +-
src/components/FieldComment.tsx | 8 +-
src/components/FieldDocLabel.tsx | 12 +-
src/components/FieldDynamicArray.tsx | 4 +-
src/components/FieldEnum.tsx | 4 +-
src/components/FieldFunction.tsx | 74 ++---
src/components/FieldId.tsx | 6 +-
src/components/FieldJson.tsx | 2 +-
src/components/FieldMaxZoom.tsx | 12 +-
src/components/FieldMinZoom.tsx | 12 +-
src/components/FieldMultiInput.tsx | 4 +-
src/components/FieldNumber.tsx | 4 +-
src/components/FieldSelect.tsx | 4 +-
src/components/FieldSource.tsx | 12 +-
src/components/FieldSourceLayer.tsx | 14 +-
src/components/FieldSpec.tsx | 60 ++--
src/components/FieldString.tsx | 4 +-
src/components/FieldType.tsx | 20 +-
src/components/FieldUrl.tsx | 4 +-
src/components/Fieldset.tsx | 12 +-
src/components/FilterEditor.tsx | 86 ++---
src/components/FilterEditorBlock.tsx | 10 +-
src/components/IconLayer.tsx | 36 +-
src/components/InputArray.tsx | 32 +-
src/components/InputAutocomplete.cy.tsx | 22 +-
src/components/InputAutocomplete.tsx | 78 ++---
src/components/InputButton.tsx | 6 +-
src/components/InputCheckbox.tsx | 10 +-
src/components/InputColor.tsx | 58 ++--
src/components/InputDynamicArray.tsx | 92 +++---
src/components/InputEnum.tsx | 22 +-
src/components/InputFont.tsx | 20 +-
src/components/InputJson.tsx | 60 ++--
src/components/InputMultiInput.tsx | 20 +-
src/components/InputNumber.tsx | 40 +--
src/components/InputSelect.tsx | 8 +-
src/components/InputSpec.tsx | 198 +++++------
src/components/InputString.tsx | 22 +-
src/components/InputUrl.tsx | 22 +-
src/components/LayerEditor.tsx | 272 +++++++--------
src/components/LayerEditorGroup.tsx | 10 +-
src/components/LayerList.tsx | 122 +++----
src/components/LayerListGroup.tsx | 10 +-
src/components/LayerListItem.tsx | 42 +--
src/components/MapMaplibreGl.tsx | 112 +++----
.../MapMaplibreGlFeaturePropertyPopup.tsx | 46 +--
src/components/MapMaplibreGlLayerPopup.tsx | 44 +--
src/components/MapOpenLayers.tsx | 44 +--
src/components/PropertyGroup.tsx | 50 +--
src/components/ScrollContainer.tsx | 4 +-
src/components/SingleFilterEditor.tsx | 42 +--
src/components/SmallError.tsx | 6 +-
src/components/_DataProperty.tsx | 102 +++---
src/components/_DeleteStopButton.tsx | 10 +-
src/components/_ExpressionProperty.tsx | 32 +-
src/components/_FunctionButtons.tsx | 28 +-
src/components/_SpecProperty.tsx | 16 +-
src/components/_ZoomProperty.tsx | 64 ++--
src/components/modals/Modal.tsx | 16 +-
src/components/modals/ModalAdd.tsx | 104 +++---
src/components/modals/ModalDebug.tsx | 18 +-
src/components/modals/ModalExport.tsx | 52 +--
src/components/modals/ModalLoading.tsx | 10 +-
src/components/modals/ModalOpen.tsx | 72 ++--
src/components/modals/ModalSettings.tsx | 54 +--
src/components/modals/ModalShortcuts.tsx | 18 +-
src/components/modals/ModalSources.tsx | 268 +++++++--------
.../modals/ModalSourcesTypeEditor.tsx | 148 ++++-----
src/index.jsx | 12 +-
src/libs/accessibility.ts | 8 +-
src/libs/codemirror-mgl.ts | 20 +-
src/libs/definitions.d.ts | 2 +-
src/libs/diffmessage.ts | 12 +-
src/libs/field-spec-additional.ts | 4 +-
src/libs/filterops.ts | 6 +-
src/libs/highlight.ts | 40 +--
src/libs/label-from-field-name.ts | 6 +-
src/libs/layer.ts | 40 +--
src/libs/layerwatcher.ts | 54 +--
src/libs/maplibre-rtl.ts | 4 +-
src/libs/metadata.ts | 30 +-
src/libs/non-source-layers.ts | 2 +-
src/libs/revisions.ts | 16 +-
src/libs/sort-numerically.ts | 4 +-
src/libs/source.ts | 12 +-
src/libs/spec-helper.ts | 18 +-
src/libs/store/apistore.ts | 64 ++--
src/libs/store/style-store-factory.ts | 4 +-
src/libs/store/stylestore.ts | 70 ++--
src/libs/style.ts | 84 ++---
src/libs/urlopen.ts | 18 +-
src/libs/zoomcontrol.ts | 12 +-
115 files changed, 2111 insertions(+), 2053 deletions(-)
diff --git a/build/bump-version-changelog.js b/build/bump-version-changelog.js
index 1c9795b8..9652b6e7 100755
--- a/build/bump-version-changelog.js
+++ b/build/bump-version-changelog.js
@@ -10,12 +10,12 @@
* https://github.com/maplibre/maplibre-gl-js/blob/bc70bc559cea5c987fa1b79fd44766cef68bbe28/build/release-notes.js
*/
-import * as fs from 'fs';
+import * as fs from "fs";
-const changelogPath = 'CHANGELOG.md';
-let changelog = fs.readFileSync(changelogPath, 'utf8');
-changelog = changelog.replace('## main', `## ${process.argv[2]}`);
-changelog = changelog.replaceAll('- _...Add new stuff here..._\n', '');
+const changelogPath = "CHANGELOG.md";
+let changelog = fs.readFileSync(changelogPath, "utf8");
+changelog = changelog.replace("## main", `## ${process.argv[2]}`);
+changelog = changelog.replaceAll("- _...Add new stuff here..._\n", "");
changelog = `## main
### ✨ Features and improvements
@@ -26,4 +26,4 @@ changelog = `## main
` + changelog;
-fs.writeFileSync(changelogPath, changelog, 'utf8');
+fs.writeFileSync(changelogPath, changelog, "utf8");
diff --git a/build/release-notes.js b/build/release-notes.js
index 0cf331a6..24791387 100755
--- a/build/release-notes.js
+++ b/build/release-notes.js
@@ -3,10 +3,10 @@
// Copied from maplibre/maplibre-gl-js
// https://github.com/maplibre/maplibre-gl-js/blob/bc70bc559cea5c987fa1b79fd44766cef68bbe28/build/release-notes.js
-import * as fs from 'fs';
+import * as fs from "fs";
-const changelogPath = 'CHANGELOG.md';
-const changelog = fs.readFileSync(changelogPath, 'utf8');
+const changelogPath = "CHANGELOG.md";
+const changelog = fs.readFileSync(changelogPath, "utf8");
/*
Parse the raw changelog text and split it into individual releases.
@@ -25,8 +25,8 @@ let match;
// eslint-disable-next-line no-cond-assign
while (match = regex.exec(changelog)) {
releaseNotes.push({
- 'version': match[1],
- 'changelog': match[2].trim(),
+ "version": match[1],
+ "changelog": match[2].trim(),
});
}
@@ -35,10 +35,10 @@ const previous = releaseNotes[1];
// Print the release notes template.
-let header = 'Changes since previous version'
+let header = "Changes since previous version";
if (previous) {
header = `https://github.com/maplibre/maputnik
- [Changes](https://github.com/maplibre/maputnik/compare/v${previous.version}...v${latest.version}) since [Maputnik v${previous.version}](https://github.com/maplibre/maputnik/releases/tag/v${previous.version})`
+ [Changes](https://github.com/maplibre/maputnik/compare/v${previous.version}...v${latest.version}) since [Maputnik v${previous.version}](https://github.com/maplibre/maputnik/releases/tag/v${previous.version})`;
}
const templatedReleaseNotes = `${header}
diff --git a/cypress/e2e/layers.cy.ts b/cypress/e2e/layers.cy.ts
index 3687c0da..06c17e8a 100644
--- a/cypress/e2e/layers.cy.ts
+++ b/cypress/e2e/layers.cy.ts
@@ -313,7 +313,7 @@ describe("layers", () => {
it("should revert to a valid value when focus out", () => {
when.click("layer-list-item:background:" + bgId);
- then(get.elementByTestId("spec-field-input:background-opacity")).shouldHaveValue('0');
+ then(get.elementByTestId("spec-field-input:background-opacity")).shouldHaveValue("0");
});
});
@@ -575,10 +575,10 @@ describe("layers", () => {
});
when.collapseGroupInLayerEditor();
when.collapseGroupInLayerEditor(1);
- when.setValueToPropertyArray("spec-field:hillshade-illumination-direction", '1');
- when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", '2');
- when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", '3');
- when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", '4');
+ when.setValueToPropertyArray("spec-field:hillshade-illumination-direction", "1");
+ when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", "2");
+ when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", "3");
+ when.addValueToPropertyArray("spec-field:hillshade-illumination-direction", "4");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
@@ -600,9 +600,9 @@ describe("layers", () => {
layer: "example",
});
when.collapseGroupInLayerEditor();
- when.setValueToPropertyArray("spec-field:hillshade-highlight-color", 'blue');
- when.addValueToPropertyArray("spec-field:hillshade-highlight-color", '#00ff00');
- when.addValueToPropertyArray("spec-field:hillshade-highlight-color", 'rgba(255, 255, 0, 1)');
+ when.setValueToPropertyArray("spec-field:hillshade-highlight-color", "blue");
+ when.addValueToPropertyArray("spec-field:hillshade-highlight-color", "#00ff00");
+ when.addValueToPropertyArray("spec-field:hillshade-highlight-color", "rgba(255, 255, 0, 1)");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
@@ -706,8 +706,8 @@ describe("layers", () => {
sourceText.click();
sourceText.type("\"");
- const error = get.element('.CodeMirror-lint-marker-error');
- error.should('exist');
+ const error = get.element(".CodeMirror-lint-marker-error");
+ error.should("exist");
});
});
diff --git a/cypress/e2e/map.cy.ts b/cypress/e2e/map.cy.ts
index 7ce34c18..1845dd8d 100644
--- a/cypress/e2e/map.cy.ts
+++ b/cypress/e2e/map.cy.ts
@@ -25,7 +25,7 @@ describe("map", () => {
});
describe("search", () => {
- it('should exist', () => {
+ it("should exist", () => {
then(get.searchControl()).shouldBeVisible();
});
});
@@ -33,7 +33,7 @@ describe("map", () => {
describe("popup", () => {
beforeEach(() => {
when.setStyle("rectangles");
- })
+ });
it("should open on feature click", () => {
when.clickCenter("maplibre:map");
then(get.elementByTestId("feature-layer-popup")).shouldBeVisible();
diff --git a/cypress/e2e/maputnik-cypress-helper.ts b/cypress/e2e/maputnik-cypress-helper.ts
index 8c20bee8..b2a83d31 100644
--- a/cypress/e2e/maputnik-cypress-helper.ts
+++ b/cypress/e2e/maputnik-cypress-helper.ts
@@ -1,6 +1,6 @@
///
import { CypressHelper } from "@shellygo/cypress-test-utils";
-import 'cypress-real-events/support';
+import "cypress-real-events/support";
export default class MaputnikCypressHelper {
private helper = new CypressHelper({ defaultDataAttribute: "data-wd-key" });
@@ -17,7 +17,7 @@ export default class MaputnikCypressHelper {
dragAndDropWithWait: (element: string, targetElement: string) => {
this.helper.get.elementByTestId(element).realMouseDown({ button: "left", position: "center" });
this.helper.get.elementByTestId(element).realMouseMove(0, 10, { position: "center" });
- this.helper.get.elementByTestId(targetElement).realMouseMove(0, 0, { position: "center" })
+ this.helper.get.elementByTestId(targetElement).realMouseMove(0, 0, { position: "center" });
this.helper.when.wait(1);
this.helper.get.elementByTestId(targetElement).realMouseUp();
},
diff --git a/cypress/e2e/maputnik-driver.ts b/cypress/e2e/maputnik-driver.ts
index 964215e9..c4a5b7e5 100644
--- a/cypress/e2e/maputnik-driver.ts
+++ b/cypress/e2e/maputnik-driver.ts
@@ -119,21 +119,21 @@ export class MaputnikDriver {
) => {
const url = new URL(baseUrl);
switch (styleProperties) {
- case "geojson":
- url.searchParams.set("style", baseUrl + "geojson-style.json");
- break;
- case "raster":
- url.searchParams.set("style", baseUrl + "raster-style.json");
- break;
- case "both":
- url.searchParams.set("style", baseUrl + "geojson-raster-style.json");
- break;
- case "layer":
- url.searchParams.set("style", baseUrl + "example-layer-style.json");
- break;
- case "rectangles":
- url.searchParams.set("style", baseUrl + "rectangles-style.json");
- break;
+ case "geojson":
+ url.searchParams.set("style", baseUrl + "geojson-style.json");
+ break;
+ case "raster":
+ url.searchParams.set("style", baseUrl + "raster-style.json");
+ break;
+ case "both":
+ url.searchParams.set("style", baseUrl + "geojson-raster-style.json");
+ break;
+ case "layer":
+ url.searchParams.set("style", baseUrl + "example-layer-style.json");
+ break;
+ case "rectangles":
+ url.searchParams.set("style", baseUrl + "rectangles-style.json");
+ break;
}
if (zoom) {
@@ -144,7 +144,7 @@ export class MaputnikDriver {
this.helper.when.acceptConfirm();
}
// when methods should not include assertions
- const toolbarLink = this.helper.get.elementByTestId("toolbar:link")
+ const toolbarLink = this.helper.get.elementByTestId("toolbar:link");
toolbarLink.scrollIntoView();
toolbarLink.should("be.visible");
},
@@ -215,6 +215,6 @@ export class MaputnikDriver {
skipTargetLayerEditor: () =>
this.helper.get.elementByTestId("skip-target-layer-editor"),
canvas: () => this.helper.get.element("canvas"),
- searchControl: () => this.helper.get.element('.maplibregl-ctrl-geocoder')
+ searchControl: () => this.helper.get.element(".maplibregl-ctrl-geocoder")
};
}
diff --git a/cypress/e2e/modals.cy.ts b/cypress/e2e/modals.cy.ts
index 657727a5..04c0cf9e 100644
--- a/cypress/e2e/modals.cy.ts
+++ b/cypress/e2e/modals.cy.ts
@@ -253,10 +253,10 @@ describe("modals", () => {
it("inlcude API key when change renderer", () => {
- when.click("modal:settings.close-modal")
+ when.click("modal:settings.close-modal");
when.click("nav:open");
- get.elementByAttribute('aria-label', "MapTiler Basic").should('exist').click();
+ get.elementByAttribute("aria-label", "MapTiler Basic").should("exist").click();
when.wait(1000);
when.click("nav:settings");
@@ -322,7 +322,7 @@ describe("modals", () => {
win.localStorage.setItem(key, chunk);
} catch (e: any) {
// Verify it's a quota error
- if (e.name === 'QuotaExceededError') {
+ if (e.name === "QuotaExceededError") {
if (chunkSize <= 1) return;
else {
chunkSize /= 2;
diff --git a/cypress/support/component.ts b/cypress/support/component.ts
index b2c275d6..1b940dc5 100644
--- a/cypress/support/component.ts
+++ b/cypress/support/component.ts
@@ -14,9 +14,9 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
-import './commands'
+import "./commands";
-import { mount } from 'cypress/react'
+import { mount } from "cypress/react";
// Augment the Cypress namespace to include type definitions for
// your custom command.
@@ -31,7 +31,7 @@ declare global {
}
}
-Cypress.Commands.add('mount', mount)
+Cypress.Commands.add("mount", mount);
// Example use:
// cy.mount()
diff --git a/eslint.config.js b/eslint.config.js
index 4800f10a..8825a6bc 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -1,56 +1,65 @@
-import eslint from '@eslint/js';
-import tseslint from 'typescript-eslint';
-import reactPlugin from 'eslint-plugin-react';
-import reactHooksPlugin from 'eslint-plugin-react-hooks';
-import reactRefreshPlugin from 'eslint-plugin-react-refresh';
+import eslint from "@eslint/js";
+import {defineConfig} from "eslint/config";
+import stylisticTs from "@stylistic/eslint-plugin";
+import tseslint from "typescript-eslint";
+import reactPlugin from "eslint-plugin-react";
+import reactHooksPlugin from "eslint-plugin-react-hooks";
+import reactRefreshPlugin from "eslint-plugin-react-refresh";
-export default tseslint.config({
+export default defineConfig({
extends: [
eslint.configs.recommended,
tseslint.configs.recommended,
],
- files: ['**/*.{js,jsx,ts,tsx}'],
+ files: ["**/*.{js,jsx,ts,tsx}"],
ignores: [
"dist/**/*",
],
languageOptions: {
ecmaVersion: 2024,
- sourceType: 'module',
+ sourceType: "module",
globals: {
- global: 'readonly'
+ global: "readonly"
}
},
settings: {
- react: { version: '18.2' }
+ react: { version: "18.2" }
},
plugins: {
- 'react': reactPlugin,
- 'react-hooks': reactHooksPlugin,
- 'react-refresh': reactRefreshPlugin
+ "react": reactPlugin,
+ "react-hooks": reactHooksPlugin,
+ "react-refresh": reactRefreshPlugin,
+ "@stylistic": stylisticTs
},
rules: {
- 'react-refresh/only-export-components': [
- 'warn',
+ "react-refresh/only-export-components": [
+ "warn",
{ allowConstantExport: true }
],
"@typescript-eslint/no-explicit-any": "off",
- '@typescript-eslint/no-unused-vars': [
- 'warn',
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
{
- varsIgnorePattern: '^_',
- caughtErrors: 'all',
- caughtErrorsIgnorePattern: '^_',
- argsIgnorePattern: '^_'
+ varsIgnorePattern: "^_",
+ caughtErrors: "all",
+ caughtErrorsIgnorePattern: "^_",
+ argsIgnorePattern: "^_"
}
],
- 'no-unused-vars': 'off',
- 'react/prop-types': 'off',
- 'no-undef': 'off',
- 'indent': ['error', 2],
- 'no-var': 'error',
- '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
- '@typescript-eslint/ban-ts-comment': 'off',
- '@typescript-eslint/no-empty-object-type': 'off',
+ "no-unused-vars": "off",
+ "react/prop-types": "off",
+ "no-undef": "off",
+ "indent": "off",
+ "@stylistic/indent": ["error", 2],
+ "semi": "off",
+ "@stylistic/semi": ["error", "always"],
+ "quotes": "off",
+ "@stylistic/quotes": ["error", "double", { avoidEscape: true }],
+ "no-var": "error",
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
+ "@typescript-eslint/ban-ts-comment": "off",
+ "@typescript-eslint/no-empty-object-type": "off",
+ "@typescript-eslint/consistent-type-imports": ["error", { "fixStyle": "inline-type-imports" }],
},
linterOptions: {
@@ -58,4 +67,4 @@ export default tseslint.config({
noInlineConfig: false
}
}
-)
+);
diff --git a/i18next-parser.config.ts b/i18next-parser.config.ts
index 70c37158..e16bf8d3 100644
--- a/i18next-parser.config.ts
+++ b/i18next-parser.config.ts
@@ -1,6 +1,6 @@
export default {
- output: 'src/locales/$LOCALE/$NAMESPACE.json',
- locales: [ 'de', 'fr', 'he', 'it','ja', 'zh' ],
+ output: "src/locales/$LOCALE/$NAMESPACE.json",
+ locales: [ "de", "fr", "he", "it","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.
@@ -12,6 +12,6 @@ export default {
defaultValue: (_locale, _ns, _key) => {
// The default value is a string that indicates that the string is not translated.
- return '__STRING_NOT_TRANSLATED__';
+ return "__STRING_NOT_TRANSLATED__";
}
-}
+};
diff --git a/package-lock.json b/package-lock.json
index f804337b..e33d5ac2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -67,6 +67,7 @@
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@rollup/plugin-replace": "^6.0.2",
"@shellygo/cypress-test-utils": "^6.0.1",
+ "@stylistic/eslint-plugin": "^5.3.1",
"@types/codemirror": "^5.60.16",
"@types/color": "^4.2.0",
"@types/cors": "^2.8.19",
@@ -107,7 +108,7 @@
"stylelint": "^16.24.0",
"stylelint-config-recommended-scss": "^16.0.1",
"stylelint-scss": "^6.12.1",
- "typescript": "^5.8.3",
+ "typescript": "^5.9.2",
"typescript-eslint": "^8.43.0",
"uuid": "^13.0.0",
"vite": "^7.1.5",
@@ -2805,6 +2806,53 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@stylistic/eslint-plugin": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.3.1.tgz",
+ "integrity": "sha512-Ykums1VYonM0TgkD0VteVq9mrlO2FhF48MDJnPyv3MktIB2ydtuhlO0AfWm7xnW1kyf5bjOqA6xc7JjviuVTxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/types": "^8.41.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "estraverse": "^5.3.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=9.0.0"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -12708,9 +12756,9 @@
}
},
"node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "version": "5.9.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
+ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/package.json b/package.json
index 64d4af7f..026261f9 100644
--- a/package.json
+++ b/package.json
@@ -99,6 +99,7 @@
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@rollup/plugin-replace": "^6.0.2",
"@shellygo/cypress-test-utils": "^6.0.1",
+ "@stylistic/eslint-plugin": "^5.3.1",
"@types/codemirror": "^5.60.16",
"@types/color": "^4.2.0",
"@types/cors": "^2.8.19",
@@ -139,7 +140,7 @@
"stylelint": "^16.24.0",
"stylelint-config-recommended-scss": "^16.0.1",
"stylelint-scss": "^6.12.1",
- "typescript": "^5.8.3",
+ "typescript": "^5.9.2",
"typescript-eslint": "^8.43.0",
"uuid": "^13.0.0",
"vite": "^7.1.5",
diff --git a/src/components/App.tsx b/src/components/App.tsx
index b666d2a6..2447aed8 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1,41 +1,41 @@
-import React from 'react'
-import cloneDeep from 'lodash.clonedeep'
-import clamp from 'lodash.clamp'
-import buffer from 'buffer'
-import get from 'lodash.get'
-import {unset} from 'lodash'
-import {arrayMoveMutable} from 'array-move'
+import React from "react";
+import cloneDeep from "lodash.clonedeep";
+import clamp from "lodash.clamp";
+import buffer from "buffer";
+import get from "lodash.get";
+import {unset} from "lodash";
+import {arrayMoveMutable} from "array-move";
import hash from "string-hash";
import { PMTiles } from "pmtiles";
-import {Map, LayerSpecification, StyleSpecification, ValidationError, SourceSpecification} from 'maplibre-gl'
-import {validateStyleMin} from '@maplibre/maplibre-gl-style-spec'
-import latest from '@maplibre/maplibre-gl-style-spec/dist/latest.json'
+import {type Map, type LayerSpecification, type StyleSpecification, type ValidationError, type SourceSpecification} from "maplibre-gl";
+import {validateStyleMin} from "@maplibre/maplibre-gl-style-spec";
+import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json";
-import MapMaplibreGl from './MapMaplibreGl'
-import MapOpenLayers from './MapOpenLayers'
-import LayerList from './LayerList'
-import LayerEditor from './LayerEditor'
-import AppToolbar, { MapState } from './AppToolbar'
-import AppLayout from './AppLayout'
-import MessagePanel from './AppMessagePanel'
+import MapMaplibreGl from "./MapMaplibreGl";
+import MapOpenLayers from "./MapOpenLayers";
+import LayerList from "./LayerList";
+import LayerEditor from "./LayerEditor";
+import AppToolbar, { type MapState } from "./AppToolbar";
+import AppLayout from "./AppLayout";
+import MessagePanel from "./AppMessagePanel";
-import ModalSettings from './modals/ModalSettings'
-import ModalExport from './modals/ModalExport'
-import ModalSources from './modals/ModalSources'
-import ModalOpen from './modals/ModalOpen'
-import ModalShortcuts from './modals/ModalShortcuts'
-import ModalDebug from './modals/ModalDebug'
+import ModalSettings from "./modals/ModalSettings";
+import ModalExport from "./modals/ModalExport";
+import ModalSources from "./modals/ModalSources";
+import ModalOpen from "./modals/ModalOpen";
+import ModalShortcuts from "./modals/ModalShortcuts";
+import ModalDebug from "./modals/ModalDebug";
-import {downloadGlyphsMetadata, downloadSpriteMetadata} from '../libs/metadata'
-import style from '../libs/style'
-import { undoMessages, redoMessages } from '../libs/diffmessage'
-import { createStyleStore, type IStyleStore } from '../libs/store/style-store-factory'
-import { RevisionStore } from '../libs/revisions'
-import LayerWatcher from '../libs/layerwatcher'
-import tokens from '../config/tokens.json'
-import isEqual from 'lodash.isequal'
-import { MapOptions } from 'maplibre-gl';
-import { OnStyleChangedOpts, StyleSpecificationWithId } from '../libs/definitions'
+import {downloadGlyphsMetadata, downloadSpriteMetadata} from "../libs/metadata";
+import style from "../libs/style";
+import { undoMessages, redoMessages } from "../libs/diffmessage";
+import { createStyleStore, type IStyleStore } from "../libs/store/style-store-factory";
+import { RevisionStore } from "../libs/revisions";
+import LayerWatcher from "../libs/layerwatcher";
+import tokens from "../config/tokens.json";
+import isEqual from "lodash.isequal";
+import { type MapOptions } from "maplibre-gl";
+import { type OnStyleChangedOpts, type StyleSpecificationWithId } from "../libs/definitions";
// Buffer must be defined globally for @maplibre/maplibre-gl-style-spec validate() function to succeed.
window.Buffer = buffer.Buffer;
@@ -46,21 +46,21 @@ function setFetchAccessToken(url: string, mapStyle: StyleSpecification) {
const matchesThunderforest = url.match(/\.thunderforest\.com/);
const matchesLocationIQ = url.match(/\.locationiq\.com/);
if (matchesTilehosting || matchesMaptiler) {
- const accessToken = style.getAccessToken("openmaptiles", mapStyle, {allowFallback: true})
+ const accessToken = style.getAccessToken("openmaptiles", mapStyle, {allowFallback: true});
if (accessToken) {
- return url.replace('{key}', accessToken)
+ return url.replace("{key}", accessToken);
}
}
else if (matchesThunderforest) {
- const accessToken = style.getAccessToken("thunderforest", mapStyle, {allowFallback: true})
+ const accessToken = style.getAccessToken("thunderforest", mapStyle, {allowFallback: true});
if (accessToken) {
- return url.replace('{key}', accessToken)
+ return url.replace("{key}", accessToken);
}
}
else if (matchesLocationIQ) {
- const accessToken = style.getAccessToken("locationiq", mapStyle, {allowFallback: true})
+ const accessToken = style.getAccessToken("locationiq", mapStyle, {allowFallback: true});
if (accessToken) {
- return url.replace('{key}', accessToken)
+ return url.replace("{key}", accessToken);
}
}
else {
@@ -78,7 +78,7 @@ function updateRootSpec(spec: any, fieldName: string, newValues: any) {
values: newValues
}
}
- }
+ };
}
type MappedErrors = {
@@ -91,7 +91,7 @@ type MappedErrors = {
message: string
}
}
-}
+};
type AppState = {
errors: MappedErrors[],
@@ -128,7 +128,7 @@ type AppState = {
debug: boolean
}
fileHandle: FileSystemFileHandle | null
-}
+};
export default class App extends React.Component {
revisionStore: RevisionStore;
@@ -136,7 +136,7 @@ export default class App extends React.Component {
layerWatcher: LayerWatcher;
constructor(props: any) {
- super(props)
+ super(props);
this.revisionStore = new RevisionStore();
this.configureKeyboardShortcuts();
@@ -174,11 +174,11 @@ export default class App extends React.Component {
debugToolbox: false,
},
fileHandle: null,
- }
+ };
this.layerWatcher = new LayerWatcher({
onVectorLayersChange: v => this.setState({ vectorLayers: v })
- })
+ });
}
configureKeyboardShortcuts = () => {
@@ -233,7 +233,7 @@ export default class App extends React.Component {
this.toggleModal("debug");
}
},
- ]
+ ];
document.body.addEventListener("keyup", (e) => {
if(e.key === "Escape") {
@@ -242,19 +242,19 @@ export default class App extends React.Component {
}
else if(this.state.isOpen.shortcuts || document.activeElement === document.body) {
const shortcut = shortcuts.find((shortcut) => {
- return (shortcut.key === e.key)
- })
+ return (shortcut.key === e.key);
+ });
if(shortcut) {
this.setModal("shortcuts", false);
shortcut.handler();
}
}
- })
- }
+ });
+ };
handleKeyPress = (e: KeyboardEvent) => {
- if(navigator.platform.toUpperCase().indexOf('MAC') >= 0) {
+ if(navigator.platform.toUpperCase().indexOf("MAC") >= 0) {
if(e.metaKey && e.shiftKey && e.keyCode === 90) {
e.preventDefault();
this.onRedo();
@@ -274,7 +274,7 @@ export default class App extends React.Component {
this.onRedo();
}
}
- }
+ };
async componentDidMount() {
this.styleStore = await createStyleStore((mapStyle, opts) => this.onStyleChanged(mapStyle, opts));
@@ -286,33 +286,33 @@ export default class App extends React.Component {
}
saveStyle(snapshotStyle: StyleSpecificationWithId) {
- this.styleStore?.save(snapshotStyle)
+ this.styleStore?.save(snapshotStyle);
}
updateFonts(urlTemplate: string) {
- const metadata: {[key: string]: string} = this.state.mapStyle.metadata || {} as any
- const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
+ const metadata: {[key: string]: string} = this.state.mapStyle.metadata || {} as any;
+ const accessToken = metadata["maputnik:openmaptiles_access_token"] || tokens.openmaptiles;
- const glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
+ const glyphUrl = (typeof urlTemplate === "string")? urlTemplate.replace("{key}", accessToken): urlTemplate;
downloadGlyphsMetadata(glyphUrl, fonts => {
- this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
- })
+ this.setState({ spec: updateRootSpec(this.state.spec, "glyphs", fonts)});
+ });
}
updateIcons(baseUrl: string) {
downloadSpriteMetadata(baseUrl, icons => {
- this.setState({ spec: updateRootSpec(this.state.spec, 'sprite', icons)})
- })
+ this.setState({ spec: updateRootSpec(this.state.spec, "sprite", icons)});
+ });
}
onChangeMetadataProperty = (property: string, value: any) => {
// If we're changing renderer reset the map state.
if (
- property === 'maputnik:renderer' &&
- value !== get(this.state.mapStyle, ['metadata', 'maputnik:renderer'], 'mlgljs')
+ property === "maputnik:renderer" &&
+ value !== get(this.state.mapStyle, ["metadata", "maputnik:renderer"], "mlgljs")
) {
this.setState({
- mapState: 'map'
+ mapState: "map"
});
}
@@ -322,10 +322,10 @@ export default class App extends React.Component {
...(this.state.mapStyle as any).metadata,
[property]: value
}
- }
+ };
- this.onStyleChanged(changedStyle)
- }
+ this.onStyleChanged(changedStyle);
+ };
onStyleChanged = (newStyle: StyleSpecificationWithId, opts: OnStyleChangedOpts={}): void => {
opts = {
@@ -338,16 +338,16 @@ export default class App extends React.Component {
// For the style object, find the urls that has "{key}" and insert the correct API keys
// Without this, going from e.g. MapTiler to OpenLayers and back will lose the maptlier key.
- if (newStyle.glyphs && typeof newStyle.glyphs === 'string') {
+ if (newStyle.glyphs && typeof newStyle.glyphs === "string") {
newStyle.glyphs = setFetchAccessToken(newStyle.glyphs, newStyle);
}
- if (newStyle.sprite && typeof newStyle.sprite === 'string') {
+ if (newStyle.sprite && typeof newStyle.sprite === "string") {
newStyle.sprite = setFetchAccessToken(newStyle.sprite, newStyle);
}
for (const [_sourceId, source] of Object.entries(newStyle.sources)) {
- if (source && 'url' in source && typeof source.url === 'string') {
+ if (source && "url" in source && typeof source.url === "string") {
source.url = setFetchAccessToken(source.url, newStyle);
}
}
@@ -389,7 +389,7 @@ export default class App extends React.Component {
message,
}
}
- }
+ };
}
// Special case: Invalid source
@@ -406,7 +406,7 @@ export default class App extends React.Component {
message,
}
}
- }
+ };
}
const layerMatch = error.message.match(/layers\[(\d+)\]\.(?:(\S+)\.)?(\S+): (.*)/);
@@ -423,7 +423,7 @@ export default class App extends React.Component {
message
}
}
- }
+ };
}
else {
return {
@@ -453,10 +453,10 @@ export default class App extends React.Component {
}
if(newStyle.glyphs !== this.state.mapStyle.glyphs) {
- this.updateFonts(newStyle.glyphs as string)
+ this.updateFonts(newStyle.glyphs as string);
}
if(newStyle.sprite !== this.state.mapStyle.sprite) {
- this.updateIcons(newStyle.sprite as string)
+ this.updateIcons(newStyle.sprite as string);
}
if (opts.addRevision) {
@@ -473,28 +473,28 @@ export default class App extends React.Component {
}, () => {
this.fetchSources();
this.setStateInUrl();
- })
+ });
- }
+ };
onUndo = () => {
- const activeStyle = this.revisionStore.undo()
+ const activeStyle = this.revisionStore.undo();
- const messages = undoMessages(this.state.mapStyle, activeStyle)
+ const messages = undoMessages(this.state.mapStyle, activeStyle);
this.onStyleChanged(activeStyle, {addRevision: false});
this.setState({
infos: messages,
- })
- }
+ });
+ };
onRedo = () => {
- const activeStyle = this.revisionStore.redo()
- const messages = redoMessages(this.state.mapStyle, activeStyle)
+ const activeStyle = this.revisionStore.redo();
+ const messages = redoMessages(this.state.mapStyle, activeStyle);
this.onStyleChanged(activeStyle, {addRevision: false});
this.setState({
infos: messages,
- })
- }
+ });
+ };
onMoveLayer = (move: {oldIndex: number; newIndex: number}) => {
let { oldIndex, newIndex } = move;
@@ -512,97 +512,97 @@ export default class App extends React.Component {
layers = layers.slice(0);
arrayMoveMutable(layers, oldIndex, newIndex);
this.onLayersChange(layers);
- }
+ };
onLayersChange = (changedLayers: LayerSpecification[]) => {
const changedStyle = {
...this.state.mapStyle,
layers: changedLayers
- }
- this.onStyleChanged(changedStyle)
- }
+ };
+ this.onStyleChanged(changedStyle);
+ };
onLayerDestroy = (index: number) => {
const layers = this.state.mapStyle.layers;
const remainingLayers = layers.slice(0);
remainingLayers.splice(index, 1);
this.onLayersChange(remainingLayers);
- }
+ };
onLayerCopy = (index: number) => {
const layers = this.state.mapStyle.layers;
- const changedLayers = layers.slice(0)
+ const changedLayers = layers.slice(0);
- const clonedLayer = cloneDeep(changedLayers[index])
- clonedLayer.id = clonedLayer.id + "-copy"
- changedLayers.splice(index, 0, clonedLayer)
- this.onLayersChange(changedLayers)
- }
+ const clonedLayer = cloneDeep(changedLayers[index]);
+ clonedLayer.id = clonedLayer.id + "-copy";
+ changedLayers.splice(index, 0, clonedLayer);
+ this.onLayersChange(changedLayers);
+ };
onLayerVisibilityToggle = (index: number) => {
const layers = this.state.mapStyle.layers;
- const changedLayers = layers.slice(0)
+ const changedLayers = layers.slice(0);
- const layer = { ...changedLayers[index] }
- const changedLayout = 'layout' in layer ? {...layer.layout} : {}
- changedLayout.visibility = changedLayout.visibility === 'none' ? 'visible' : 'none'
+ const layer = { ...changedLayers[index] };
+ const changedLayout = "layout" in layer ? {...layer.layout} : {};
+ changedLayout.visibility = changedLayout.visibility === "none" ? "visible" : "none";
- layer.layout = changedLayout
- changedLayers[index] = layer
- this.onLayersChange(changedLayers)
- }
+ layer.layout = changedLayout;
+ changedLayers[index] = layer;
+ this.onLayersChange(changedLayers);
+ };
onLayerIdChange = (index: number, _oldId: string, newId: string) => {
- const changedLayers = this.state.mapStyle.layers.slice(0)
+ const changedLayers = this.state.mapStyle.layers.slice(0);
changedLayers[index] = {
...changedLayers[index],
id: newId
- }
+ };
- this.onLayersChange(changedLayers)
- }
+ this.onLayersChange(changedLayers);
+ };
onLayerChanged = (index: number, layer: LayerSpecification) => {
- const changedLayers = this.state.mapStyle.layers.slice(0)
- changedLayers[index] = layer
+ const changedLayers = this.state.mapStyle.layers.slice(0);
+ changedLayers[index] = layer;
- this.onLayersChange(changedLayers)
- }
+ this.onLayersChange(changedLayers);
+ };
setMapState = (newState: MapState) => {
this.setState({
mapState: newState
}, this.setStateInUrl);
- }
+ };
setDefaultValues = (styleObj: StyleSpecificationWithId) => {
- const metadata: {[key: string]: string} = styleObj.metadata || {} as any
- if(metadata['maputnik:renderer'] === undefined) {
+ const metadata: {[key: string]: string} = styleObj.metadata || {} as any;
+ if(metadata["maputnik:renderer"] === undefined) {
const changedStyle = {
...styleObj,
metadata: {
...styleObj.metadata as any,
- 'maputnik:renderer': 'mlgljs'
+ "maputnik:renderer": "mlgljs"
}
- }
- return changedStyle
+ };
+ return changedStyle;
} else {
- return styleObj
+ return styleObj;
}
- }
+ };
openStyle = (styleObj: StyleSpecificationWithId, fileHandle: FileSystemFileHandle | null) => {
this.setState({fileHandle: fileHandle});
- styleObj = this.setDefaultValues(styleObj)
- this.onStyleChanged(styleObj)
- }
+ styleObj = this.setDefaultValues(styleObj);
+ this.onStyleChanged(styleObj);
+ };
async fetchSources() {
const sourceList: {[key: string]: SourceSpecification & {layers: string[]}} = {};
for(const key of Object.keys(this.state.mapStyle.sources)) {
const source = this.state.mapStyle.sources[key];
- if(source.type !== "vector" || !('url' in source)) {
+ if(source.type !== "vector" || !("url" in source)) {
sourceList[key] = this.state.sources[key] || {...this.state.mapStyle.sources[key]};
if (sourceList[key].layers === undefined) {
sourceList[key].layers = [];
@@ -616,7 +616,7 @@ export default class App extends React.Component {
let url = source.url;
try {
- url = setFetchAccessToken(url!, this.state.mapStyle)
+ url = setFetchAccessToken(url!, this.state.mapStyle);
} catch(err) {
console.warn("Failed to setFetchAccessToken: ", err);
}
@@ -627,7 +627,7 @@ export default class App extends React.Component {
}
for(const layer of json.vector_layers) {
- sourceList[key].layers.push(layer.id)
+ sourceList[key].layers.push(layer.id);
}
};
@@ -636,7 +636,7 @@ export default class App extends React.Component {
const json = await (new PMTiles(url!.substring(10))).getTileJson("");
setVectorLayers(json);
} else {
- const response = await fetch(url!, { mode: 'cors' });
+ const response = await fetch(url!, { mode: "cors" });
const json = await response.json();
setVectorLayers(json);
}
@@ -650,13 +650,13 @@ export default class App extends React.Component {
console.debug("Setting sources", sourceList);
this.setState({
sources: sourceList
- })
+ });
}
}
_getRenderer () {
const metadata: {[key:string]: string} = this.state.mapStyle.metadata || {} as any;
- return metadata['maputnik:renderer'] || 'mlgljs';
+ return metadata["maputnik:renderer"] || "mlgljs";
}
onMapChange = (mapView: {
@@ -669,7 +669,7 @@ export default class App extends React.Component {
this.setState({
mapView,
});
- }
+ };
mapRenderer() {
const {mapStyle, dirtyMapStyle} = this.state;
@@ -682,23 +682,23 @@ export default class App extends React.Component {
});
},
onDataChange: (e: {map: Map}) => {
- this.layerWatcher.analyzeMap(e.map)
+ this.layerWatcher.analyzeMap(e.map);
this.fetchSources();
},
- }
+ };
const renderer = this._getRenderer();
let mapElement;
// Check if OL code has been loaded?
- if(renderer === 'ol') {
+ if(renderer === "ol") {
mapElement = this.onLayerSelect(+layerId)}
- />
+ />;
} else {
mapElement = {
options={this.state.maplibreGlDebugOptions}
inspectModeEnabled={this.state.mapState === "inspect"}
highlightedLayer={this.state.mapStyle.layers[this.state.selectedLayerIndex]}
- onLayerSelect={this.onLayerSelect} />
+ onLayerSelect={this.onLayerSelect} />;
}
let filterName;
@@ -720,7 +720,7 @@ export default class App extends React.Component {
return
{mapElement}
-
+ ;
}
setStateInUrl = () => {
@@ -749,7 +749,7 @@ export default class App extends React.Component {
}
history.replaceState({selectedLayerIndex}, "Maputnik", url.href);
- }
+ };
getInitialStateFromUrl = (mapStyle: StyleSpecification) => {
const url = new URL(location.href);
@@ -802,14 +802,14 @@ export default class App extends React.Component {
console.warn(err);
}
}
- }
+ };
onLayerSelect = (index: number) => {
this.setState({
selectedLayerIndex: index,
selectedLayerOriginalId: this.state.mapStyle.layers[index].id,
}, this.setStateInUrl);
- }
+ };
setModal(modalName: keyof AppState["isOpen"], value: boolean) {
this.setState({
@@ -817,7 +817,7 @@ export default class App extends React.Component {
...this.state.isOpen,
[modalName]: value
}
- }, this.setStateInUrl)
+ }, this.setStateInUrl);
}
toggleModal(modalName: keyof AppState["isOpen"]) {
@@ -826,7 +826,7 @@ export default class App extends React.Component {
onSetFileHandle = (fileHandle: FileSystemFileHandle | null) => {
this.setState({ fileHandle });
- }
+ };
onChangeOpenlayersDebug = (key: keyof AppState["openlayersDebugOptions"], value: boolean) => {
this.setState({
@@ -835,7 +835,7 @@ export default class App extends React.Component {
[key]: value,
}
});
- }
+ };
onChangeMaplibreGlDebug = (key: keyof AppState["maplibreGlDebugOptions"], value: any) => {
this.setState({
@@ -844,11 +844,11 @@ export default class App extends React.Component {
[key]: value,
}
});
- }
+ };
render() {
- const layers = this.state.mapStyle.layers || []
- const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : undefined
+ const layers = this.state.mapStyle.layers || [];
+ const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : undefined;
const toolbar = {
onStyleOpen={this.onStyleChanged}
onSetMapState={this.setMapState}
onToggleModal={this.toggleModal.bind(this)}
- />
+ />;
const layerList = {
layers={layers}
sources={this.state.sources}
errors={this.state.errors}
- />
+ />;
const layerEditor = selectedLayer ? {
onLayerVisibilityToggle={this.onLayerVisibilityToggle}
onLayerIdChange={this.onLayerIdChange}
errors={this.state.errors}
- /> : undefined
+ /> : undefined;
const bottomPanel = (this.state.errors.length + this.state.infos.length) > 0 ? {
mapStyle={this.state.mapStyle}
errors={this.state.errors}
infos={this.state.infos}
- /> : undefined
+ /> : undefined;
const modals =
@@ -911,41 +911,41 @@ export default class App extends React.Component
{
onChangeMaplibreGlDebug={this.onChangeMaplibreGlDebug}
onChangeOpenlayersDebug={this.onChangeOpenlayersDebug}
isOpen={this.state.isOpen.debug}
- onOpenToggle={this.toggleModal.bind(this, 'debug')}
+ onOpenToggle={this.toggleModal.bind(this, "debug")}
mapView={this.state.mapView}
/>
-
+ ;
return {
map={this.mapRenderer()}
bottom={bottomPanel}
modals={modals}
- />
+ />;
}
}
diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx
index 784abbcd..8d6590cc 100644
--- a/src/components/AppLayout.tsx
+++ b/src/components/AppLayout.tsx
@@ -1,7 +1,7 @@
-import React from 'react'
-import ScrollContainer from './ScrollContainer'
-import { WithTranslation, withTranslation } from 'react-i18next';
-import { IconContext } from 'react-icons';
+import React from "react";
+import ScrollContainer from "./ScrollContainer";
+import { type WithTranslation, withTranslation } from "react-i18next";
+import { IconContext } from "react-icons";
type AppLayoutInternalProps = {
toolbar: React.ReactElement
@@ -17,7 +17,7 @@ class AppLayoutInternal extends React.Component {
render() {
document.body.dir = this.props.i18n.dir();
- return
+ return
{this.props.toolbar}
@@ -37,7 +37,7 @@ class AppLayoutInternal extends React.Component
{
}
{this.props.modals}
-
+ ;
}
}
diff --git a/src/components/AppMessagePanel.tsx b/src/components/AppMessagePanel.tsx
index 2e7df6b4..c2fe44e4 100644
--- a/src/components/AppMessagePanel.tsx
+++ b/src/components/AppMessagePanel.tsx
@@ -1,7 +1,7 @@
-import React from 'react'
-import {formatLayerId} from '../libs/format';
-import {LayerSpecification, StyleSpecification} from 'maplibre-gl';
-import { Trans, WithTranslation, withTranslation } from 'react-i18next';
+import React from "react";
+import {formatLayerId} from "../libs/format";
+import {type LayerSpecification, type StyleSpecification} from "maplibre-gl";
+import { Trans, type WithTranslation, withTranslation } from "react-i18next";
type AppMessagePanelInternalProps = {
errors?: unknown[]
@@ -15,7 +15,7 @@ type AppMessagePanelInternalProps = {
class AppMessagePanelInternal extends React.Component
{
static defaultProps = {
onLayerSelect: () => {},
- }
+ };
render() {
const {t, selectedLayerIndex} = this.props;
@@ -48,17 +48,17 @@ class AppMessagePanelInternal extends React.Component
{content}
-
- })
+ ;
+ });
const infos = this.props.infos?.map((m, i) => {
- return {m}
- })
+ return {m}
;
+ });
return
{errors}
{infos}
-
+ ;
}
}
diff --git a/src/components/AppToolbar.tsx b/src/components/AppToolbar.tsx
index 2844c4bf..d3359174 100644
--- a/src/components/AppToolbar.tsx
+++ b/src/components/AppToolbar.tsx
@@ -1,6 +1,6 @@
-import React from 'react'
-import classnames from 'classnames'
-import {detect} from 'detect-browser';
+import React from "react";
+import classnames from "classnames";
+import {detect} from "detect-browser";
import {
MdOpenInBrowser,
@@ -10,17 +10,17 @@ import {
MdFindInPage,
MdLanguage,
MdSave
-} from 'react-icons/md'
-import pkgJson from '../../package.json'
+} from "react-icons/md";
+import pkgJson from "../../package.json";
//@ts-ignore
-import maputnikLogo from 'maputnik-design/logos/logo-color.svg?inline'
-import { withTranslation, WithTranslation } from 'react-i18next';
-import { supportedLanguages } from '../i18n';
-import type { OnStyleChangedCallback } from '../libs/definitions';
+import maputnikLogo from "maputnik-design/logos/logo-color.svg?inline";
+import { withTranslation, type WithTranslation } from "react-i18next";
+import { supportedLanguages } from "../i18n";
+import type { OnStyleChangedCallback } from "../libs/definitions";
// This is required because of , there isn't another way to detect support that I'm aware of.
const browser = detect();
-const colorAccessibilityFiltersEnabled = ['chrome', 'firefox'].indexOf(browser!.name) > -1;
+const colorAccessibilityFiltersEnabled = ["chrome", "firefox"].indexOf(browser!.name) > -1;
type IconTextProps = {
@@ -30,7 +30,7 @@ type IconTextProps = {
class IconText extends React.Component {
render() {
- return {this.props.children}
+ return {this.props.children};
}
}
@@ -44,14 +44,14 @@ type ToolbarLinkProps = {
class ToolbarLink extends React.Component {
render() {
return
{this.props.children}
-
+ ;
}
}
@@ -67,7 +67,7 @@ class ToolbarSelect extends React.Component {
data-wd-key={this.props.wdKey}
>
{this.props.children}
-
+ ;
}
}
@@ -85,7 +85,7 @@ class ToolbarAction extends React.Component {
onClick={this.props.onClick}
>
{this.props.children}
-
+ ;
}
}
@@ -115,7 +115,7 @@ class AppToolbarInternal extends React.Component {
add: false,
export: false,
}
- }
+ };
handleSelection(val: MapState) {
this.props.onSetMapState(val);
@@ -133,7 +133,7 @@ class AppToolbarInternal extends React.Component {
const el = document.querySelector("#skip-target-"+target) as HTMLButtonElement;
el.focus();
}
- }
+ };
render() {
const t = this.props.t;
@@ -147,7 +147,7 @@ class AppToolbarInternal extends React.Component {
id: "inspect",
group: "general",
title: t("Inspect"),
- disabled: this.props.renderer === 'ol',
+ disabled: this.props.renderer === "ol",
},
{
id: "filter-deuteranopia",
@@ -220,19 +220,19 @@ class AppToolbarInternal extends React.Component {
-
+
{t("Open")}
-
+
{t("Save")}
-
+
{t("Data Sources")}
-
+
{t("Style Settings")}
@@ -292,7 +292,7 @@ class AppToolbarInternal extends React.Component {
-
+ ;
}
}
diff --git a/src/components/Block.tsx b/src/components/Block.tsx
index 32911812..d38d2af3 100644
--- a/src/components/Block.tsx
+++ b/src/components/Block.tsx
@@ -1,7 +1,7 @@
-import React, {PropsWithChildren, SyntheticEvent} from 'react'
-import classnames from 'classnames'
-import FieldDocLabel from './FieldDocLabel'
-import Doc from './Doc'
+import React, {type PropsWithChildren, type SyntheticEvent} from "react";
+import classnames from "classnames";
+import FieldDocLabel from "./FieldDocLabel";
+import Doc from "./Doc";
type BlockProps = PropsWithChildren & {
"data-wd-key"?: string
@@ -26,13 +26,13 @@ export default class Block extends React.Component {
super(props);
this.state = {
showDoc: false,
- }
+ };
}
onChange(e: React.BaseSyntheticEvent) {
- const value = e.target.value
+ const value = e.target.value;
if (this.props.onChange) {
- return this.props.onChange(value === "" ? undefined : value)
+ return this.props.onChange(value === "" ? undefined : value);
}
}
@@ -40,7 +40,7 @@ export default class Block extends React.Component {
this.setState({
showDoc: val
});
- }
+ };
/**
* Some fields for example bind click events inside the element
@@ -58,7 +58,7 @@ export default class Block extends React.Component {
if (event.nativeEvent.target.nodeName !== "A") {
event.preventDefault();
}
- }
+ };
render() {
return
- })
+ ;
+ });
- return ;
}
}
diff --git a/src/components/InputNumber.tsx b/src/components/InputNumber.tsx
index 19067aa7..ba8f9361 100644
--- a/src/components/InputNumber.tsx
+++ b/src/components/InputNumber.tsx
@@ -1,5 +1,5 @@
-import React, { BaseSyntheticEvent } from 'react'
-import generateUniqueId from '../libs/document-uid';
+import React, { type BaseSyntheticEvent } from "react";
+import generateUniqueId from "../libs/document-uid";
export type InputNumberProps = {
value?: number
@@ -23,22 +23,22 @@ type InputNumberState = {
* This is the value that is currently being edited. It can be an invalid value.
*/
dirtyValue?: number | string | undefined
-}
+};
export default class InputNumber extends React.Component {
static defaultProps = {
rangeStep: 1
- }
+ };
_keyboardEvent: boolean = false;
constructor(props: InputNumberProps) {
- super(props)
+ super(props);
this.state = {
uuid: +generateUniqueId(),
editing: false,
value: props.value,
dirtyValue: props.value,
- }
+ };
}
static getDerivedStateFromProps(props: Readonly, state: InputNumberState) {
@@ -57,7 +57,7 @@ export default class InputNumber extends React.Component this.props.max!) {
- return false
+ return false;
}
- return true
+ return true;
}
resetValue = () => {
@@ -104,14 +104,14 @@ export default class InputNumber extends React.Component) => {
let value = parseFloat(e.target.value);
@@ -132,7 +132,7 @@ export default class InputNumber extends React.Component {
this.setState({editing: false});
- this.resetValue()
+ this.resetValue();
}}
data-wd-key={this.props["data-wd-key"] + "-text"}
/>
-
+ ;
}
else {
const value = this.state.editing ? this.state.dirtyValue : this.state.value;
return
+ />;
}
}
}
diff --git a/src/components/InputSelect.tsx b/src/components/InputSelect.tsx
index 8922a29d..492df824 100644
--- a/src/components/InputSelect.tsx
+++ b/src/components/InputSelect.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React from "react";
export type InputSelectProps = {
value: string
@@ -7,7 +7,7 @@ export type InputSelectProps = {
style?: object
onChange(value: string | [string, any]): unknown
title?: string
- 'aria-label'?: string
+ "aria-label"?: string
};
export default class InputSelect extends React.Component {
@@ -24,9 +24,9 @@ export default class InputSelect extends React.Component {
title={this.props.title}
value={this.props.value}
onChange={e => this.props.onChange(e.target.value)}
- aria-label={this.props['aria-label']}
+ aria-label={this.props["aria-label"]}
>
{ options.map(([val, label]) => ) }
-
+ ;
}
}
diff --git a/src/components/InputSpec.tsx b/src/components/InputSpec.tsx
index d69d1aa1..e6a8481b 100644
--- a/src/components/InputSpec.tsx
+++ b/src/components/InputSpec.tsx
@@ -1,19 +1,19 @@
-import React, { ReactElement } from 'react'
+import React, { type ReactElement } from "react";
-import InputColor, { InputColorProps } from './InputColor'
-import InputNumber, { InputNumberProps } from './InputNumber'
-import InputCheckbox, { InputCheckboxProps } from './InputCheckbox'
-import InputString, { InputStringProps } from './InputString'
-import InputArray, { InputArrayProps } from './InputArray'
-import InputDynamicArray, { InputDynamicArrayProps } from './InputDynamicArray'
-import InputFont, { InputFontProps } from './InputFont'
-import InputAutocomplete, { InputAutocompleteProps } from './InputAutocomplete'
-import InputEnum, { InputEnumProps } from './InputEnum'
-import capitalize from 'lodash.capitalize'
+import InputColor, { type InputColorProps } from "./InputColor";
+import InputNumber, { type InputNumberProps } from "./InputNumber";
+import InputCheckbox, { type InputCheckboxProps } from "./InputCheckbox";
+import InputString, { type InputStringProps } from "./InputString";
+import InputArray, { type InputArrayProps } from "./InputArray";
+import InputDynamicArray, { type InputDynamicArrayProps } from "./InputDynamicArray";
+import InputFont, { type InputFontProps } from "./InputFont";
+import InputAutocomplete, { type InputAutocompleteProps } from "./InputAutocomplete";
+import InputEnum, { type InputEnumProps } from "./InputEnum";
+import capitalize from "lodash.capitalize";
-const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
+const iconProperties = ["background-pattern", "fill-pattern", "line-pattern", "fill-extrusion-pattern", "icon-image"];
-export type FieldSpecType = 'number' | 'enum' | 'resolvedImage' | 'formatted' | 'string' | 'color' | 'boolean' | 'array' | 'numberArray' | 'padding' | 'colorArray' | 'variableAnchorOffsetCollection';
+export type FieldSpecType = "number" | "enum" | "resolvedImage" | "formatted" | "string" | "color" | "boolean" | "array" | "numberArray" | "padding" | "colorArray" | "variableAnchorOffsetCollection";
export type InputSpecProps = {
onChange?(fieldName: string | undefined, value: number | undefined | (string | number | undefined)[]): unknown
@@ -30,7 +30,7 @@ export type InputSpecProps = {
value?: string | number | unknown[] | boolean
/** Override the style of the field */
style?: object
- 'aria-label'?: string
+ "aria-label"?: string
error?: unknown[]
label?: string
action?: ReactElement
@@ -53,96 +53,96 @@ export default class InputSpec extends React.Component {
name: this.props.fieldName,
"data-wd-key": "spec-field-input:" + this.props.fieldName,
onChange: (newValue: number | undefined | (string | number | undefined)[]) => this.props.onChange!(this.props.fieldName, newValue),
- 'aria-label': this.props['aria-label'],
- }
+ "aria-label": this.props["aria-label"],
+ };
switch(this.props.fieldSpec?.type) {
- case 'number': return (
-
- )
- case 'enum': {
- const options = Object.keys(this.props.fieldSpec.values || []).map(v => [v, capitalize(v)])
+ case "number": return (
+
+ );
+ case "enum": {
+ const options = Object.keys(this.props.fieldSpec.values || []).map(v => [v, capitalize(v)]);
- return }
- options={options}
- />
- }
- case 'resolvedImage':
- case 'formatted':
- case 'string':
- if (iconProperties.indexOf(this.props.fieldName!) >= 0) {
- const options = this.props.fieldSpec.values || [];
- return }
- options={options.map(f => [f, f])}
- />
- } else {
- return
+ return }
+ options={options}
+ />;
}
- case 'color': return (
-
- )
- case 'boolean': return (
-
- )
- case 'array':
- if(this.props.fieldName === 'text-font') {
- return
- } else {
- if (this.props.fieldSpec.length) {
- return
+ case "resolvedImage":
+ case "formatted":
+ case "string":
+ if (iconProperties.indexOf(this.props.fieldName!) >= 0) {
+ const options = this.props.fieldSpec.values || [];
+ return }
+ options={options.map(f => [f, f])}
+ />;
} else {
- return
+ return ;
}
- }
- case 'numberArray': return (
-
- )
- case 'colorArray': return (
-
- )
- case 'padding': return (
-
- )
- default:
- console.warn(`No proper field input for ${this.props.fieldName} type: ${this.props.fieldSpec?.type}`);
- return null
+ case "color": return (
+
+ );
+ case "boolean": return (
+
+ );
+ case "array":
+ if(this.props.fieldName === "text-font") {
+ return ;
+ } else {
+ if (this.props.fieldSpec.length) {
+ return ;
+ } else {
+ return ;
+ }
+ }
+ case "numberArray": return (
+
+ );
+ case "colorArray": return (
+
+ );
+ case "padding": return (
+
+ );
+ default:
+ console.warn(`No proper field input for ${this.props.fieldName} type: ${this.props.fieldSpec?.type}`);
+ return null;
}
}
diff --git a/src/components/InputString.tsx b/src/components/InputString.tsx
index 1fa91f49..3403e5e2 100644
--- a/src/components/InputString.tsx
+++ b/src/components/InputString.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React from "react";
export type InputStringProps = {
"data-wd-key"?: string
@@ -11,26 +11,26 @@ export type InputStringProps = {
required?: boolean
disabled?: boolean
spellCheck?: boolean
- 'aria-label'?: string
+ "aria-label"?: string
title?: string
};
type InputStringState = {
editing: boolean
value?: string
-}
+};
export default class InputString extends React.Component {
static defaultProps = {
onInput: () => {},
- }
+ };
constructor(props: InputStringProps) {
- super(props)
+ super(props);
this.state = {
editing: false,
- value: props.value || ''
- }
+ value: props.value || ""
+ };
}
static getDerivedStateFromProps(props: Readonly, state: InputStringState) {
@@ -47,17 +47,17 @@ export default class InputString extends React.Component {
static defaultProps = {
onInput: () => {},
- }
+ };
constructor (props: InputUrlInternalProps) {
super(props);
@@ -91,14 +91,14 @@ class InputUrlInternal extends React.Component {
this.setState({
error: validate(url, this.props.t),
});
this.props.onChange(url);
- }
+ };
render () {
return (
@@ -107,7 +107,7 @@ class InputUrlInternal extends React.Component
{this.state.error}
diff --git a/src/components/LayerEditor.tsx b/src/components/LayerEditor.tsx
index cc803424..d4803934 100644
--- a/src/components/LayerEditor.tsx
+++ b/src/components/LayerEditor.tsx
@@ -1,35 +1,35 @@
-import React, {type JSX} from 'react'
-import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
-import {Accordion} from 'react-accessible-accordion';
-import {MdMoreVert} from 'react-icons/md'
-import { IconContext } from 'react-icons'
-import {BackgroundLayerSpecification, LayerSpecification, SourceSpecification} from 'maplibre-gl';
-import {v8} from '@maplibre/maplibre-gl-style-spec';
+import React, {type JSX} from "react";
+import { Wrapper, Button, Menu, MenuItem } from "react-aria-menubutton";
+import {Accordion} from "react-accessible-accordion";
+import {MdMoreVert} from "react-icons/md";
+import { IconContext } from "react-icons";
+import {type BackgroundLayerSpecification, type LayerSpecification, type SourceSpecification} from "maplibre-gl";
+import {v8} from "@maplibre/maplibre-gl-style-spec";
-import FieldJson from './FieldJson'
-import FilterEditor from './FilterEditor'
-import PropertyGroup from './PropertyGroup'
-import LayerEditorGroup from './LayerEditorGroup'
-import FieldType from './FieldType'
-import FieldId from './FieldId'
-import FieldMinZoom from './FieldMinZoom'
-import FieldMaxZoom from './FieldMaxZoom'
-import FieldComment from './FieldComment'
-import FieldSource from './FieldSource'
-import FieldSourceLayer from './FieldSourceLayer'
-import { changeType, changeProperty } from '../libs/layer'
-import {formatLayerId} from '../libs/format';
-import { WithTranslation, withTranslation } from 'react-i18next';
-import { TFunction } from 'i18next';
-import { NON_SOURCE_LAYERS } from '../libs/non-source-layers';
-import { OnMoveLayerCallback } from '../libs/definitions';
+import FieldJson from "./FieldJson";
+import FilterEditor from "./FilterEditor";
+import PropertyGroup from "./PropertyGroup";
+import LayerEditorGroup from "./LayerEditorGroup";
+import FieldType from "./FieldType";
+import FieldId from "./FieldId";
+import FieldMinZoom from "./FieldMinZoom";
+import FieldMaxZoom from "./FieldMaxZoom";
+import FieldComment from "./FieldComment";
+import FieldSource from "./FieldSource";
+import FieldSourceLayer from "./FieldSourceLayer";
+import { changeType, changeProperty } from "../libs/layer";
+import {formatLayerId} from "../libs/format";
+import { type WithTranslation, withTranslation } from "react-i18next";
+import { type TFunction } from "i18next";
+import { NON_SOURCE_LAYERS } from "../libs/non-source-layers";
+import { type OnMoveLayerCallback } from "../libs/definitions";
type MaputnikLayoutGroup = {
id: string;
title: string;
type: string;
fields: string[];
-}
+};
function getLayoutForSymbolType(t: TFunction): MaputnikLayoutGroup[] {
const groups: MaputnikLayoutGroup[] = [];
@@ -68,7 +68,7 @@ function getLayoutForSymbolType(t: TFunction): MaputnikLayoutGroup[] {
function getLayoutForType(type: LayerSpecification["type"], t: TFunction): MaputnikLayoutGroup[] {
if (Object.keys(v8.layer.type.values).indexOf(type) < 0) {
- return []
+ return [];
}
if (type === "symbol") {
return getLayoutForSymbolType(t);
@@ -95,23 +95,23 @@ function getLayoutForType(type: LayerSpecification["type"], t: TFunction): Maput
function layoutGroups(layerType: LayerSpecification["type"], t: TFunction): {id: string, title: string, type: string, fields?: string[]}[] {
const layerGroup = {
- id: 'layer',
- title: t('Layer'),
- type: 'layer'
- }
+ id: "layer",
+ title: t("Layer"),
+ type: "layer"
+ };
const filterGroup = {
- id: 'filter',
- title: t('Filter'),
- type: 'filter'
- }
+ id: "filter",
+ title: t("Filter"),
+ type: "filter"
+ };
const editorGroup = {
- id: 'jsoneditor',
- title: t('JSON Editor'),
- type: 'jsoneditor'
- }
+ id: "jsoneditor",
+ title: t("JSON Editor"),
+ type: "jsoneditor"
+ };
return [layerGroup, filterGroup]
.concat(getLayoutForType(layerType, t))
- .concat([editorGroup])
+ .concat([editorGroup]);
}
type LayerEditorInternalProps = {
@@ -141,25 +141,25 @@ class LayerEditorInternal extends React.Component {},
onLayerIdChange: () => {},
onLayerDestroyed: () => {},
- }
+ };
constructor(props: LayerEditorInternalProps) {
- super(props)
+ super(props);
- const editorGroups: {[keys:string]: boolean} = {}
+ const editorGroups: {[keys:string]: boolean} = {};
for (const group of layoutGroups(this.props.layer.type, props.t)) {
- editorGroups[group.title] = true
+ editorGroups[group.title] = true;
}
- this.state = { editorGroups }
+ this.state = { editorGroups };
}
static getDerivedStateFromProps(props: Readonly, state: LayerEditorState) {
- const additionalGroups = { ...state.editorGroups }
+ const additionalGroups = { ...state.editorGroups };
for (const group of getLayoutForType(props.layer.type, props.t)) {
if(!(group.title in additionalGroups)) {
- additionalGroups[group.title] = true
+ additionalGroups[group.title] = true;
}
}
@@ -173,23 +173,23 @@ class LayerEditorInternal extends React.Component;
@@ -213,82 +213,82 @@ class LayerEditorInternal extends React.Component
- this.props.onLayerIdChange(this.props.layerIndex, this.props.layer.id, newId)}
- />
- this.props.onLayerChanged(
- this.props.layerIndex,
- changeType(this.props.layer, newType)
- )}
- />
- {this.props.layer.type !== 'background' && this.changeProperty(null, 'source', v)}
- />
- }
- {!NON_SOURCE_LAYERS.includes(this.props.layer.type) &&
- this.changeProperty(null, 'source-layer', v)}
+ case "layer": return
+ this.props.onLayerIdChange(this.props.layerIndex, this.props.layer.id, newId)}
/>
- }
- this.changeProperty(null, 'minzoom', v)}
- />
- this.changeProperty(null, 'maxzoom', v)}
- />
- this.changeProperty('metadata', 'maputnik:comment', v == "" ? undefined : v)}
- />
-
- case 'filter': return
-
- this.changeProperty(null, 'filter', f)}
- />
-
-
- case 'properties':
- return
- case 'jsoneditor':
- return {
- this.props.onLayerChanged(
+ this.props.onLayerChanged(
this.props.layerIndex,
- layer
- );
- }}
- />
- default: return <>>
+ changeType(this.props.layer, newType)
+ )}
+ />
+ {this.props.layer.type !== "background" && this.changeProperty(null, "source", v)}
+ />
+ }
+ {!NON_SOURCE_LAYERS.includes(this.props.layer.type) &&
+ this.changeProperty(null, "source-layer", v)}
+ />
+ }
+ this.changeProperty(null, "minzoom", v)}
+ />
+ this.changeProperty(null, "maxzoom", v)}
+ />
+ this.changeProperty("metadata", "maputnik:comment", v == "" ? undefined : v)}
+ />
+ ;
+ case "filter": return
+
+ this.changeProperty(null, "filter", f)}
+ />
+
+
;
+ case "properties":
+ return ;
+ case "jsoneditor":
+ return {
+ this.props.onLayerChanged(
+ this.props.layerIndex,
+ layer
+ );
+ }}
+ />;
+ default: return <>>;
}
}
@@ -296,16 +296,16 @@ class LayerEditorInternal extends React.Component {
- return !(layerType === 'background' && group.type === 'source')
+ return !(layerType === "background" && group.type === "source");
}).map(group => {
const groupId = group.id;
groupIds.push(groupId);
@@ -318,10 +318,10 @@ class LayerEditorInternal extends React.Component
{this.renderGroupType(group.type, group.fields)}
-
- })
+ ;
+ });
- const layout = this.props.layer.layout || {}
+ const layout = this.props.layer.layout || {};
const items: {[key: string]: {
text: string,
@@ -356,14 +356,14 @@ class LayerEditorInternal extends React.Component this.moveLayer(+1),
wdKey: "menu-move-layer-down"
}
- }
+ };
function handleSelection(id: string, event: React.SyntheticEvent) {
event.stopPropagation();
items[id].handler();
}
- return
+ return
{item.text}
-
+ ;
})}
@@ -412,7 +412,7 @@ class LayerEditorInternal extends React.Component
-
+ ;
}
}
diff --git a/src/components/LayerEditorGroup.tsx b/src/components/LayerEditorGroup.tsx
index 33f32712..d41a738f 100644
--- a/src/components/LayerEditorGroup.tsx
+++ b/src/components/LayerEditorGroup.tsx
@@ -1,15 +1,15 @@
-import React from 'react'
-import Icon from '@mdi/react'
+import React from "react";
+import Icon from "@mdi/react";
import {
mdiMenuDown,
mdiMenuUp
-} from '@mdi/js';
+} from "@mdi/js";
import {
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel,
-} from 'react-accessible-accordion';
+} from "react-accessible-accordion";
type LayerEditorGroupProps = {
@@ -46,6 +46,6 @@ export default class LayerEditorGroup extends React.Component
{this.props.children}
-
+ ;
}
}
diff --git a/src/components/LayerList.tsx b/src/components/LayerList.tsx
index 5c12dbd2..a515b856 100644
--- a/src/components/LayerList.tsx
+++ b/src/components/LayerList.tsx
@@ -1,28 +1,28 @@
-import React, {type JSX} from 'react'
-import classnames from 'classnames'
-import lodash from 'lodash';
+import React, {type JSX} from "react";
+import classnames from "classnames";
+import lodash from "lodash";
import {
DndContext,
PointerSensor,
useSensor,
useSensors,
closestCenter,
- DragEndEvent,
-} from '@dnd-kit/core';
+ type DragEndEvent,
+} from "@dnd-kit/core";
import {
SortableContext,
verticalListSortingStrategy,
-} from '@dnd-kit/sortable';
+} from "@dnd-kit/sortable";
-import LayerListGroup from './LayerListGroup'
-import LayerListItem from './LayerListItem'
-import ModalAdd from './modals/ModalAdd'
+import LayerListGroup from "./LayerListGroup";
+import LayerListItem from "./LayerListItem";
+import ModalAdd from "./modals/ModalAdd";
-import type {LayerSpecification, SourceSpecification} from 'maplibre-gl';
-import generateUniqueId from '../libs/document-uid';
-import { findClosestCommonPrefix, layerPrefix } from '../libs/layer';
-import { WithTranslation, withTranslation } from 'react-i18next';
-import { OnMoveLayerCallback } from '../libs/definitions';
+import type {LayerSpecification, SourceSpecification} from "maplibre-gl";
+import generateUniqueId from "../libs/document-uid";
+import { findClosestCommonPrefix, layerPrefix } from "../libs/layer";
+import { type WithTranslation, withTranslation } from "react-i18next";
+import { type OnMoveLayerCallback } from "../libs/definitions";
type LayerListContainerProps = {
layers: LayerSpecification[]
@@ -48,7 +48,7 @@ type LayerListContainerState = {
class LayerListContainerInternal extends React.Component {
static defaultProps = {
onLayerSelect: () => {},
- }
+ };
selectedItemRef: React.RefObject;
scrollContainerRef: React.RefObject;
@@ -65,7 +65,7 @@ class LayerListContainerInternal extends React.Component {
- let idx = 0
+ let idx = 0;
- const newGroups: {[key:string]: boolean} = {}
+ const newGroups: {[key:string]: boolean} = {};
this.groupedLayers().forEach(layers => {
- const groupPrefix = layerPrefix(layers[0].id)
- const lookupKey = [groupPrefix, idx].join('-')
+ const groupPrefix = layerPrefix(layers[0].id);
+ const lookupKey = [groupPrefix, idx].join("-");
if (layers.length > 1) {
- newGroups[lookupKey] = this.state.areAllGroupsExpanded
+ newGroups[lookupKey] = this.state.areAllGroupsExpanded;
}
layers.forEach((_layer) => {
- idx += 1
- })
+ idx += 1;
+ });
});
this.setState({
collapsedGroups: newGroups,
areAllGroupsExpanded: !this.state.areAllGroupsExpanded
- })
- }
+ });
+ };
groupedLayers(): (LayerSpecification & {key: string})[][] {
- const groups = []
+ const groups = [];
const layerIdCount = new Map();
for (let i = 0; i < this.props.layers.length; i++) {
const origLayer = this.props.layers[i];
- const previousLayer = this.props.layers[i-1]
+ const previousLayer = this.props.layers[i-1];
layerIdCount.set(origLayer.id,
layerIdCount.has(origLayer.id) ? layerIdCount.get(origLayer.id) + 1 : 0
);
const layer = {
...origLayer,
key: `layers-list-${origLayer.id}-${layerIdCount.get(origLayer.id)}`,
- }
+ };
if(previousLayer && layerPrefix(previousLayer.id) == layerPrefix(layer.id)) {
- const lastGroup = groups[groups.length - 1]
- lastGroup.push(layer)
+ const lastGroup = groups[groups.length - 1];
+ lastGroup.push(layer);
} else {
- groups.push([layer])
+ groups.push([layer]);
}
}
- return groups
+ return groups;
}
toggleLayerGroup(groupPrefix: string, idx: number) {
- const lookupKey = [groupPrefix, idx].join('-')
- const newGroups = { ...this.state.collapsedGroups }
+ const lookupKey = [groupPrefix, idx].join("-");
+ const newGroups = { ...this.state.collapsedGroups };
if(lookupKey in this.state.collapsedGroups) {
- newGroups[lookupKey] = !this.state.collapsedGroups[lookupKey]
+ newGroups[lookupKey] = !this.state.collapsedGroups[lookupKey];
} else {
- newGroups[lookupKey] = false
+ newGroups[lookupKey] = false;
}
this.setState({
collapsedGroups: newGroups
- })
+ });
}
isCollapsed(groupPrefix: string, idx: number) {
- const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join('-')]
- return collapsed === undefined ? true : collapsed
+ const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join("-")];
+ return collapsed === undefined ? true : collapsed;
}
shouldComponentUpdate (nextProps: LayerListContainerProps, nextState: LayerListContainerState) {
@@ -177,7 +177,7 @@ class LayerListContainerInternal extends React.Component {
observer.unobserve(target);
if (entries.length > 0 && entries[0].intersectionRatio < 1) {
@@ -215,25 +215,25 @@ class LayerListContainerInternal extends React.Component {
- const groupPrefix = layerPrefix(layers[0].id)
+ const groupPrefix = layerPrefix(layers[0].id);
if(layers.length > 1) {
const grp = l.key).join(" ")}
key={`group-${groupPrefix}-${idx}`}
title={groupPrefix}
isActive={!this.isCollapsed(groupPrefix, idx) || idx === this.props.selectedLayerIndex}
onActiveToggle={this.toggleLayerGroup.bind(this, groupPrefix, idx)}
- />
- listItems.push(grp)
+ />;
+ listItems.push(grp);
}
layers.forEach((layer, idxInGroup) => {
- const groupIdx = findClosestCommonPrefix(this.props.layers, idx)
+ const groupIdx = findClosestCommonPrefix(this.props.layers, idx);
const layerError = this.props.errors.find(error => {
return (
@@ -250,9 +250,9 @@ class LayerListContainerInternal extends React.Component 1 && this.isCollapsed(groupPrefix, groupIdx) && idx !== this.props.selectedLayerIndex,
- 'maputnik-layer-list-item-group-last': idxInGroup == layers.length - 1 && layers.length > 1,
- 'maputnik-layer-list-item--error': !!layerError
+ "maputnik-layer-list-item-collapsed": layers.length > 1 && this.isCollapsed(groupPrefix, groupIdx) && idx !== this.props.selectedLayerIndex,
+ "maputnik-layer-list-item-group-last": idxInGroup == layers.length - 1 && layers.length > 1,
+ "maputnik-layer-list-item--error": !!layerError
})}
key={layer.key}
id={layer.key}
@@ -266,11 +266,11 @@ class LayerListContainerInternal extends React.Component
- listItems.push(listItem)
- idx += 1
- })
- })
+ />;
+ listItems.push(listItem);
+ idx += 1;
+ });
+ });
const t = this.props.t;
@@ -286,7 +286,7 @@ class LayerListContainerInternal extends React.Component
-
+ ;
}
}
diff --git a/src/components/modals/ModalExport.tsx b/src/components/modals/ModalExport.tsx
index 87e8105b..becb89e1 100644
--- a/src/components/modals/ModalExport.tsx
+++ b/src/components/modals/ModalExport.tsx
@@ -1,17 +1,17 @@
-import React from 'react'
-import Slugify from 'slugify'
-import {saveAs} from 'file-saver'
-import {version} from 'maplibre-gl/package.json'
-import {format} from '@maplibre/maplibre-gl-style-spec'
-import {MdMap, MdSave} from 'react-icons/md'
-import {WithTranslation, withTranslation} from 'react-i18next';
+import React from "react";
+import Slugify from "slugify";
+import {saveAs} from "file-saver";
+import {version} from "maplibre-gl/package.json";
+import {format} from "@maplibre/maplibre-gl-style-spec";
+import {MdMap, MdSave} from "react-icons/md";
+import {type WithTranslation, withTranslation} from "react-i18next";
-import FieldString from '../FieldString'
-import InputButton from '../InputButton'
-import Modal from './Modal'
-import style from '../../libs/style'
-import fieldSpecAdditional from '../../libs/field-spec-additional'
-import type {OnStyleChangedCallback, StyleSpecificationWithId} from '../../libs/definitions'
+import FieldString from "../FieldString";
+import InputButton from "../InputButton";
+import Modal from "./Modal";
+import style from "../../libs/style";
+import fieldSpecAdditional from "../../libs/field-spec-additional";
+import type {OnStyleChangedCallback, StyleSpecificationWithId} from "../../libs/definitions";
const MAPLIBRE_GL_VERSION = version;
@@ -41,12 +41,12 @@ class ModalExportInternal extends React.Component {
exportName() {
if (this.props.mapStyle.name) {
return Slugify(this.props.mapStyle.name, {
- replacement: '_',
+ replacement: "_",
remove: /[*\-+~.()'"!:]/g,
lower: true
});
} else {
- return this.props.mapStyle.id
+ return this.props.mapStyle.id;
}
}
@@ -99,7 +99,7 @@ class ModalExportInternal extends React.Component {
let fileHandle = this.props.fileHandle;
if (fileHandle == null) {
fileHandle = await this.createFileHandle();
- this.props.onSetFileHandle(fileHandle)
+ this.props.onSetFileHandle(fileHandle);
if (fileHandle == null) return;
}
@@ -113,7 +113,7 @@ class ModalExportInternal extends React.Component {
const tokenStyle = this.tokenizedStyle();
const fileHandle = await this.createFileHandle();
- this.props.onSetFileHandle(fileHandle)
+ this.props.onSetFileHandle(fileHandle);
if (fileHandle == null) return;
const writable = await fileHandle.createWritable();
@@ -134,7 +134,7 @@ class ModalExportInternal extends React.Component {
};
const fileHandle = await window.showSaveFilePicker(pickerOpts) as FileSystemFileHandle;
- this.props.onSetFileHandle(fileHandle)
+ this.props.onSetFileHandle(fileHandle);
return fileHandle;
}
@@ -145,8 +145,8 @@ class ModalExportInternal extends React.Component {
...this.props.mapStyle.metadata as any,
[property]: value
}
- }
- this.props.onStyleChanged(changedStyle)
+ };
+ this.props.onStyleChanged(changedStyle);
}
@@ -157,7 +157,7 @@ class ModalExportInternal extends React.Component {
data-wd-key="modal:export"
isOpen={this.props.isOpen}
onOpenToggle={this.props.onOpenToggle}
- title={t('Save Style')}
+ title={t("Save Style")}
className="maputnik-export-modal"
>
@@ -171,25 +171,25 @@ class ModalExportInternal extends React.Component {
@@ -213,7 +213,7 @@ class ModalExportInternal extends React.Component {
-
+ ;
}
}
diff --git a/src/components/modals/ModalLoading.tsx b/src/components/modals/ModalLoading.tsx
index 8574e7a5..32e3ee25 100644
--- a/src/components/modals/ModalLoading.tsx
+++ b/src/components/modals/ModalLoading.tsx
@@ -1,8 +1,8 @@
-import React from 'react'
-import { WithTranslation, withTranslation } from 'react-i18next';
+import React from "react";
+import { type WithTranslation, withTranslation } from "react-i18next";
-import InputButton from '../InputButton'
-import Modal from './Modal'
+import InputButton from "../InputButton";
+import Modal from "./Modal";
type ModalLoadingInternalProps = {
@@ -31,7 +31,7 @@ class ModalLoadingInternal extends React.Component {
{t("Cancel")}
-
+ ;
}
}
diff --git a/src/components/modals/ModalOpen.tsx b/src/components/modals/ModalOpen.tsx
index 57e48246..f7e7cc4c 100644
--- a/src/components/modals/ModalOpen.tsx
+++ b/src/components/modals/ModalOpen.tsx
@@ -1,16 +1,16 @@
-import React, { FormEvent } from 'react'
-import {MdFileUpload} from 'react-icons/md'
-import {MdAddCircleOutline} from 'react-icons/md'
-import FileReaderInput, { Result } from 'react-file-reader-input'
-import { Trans, WithTranslation, withTranslation } from 'react-i18next';
+import React, { type FormEvent } from "react";
+import {MdFileUpload} from "react-icons/md";
+import {MdAddCircleOutline} from "react-icons/md";
+import FileReaderInput, { type Result } from "react-file-reader-input";
+import { Trans, type WithTranslation, withTranslation } from "react-i18next";
-import ModalLoading from './ModalLoading'
-import Modal from './Modal'
-import InputButton from '../InputButton'
-import InputUrl from '../InputUrl'
+import ModalLoading from "./ModalLoading";
+import Modal from "./Modal";
+import InputButton from "../InputButton";
+import InputUrl from "../InputUrl";
-import style from '../../libs/style'
-import publicStyles from '../../config/styles.json'
+import style from "../../libs/style";
+import publicStyles from "../../config/styles.json";
type PublicStyleProps = {
url: string
@@ -39,7 +39,7 @@ class PublicStyle extends React.Component {
}}
>
-
+ ;
}
}
@@ -68,7 +68,7 @@ class ModalOpenInternal extends React.Component {
this.setState({
@@ -118,8 +118,8 @@ class ModalOpenInternal extends React.Component) => {
e.preventDefault();
this.onStyleSelect(this.state.styleUrl);
- }
+ };
onOpenFile = async () => {
this.clearError();
@@ -155,19 +155,19 @@ class ModalOpenInternal extends React.Component {
let mapStyle;
try {
- mapStyle = JSON.parse(e.target?.result as string)
+ mapStyle = JSON.parse(e.target?.result as string);
}
catch(err) {
this.setState({
@@ -188,12 +188,12 @@ class ModalOpenInternal extends React.Component console.log(e.target);
- }
+ };
onOpenToggle() {
this.setState({
@@ -207,7 +207,7 @@ class ModalOpenInternal extends React.Component
- })
+ />;
+ });
let errorElement;
if(this.state.error) {
@@ -237,7 +237,7 @@ class ModalOpenInternal extends React.Component this.onOpenToggle()}
- title={t('Open Style')}
+ title={t("Open Style")}
>
{errorElement}
@@ -299,12 +299,12 @@ class ModalOpenInternal extends React.Component this.onCancelActiveRequest(e)}
message={t("Loading: {{requestUrl}}", { requestUrl: this.state.activeRequestUrl })}
/>
- )
+ );
}
}
diff --git a/src/components/modals/ModalSettings.tsx b/src/components/modals/ModalSettings.tsx
index 13c25249..cab6ec81 100644
--- a/src/components/modals/ModalSettings.tsx
+++ b/src/components/modals/ModalSettings.tsx
@@ -1,18 +1,18 @@
-import React from 'react'
-import latest from '@maplibre/maplibre-gl-style-spec/dist/latest.json'
-import type {LightSpecification, StyleSpecification, TerrainSpecification, TransitionSpecification} from 'maplibre-gl'
-import { WithTranslation, withTranslation } from 'react-i18next';
+import React from "react";
+import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json";
+import type {LightSpecification, StyleSpecification, TerrainSpecification, TransitionSpecification} from "maplibre-gl";
+import { type WithTranslation, withTranslation } from "react-i18next";
-import FieldArray from '../FieldArray'
-import FieldNumber from '../FieldNumber'
-import FieldString from '../FieldString'
-import FieldUrl from '../FieldUrl'
-import FieldSelect from '../FieldSelect'
-import FieldEnum from '../FieldEnum'
-import FieldColor from '../FieldColor'
-import Modal from './Modal'
-import fieldSpecAdditional from '../../libs/field-spec-additional'
-import type {OnStyleChangedCallback, StyleSpecificationWithId} from '../../libs/definitions';
+import FieldArray from "../FieldArray";
+import FieldNumber from "../FieldNumber";
+import FieldString from "../FieldString";
+import FieldUrl from "../FieldUrl";
+import FieldSelect from "../FieldSelect";
+import FieldEnum from "../FieldEnum";
+import FieldColor from "../FieldColor";
+import Modal from "./Modal";
+import fieldSpecAdditional from "../../libs/field-spec-additional";
+import type {OnStyleChangedCallback, StyleSpecificationWithId} from "../../libs/definitions";
type ModalSettingsInternalProps = {
mapStyle: StyleSpecificationWithId
@@ -26,7 +26,7 @@ class ModalSettingsInternal extends React.Component
changeTransitionProperty(property: keyof TransitionSpecification, value: number | undefined) {
const transition = {
...this.props.mapStyle.transition,
- }
+ };
if (value === undefined) {
delete transition[property];
@@ -44,7 +44,7 @@ class ModalSettingsInternal extends React.Component
changeLightProperty(property: keyof LightSpecification, value: any) {
const light = {
...this.props.mapStyle.light,
- }
+ };
if (value === undefined) {
delete light[property];
@@ -108,7 +108,7 @@ class ModalSettingsInternal extends React.Component
data-wd-key="modal:settings"
isOpen={this.props.isOpen}
onOpenToggle={this.props.onOpenToggle}
- title={t('Style Settings')}
+ title={t("Style Settings")}
>
label={fsa.maputnik.maptiler_access_token.label}
fieldSpec={fsa.maputnik.maptiler_access_token}
data-wd-key="modal:settings.maputnik:openmaptiles_access_token"
- value={metadata['maputnik:openmaptiles_access_token']}
+ value={metadata["maputnik:openmaptiles_access_token"]}
onChange={onChangeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
/>
@@ -153,7 +153,7 @@ class ModalSettingsInternal extends React.Component
label={fsa.maputnik.thunderforest_access_token.label}
fieldSpec={fsa.maputnik.thunderforest_access_token}
data-wd-key="modal:settings.maputnik:thunderforest_access_token"
- value={metadata['maputnik:thunderforest_access_token']}
+ value={metadata["maputnik:thunderforest_access_token"]}
onChange={onChangeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
/>
@@ -161,7 +161,7 @@ class ModalSettingsInternal extends React.Component
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']}
+ value={metadata["maputnik:stadia_access_token"]}
onChange={onChangeMetadataProperty.bind(this, "maputnik:stadia_access_token")}
/>
@@ -169,7 +169,7 @@ class ModalSettingsInternal extends React.Component
label={fsa.maputnik.locationiq_access_token.label}
fieldSpec={fsa.maputnik.locationiq_access_token}
data-wd-key="modal:settings.maputnik:locationiq_access_token"
- value={metadata['maputnik:locationiq_access_token']}
+ value={metadata["maputnik:locationiq_access_token"]}
onChange={onChangeMetadataProperty.bind(this, "maputnik:locationiq_access_token")}
/>
@@ -280,16 +280,16 @@ class ModalSettingsInternal extends React.Component
fieldSpec={fsa.maputnik.style_renderer}
data-wd-key="modal:settings.maputnik:renderer"
options={[
- ['mlgljs', 'MapLibreGL JS'],
- ['ol', t('Open Layers (experimental)')],
+ ["mlgljs", "MapLibreGL JS"],
+ ["ol", t("Open Layers (experimental)")],
]}
- value={metadata['maputnik:renderer'] || 'mlgljs'}
- onChange={onChangeMetadataProperty.bind(this, 'maputnik:renderer')}
+ value={metadata["maputnik:renderer"] || "mlgljs"}
+ onChange={onChangeMetadataProperty.bind(this, "maputnik:renderer")}
/>
-
+ ;
}
}
-const ModalSettings = withTranslation()(ModalSettingsInternal)
+const ModalSettings = withTranslation()(ModalSettingsInternal);
export default ModalSettings;
diff --git a/src/components/modals/ModalShortcuts.tsx b/src/components/modals/ModalShortcuts.tsx
index 139b4e8a..16d3ab70 100644
--- a/src/components/modals/ModalShortcuts.tsx
+++ b/src/components/modals/ModalShortcuts.tsx
@@ -1,7 +1,7 @@
-import React from 'react'
-import { Trans, WithTranslation, withTranslation } from 'react-i18next';
+import React from "react";
+import { Trans, type WithTranslation, withTranslation } from "react-i18next";
-import Modal from './Modal'
+import Modal from "./Modal";
type ModalShortcutsInternalProps = {
@@ -46,7 +46,7 @@ class ModalShortcutsInternal extends React.Component!,
text: t("Debug modal")
},
- ]
+ ];
const mapShortcuts = [
@@ -98,14 +98,14 @@ class ModalShortcutsInternal extends React.ComponentShift + Down>,
text: t("Decrease the pitch by 10 degrees.")
},
- ]
+ ];
return
@@ -118,7 +118,7 @@ class ModalShortcutsInternal extends React.Component
{item.key}
{item.text}
-
+ ;
})}
{t("If the Map is in focused you can use the following shortcuts")}
@@ -126,11 +126,11 @@ class ModalShortcutsInternal extends React.Component {
return
{item.key} {item.text}
-
+ ;
})}
-
+ ;
}
}
diff --git a/src/components/modals/ModalSources.tsx b/src/components/modals/ModalSources.tsx
index 6f398492..91a1e5a5 100644
--- a/src/components/modals/ModalSources.tsx
+++ b/src/components/modals/ModalSources.tsx
@@ -1,19 +1,19 @@
-import React from 'react'
-import {MdAddCircleOutline, MdDelete} from 'react-icons/md'
-import latest from '@maplibre/maplibre-gl-style-spec/dist/latest.json'
-import type {GeoJSONSourceSpecification, RasterDEMSourceSpecification, RasterSourceSpecification, SourceSpecification, VectorSourceSpecification} from 'maplibre-gl'
-import { WithTranslation, withTranslation } from 'react-i18next';
+import React from "react";
+import {MdAddCircleOutline, MdDelete} from "react-icons/md";
+import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json";
+import type {GeoJSONSourceSpecification, RasterDEMSourceSpecification, RasterSourceSpecification, SourceSpecification, VectorSourceSpecification} from "maplibre-gl";
+import { type WithTranslation, withTranslation } from "react-i18next";
-import Modal from './Modal'
-import InputButton from '../InputButton'
-import FieldString from '../FieldString'
-import FieldSelect from '../FieldSelect'
-import ModalSourcesTypeEditor, { EditorMode } from './ModalSourcesTypeEditor'
+import Modal from "./Modal";
+import InputButton from "../InputButton";
+import FieldString from "../FieldString";
+import FieldSelect from "../FieldSelect";
+import ModalSourcesTypeEditor, { type EditorMode } from "./ModalSourcesTypeEditor";
-import style from '../../libs/style'
-import { deleteSource, addSource, changeSource } from '../../libs/source'
-import publicSources from '../../config/tilesets.json'
-import { OnStyleChangedCallback, StyleSpecificationWithId } from '../../libs/definitions';
+import style from "../../libs/style";
+import { deleteSource, addSource, changeSource } from "../../libs/source";
+import publicSources from "../../config/tilesets.json";
+import { type OnStyleChangedCallback, type StyleSpecificationWithId } from "../../libs/definitions";
type PublicSourceProps = {
@@ -37,39 +37,39 @@ class PublicSource extends React.Component {
-
+ ;
}
}
function editorMode(source: SourceSpecification) {
- if(source.type === 'raster') {
- if(source.tiles) return 'tile_raster'
- return 'tilejson_raster'
+ if(source.type === "raster") {
+ if(source.tiles) return "tile_raster";
+ return "tilejson_raster";
}
- if(source.type === 'raster-dem') {
- if(source.tiles) return 'tilexyz_raster-dem'
- return 'tilejson_raster-dem'
+ if(source.type === "raster-dem") {
+ if(source.tiles) return "tilexyz_raster-dem";
+ return "tilejson_raster-dem";
}
- if(source.type === 'vector') {
- if(source.tiles) return 'tile_vector'
- if(source.url && source.url.startsWith("pmtiles://")) return 'pmtiles_vector'
- return 'tilejson_vector'
+ if(source.type === "vector") {
+ if(source.tiles) return "tile_vector";
+ if(source.url && source.url.startsWith("pmtiles://")) return "pmtiles_vector";
+ return "tilejson_vector";
}
- if(source.type === 'geojson') {
+ if(source.type === "geojson") {
if (typeof(source.data) === "string") {
- return 'geojson_url';
+ return "geojson_url";
}
else {
- return 'geojson_json';
+ return "geojson_json";
}
}
- if(source.type === 'image') {
- return 'image';
+ if(source.type === "image") {
+ return "image";
}
- if(source.type === 'video') {
- return 'video';
+ if(source.type === "video") {
+ return "video";
}
- return null
+ return null;
}
type ActiveModalSourcesTypeEditorProps = {
@@ -90,7 +90,7 @@ class ActiveModalSourcesTypeEditor extends React.Component this.props.onDelete(this.props.sourceId)}
- style={{backgroundColor: 'transparent'}}
+ style={{backgroundColor: "transparent"}}
>
@@ -102,7 +102,7 @@ class ActiveModalSourcesTypeEditor extends React.Component
-
+ ;
}
}
@@ -118,100 +118,100 @@ type AddSourceState = {
class AddSource extends React.Component {
constructor(props: AddSourceProps) {
- super(props)
+ super(props);
this.state = {
- mode: 'tilejson_vector',
+ mode: "tilejson_vector",
sourceId: style.generateId(),
- source: this.defaultSource('tilejson_vector'),
- }
+ source: this.defaultSource("tilejson_vector"),
+ };
}
defaultSource(mode: EditorMode): SourceSpecification {
- const source = (this.state || {}).source || {}
+ const source = (this.state || {}).source || {};
const {protocol} = window.location;
switch(mode) {
- case 'pmtiles_vector': return {
- type: 'vector',
- url: `${protocol}//localhost:3000/file.pmtiles`
- }
- case 'geojson_url': return {
- type: 'geojson',
- data: `${protocol}//localhost:3000/geojson.json`
- }
- case 'geojson_json': return {
- type: 'geojson',
- cluster: (source as GeoJSONSourceSpecification).cluster || false,
- data: ''
- }
- case 'tilejson_vector': return {
- type: 'vector',
- url: (source as VectorSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
- }
- 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,
- scheme: (source as VectorSourceSpecification).scheme || 'xyz'
- }
- case 'tilejson_raster': return {
- type: 'raster',
- url: (source as RasterSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
- }
- case 'tile_raster': return {
- type: 'raster',
- tiles: (source as RasterSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
- minzoom: (source as RasterSourceSpecification).minzoom || 0,
- 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',
- url: (source as RasterDEMSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
- }
- case 'tilexyz_raster-dem': return {
- type: 'raster-dem',
- tiles: (source as RasterDEMSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
- minzoom: (source as RasterDEMSourceSpecification).minzoom || 0,
- maxzoom: (source as RasterDEMSourceSpecification).maxzoom || 14,
- tileSize: (source as RasterDEMSourceSpecification).tileSize || 512
- }
- case 'image': return {
- type: 'image',
- url: `${protocol}//localhost:3000/image.png`,
- coordinates: [
- [0,0],
- [0,0],
- [0,0],
- [0,0],
- ],
- }
- case 'video': return {
- type: 'video',
- urls: [
- `${protocol}//localhost:3000/movie.mp4`
- ],
- coordinates: [
- [0,0],
- [0,0],
- [0,0],
- [0,0],
- ],
- }
- default: return {} as any
+ case "pmtiles_vector": return {
+ type: "vector",
+ url: `${protocol}//localhost:3000/file.pmtiles`
+ };
+ case "geojson_url": return {
+ type: "geojson",
+ data: `${protocol}//localhost:3000/geojson.json`
+ };
+ case "geojson_json": return {
+ type: "geojson",
+ cluster: (source as GeoJSONSourceSpecification).cluster || false,
+ data: ""
+ };
+ case "tilejson_vector": return {
+ type: "vector",
+ url: (source as VectorSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
+ };
+ 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,
+ scheme: (source as VectorSourceSpecification).scheme || "xyz"
+ };
+ case "tilejson_raster": return {
+ type: "raster",
+ url: (source as RasterSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
+ };
+ case "tile_raster": return {
+ type: "raster",
+ tiles: (source as RasterSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
+ minzoom: (source as RasterSourceSpecification).minzoom || 0,
+ 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",
+ url: (source as RasterDEMSourceSpecification).url || `${protocol}//localhost:3000/tilejson.json`
+ };
+ case "tilexyz_raster-dem": return {
+ type: "raster-dem",
+ tiles: (source as RasterDEMSourceSpecification).tiles || [`${protocol}//localhost:3000/{x}/{y}/{z}.png`],
+ minzoom: (source as RasterDEMSourceSpecification).minzoom || 0,
+ maxzoom: (source as RasterDEMSourceSpecification).maxzoom || 14,
+ tileSize: (source as RasterDEMSourceSpecification).tileSize || 512
+ };
+ case "image": return {
+ type: "image",
+ url: `${protocol}//localhost:3000/image.png`,
+ coordinates: [
+ [0,0],
+ [0,0],
+ [0,0],
+ [0,0],
+ ],
+ };
+ case "video": return {
+ type: "video",
+ urls: [
+ `${protocol}//localhost:3000/movie.mp4`
+ ],
+ coordinates: [
+ [0,0],
+ [0,0],
+ [0,0],
+ [0,0],
+ ],
+ };
+ default: return {} as any;
}
}
onAdd = () => {
const {source, sourceId} = this.state;
this.props.onAdd(sourceId, source);
- }
+ };
onChangeSource = (source: SourceSpecification) => {
this.setState({source});
- }
+ };
render() {
const t = this.props.t;
@@ -238,17 +238,17 @@ class AddSource extends React.Component {
label={t("Source Type")}
fieldSpec={sourceTypeFieldSpec}
options={[
- ['geojson_json', t('GeoJSON (JSON)')],
- ['geojson_url', t('GeoJSON (URL)')],
- ['tilejson_vector', t('Vector (TileJSON URL)')],
- ['tile_vector', t('Vector (Tile URLs)')],
- ['tilejson_raster', t('Raster (TileJSON URL)')],
- ['tile_raster', t('Raster (Tile URLs)')],
- ['tilejson_raster-dem', t('Raster DEM (TileJSON URL)')],
- ['tilexyz_raster-dem', t('Raster DEM (XYZ URLs)')],
- ['pmtiles_vector', t('Vector (PMTiles)')],
- ['image', t('Image')],
- ['video', t('Video')],
+ ["geojson_json", t("GeoJSON (JSON)")],
+ ["geojson_url", t("GeoJSON (URL)")],
+ ["tilejson_vector", t("Vector (TileJSON URL)")],
+ ["tile_vector", t("Vector (Tile URLs)")],
+ ["tilejson_raster", t("Raster (TileJSON URL)")],
+ ["tile_raster", t("Raster (Tile URLs)")],
+ ["tilejson_raster-dem", t("Raster DEM (TileJSON URL)")],
+ ["tilexyz_raster-dem", t("Raster DEM (XYZ URLs)")],
+ ["pmtiles_vector", t("Vector (PMTiles)")],
+ ["image", t("Image")],
+ ["video", t("Video")],
]}
onChange={mode => this.setState({mode: mode as EditorMode, source: this.defaultSource(mode as EditorMode)})}
value={this.state.mode as string}
@@ -266,7 +266,7 @@ class AddSource extends React.Component {
>
{t("Add Source")}
-
+ ;
}
}
@@ -279,16 +279,16 @@ type ModalSourcesInternalProps = {
class ModalSourcesInternal extends React.Component {
stripTitle(source: SourceSpecification & {title?: string}): SourceSpecification {
- const strippedSource = {...source}
- delete strippedSource['title']
- return strippedSource
+ const strippedSource = {...source};
+ delete strippedSource["title"];
+ return strippedSource;
}
render() {
const {t, mapStyle} = this.props;
const i18nProps = {t, i18n: this.props.i18n, tReady: this.props.tReady};
const activeSources = Object.keys(mapStyle.sources).map(sourceId => {
- const source = mapStyle.sources[sourceId]
+ const source = mapStyle.sources[sourceId];
return {
onChange={(src: SourceSpecification) => this.props.onStyleChanged(changeSource(mapStyle, sourceId, src))}
onDelete={() => this.props.onStyleChanged(deleteSource(mapStyle, sourceId))}
{...i18nProps}
- />
- })
+ />;
+ });
const tilesetOptions = Object.keys(publicSources).filter((sourceId: string) => !(sourceId in mapStyle.sources)).map((sourceId: string) => {
const source = publicSources[sourceId as keyof typeof publicSources] as SourceSpecification & {title: string};
@@ -307,14 +307,14 @@ class ModalSourcesInternal extends React.Component {
type={source.type}
title={source.title}
onSelect={() => this.props.onStyleChanged(addSource(mapStyle, sourceId, this.stripTitle(source)))}
- />
- })
+ />;
+ });
return
{t("Active Sources")}
@@ -339,7 +339,7 @@ class ModalSourcesInternal extends React.Component {
{...i18nProps}
/>
-
+ ;
}
}
diff --git a/src/components/modals/ModalSourcesTypeEditor.tsx b/src/components/modals/ModalSourcesTypeEditor.tsx
index d70a3eaf..075ab4f3 100644
--- a/src/components/modals/ModalSourcesTypeEditor.tsx
+++ b/src/components/modals/ModalSourcesTypeEditor.tsx
@@ -1,16 +1,16 @@
-import React from 'react'
-import {latest} from '@maplibre/maplibre-gl-style-spec'
-import { WithTranslation, withTranslation } from 'react-i18next';
-import { TFunction } from 'i18next'
+import React from "react";
+import {latest} from "@maplibre/maplibre-gl-style-spec";
+import { type WithTranslation, withTranslation } from "react-i18next";
+import { type TFunction } from "i18next";
-import Block from '../Block'
-import FieldUrl from '../FieldUrl'
-import FieldNumber from '../FieldNumber'
-import FieldSelect from '../FieldSelect'
-import FieldDynamicArray from '../FieldDynamicArray'
-import FieldArray from '../FieldArray'
-import FieldJson from '../FieldJson'
-import FieldCheckbox from '../FieldCheckbox'
+import Block from "../Block";
+import FieldUrl from "../FieldUrl";
+import FieldNumber from "../FieldNumber";
+import FieldSelect from "../FieldSelect";
+import FieldDynamicArray from "../FieldDynamicArray";
+import FieldArray from "../FieldArray";
+import FieldJson from "../FieldJson";
+import FieldCheckbox from "../FieldCheckbox";
export type EditorMode = "video" | "image" | "tilejson_vector" | "tile_raster" | "tilejson_raster" | "tilexyz_raster-dem" | "tilejson_raster-dem" | "pmtiles_vector" | "tile_vector" | "geojson_url" | "geojson_json" | null;
@@ -38,7 +38,7 @@ class TileJSONSourceEditor extends React.Component {
})}
/>
{this.props.children}
-
+ ;
}
}
@@ -47,7 +47,7 @@ type TileURLSourceEditorProps = {
tiles: string[]
minzoom: number
maxzoom: number
- scheme: 'xyz' | 'tms'
+ scheme: "xyz" | "tms"
}
onChange(...args: unknown[]): unknown
children?: React.ReactNode
@@ -58,7 +58,7 @@ class TileURLSourceEditor extends React.Component {
this.props.onChange({
...this.props.source,
tiles,
- })
+ });
}
renderTileUrls() {
@@ -69,7 +69,7 @@ class TileURLSourceEditor extends React.Component {
type="url"
value={tiles}
onChange={this.changeTileUrls.bind(this)}
- />
+ />;
}
render() {
@@ -80,8 +80,8 @@ class TileURLSourceEditor extends React.Component {
label={t("Scheme Type")}
fieldSpec={latest.source_vector.scheme}
options={[
- ['xyz', 'xyz (Slippy map tilenames scheme)'],
- ['tms', 'tms (OSGeo spec scheme)'],
+ ["xyz", "xyz (Slippy map tilenames scheme)"],
+ ["tms", "tms (OSGeo spec scheme)"],
]}
onChange={scheme => this.props.onChange({
...this.props.source,
@@ -109,7 +109,7 @@ class TileURLSourceEditor extends React.Component {
})}
/>
{this.props.children}
-
+ ;
}
}
@@ -140,7 +140,7 @@ class ImageSourceEditor extends React.Component {
...this.props.source,
coordinates,
});
- }
+ };
return
{
/>
);
})}
-
+ ;
}
}
@@ -188,14 +188,14 @@ class VideoSourceEditor extends React.Component {
...this.props.source,
coordinates,
});
- }
+ };
const changeUrls = (urls: string[]) => {
this.props.onChange({
...this.props.source,
urls,
});
- }
+ };
return
{
/>
);
})}
-
+ ;
}
}
@@ -241,7 +241,7 @@ class GeoJSONSourceUrlEditor extends React.Component
+ />;
}
}
@@ -270,21 +270,21 @@ class GeoJSONSourceFieldJsonEditor extends React.Component
{
this.props.onChange({
...this.props.source,
cluster: cluster,
- })
+ });
}}
/>
-
+ ;
}
}
@@ -311,7 +311,7 @@ class PMTilesSourceEditor extends React.Component {
})}
/>
{this.props.children}
-
+ ;
}
}
@@ -332,50 +332,50 @@ class ModalSourcesTypeEditorInternal extends React.Component
- case 'geojson_json': return
- case 'tilejson_vector': return
- case 'tile_vector': return
- case 'tilejson_raster': return
- case 'tile_raster': return
- 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"
- />
-
- case 'tilejson_raster-dem': return
- case 'tilexyz_raster-dem': return
- 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"
- />
- this.props.onChange({
- ...this.props.source,
- encoding: encoding
- })}
- value={this.props.source.encoding || latest.source_raster_dem.encoding.default}
- />
-
- case 'pmtiles_vector': return
- case 'image': return
- case 'video': return
- default: return null
+ case "geojson_url": return ;
+ case "geojson_json": return ;
+ case "tilejson_vector": return ;
+ case "tile_vector": return ;
+ case "tilejson_raster": return ;
+ case "tile_raster": return
+ 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"
+ />
+ ;
+ case "tilejson_raster-dem": return ;
+ case "tilexyz_raster-dem": return
+ 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"
+ />
+ this.props.onChange({
+ ...this.props.source,
+ encoding: encoding
+ })}
+ value={this.props.source.encoding || latest.source_raster_dem.encoding.default}
+ />
+ ;
+ case "pmtiles_vector": return ;
+ case "image": return ;
+ case "video": return ;
+ default: return null;
}
}
}
diff --git a/src/index.jsx b/src/index.jsx
index e479a46b..0555be43 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -1,14 +1,14 @@
import { IconContext } from "react-icons";
-import { createRoot } from 'react-dom/client';
+import { createRoot } from "react-dom/client";
-import './favicon.ico'
-import './styles/index.scss'
-import './i18n';
-import App from './components/App';
+import "./favicon.ico";
+import "./styles/index.scss";
+import "./i18n";
+import App from "./components/App";
const root = createRoot(document.querySelector("#app"));
root.render(
-
+
);
diff --git a/src/libs/accessibility.ts b/src/libs/accessibility.ts
index 84091653..14eef302 100644
--- a/src/libs/accessibility.ts
+++ b/src/libs/accessibility.ts
@@ -1,8 +1,8 @@
-import throttle from 'lodash.throttle'
+import throttle from "lodash.throttle";
// Throttle for 3 seconds so when a user enables it they don't have to refresh the page.
const reducedMotionEnabled = throttle(() => {
- return window.matchMedia("(prefers-reduced-motion: reduce)").matches
-}, 3000)
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
+}, 3000);
-export { reducedMotionEnabled }
+export { reducedMotionEnabled };
diff --git a/src/libs/codemirror-mgl.ts b/src/libs/codemirror-mgl.ts
index f078e39b..242d3b6e 100644
--- a/src/libs/codemirror-mgl.ts
+++ b/src/libs/codemirror-mgl.ts
@@ -1,7 +1,7 @@
-import {parse} from '@prantlf/jsonlint';
-import CodeMirror, { MarkerRange } from 'codemirror';
-import jsonToAst from 'json-to-ast';
-import {expression, validateStyleMin} from '@maplibre/maplibre-gl-style-spec';
+import {parse} from "@prantlf/jsonlint";
+import CodeMirror, { type MarkerRange } from "codemirror";
+import jsonToAst from "json-to-ast";
+import {expression, validateStyleMin} from "@maplibre/maplibre-gl-style-spec";
type MarkerRangeWithMessage = MarkerRange & {message: string};
@@ -90,7 +90,7 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
newNode = newNode.value;
}
}
- return getArrayPositionalFromAst(newNode, path.slice(1))
+ return getArrayPositionalFromAst(newNode, path.slice(1));
}
}
@@ -121,12 +121,12 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
// Remove the 'layers[0].' as we're validating the layer only here
const errMessageParts = err.message.replace(/^layers\[0\]./, "").split(":");
return {
- name: '',
+ name: "",
key: errMessageParts[0],
message: errMessageParts[1],
};
})
- }
+ };
}
}
else if (context === "expression") {
@@ -147,11 +147,11 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
from: CodeMirror.Pos(doc.firstLine(), 0),
to: CodeMirror.Pos(doc.lastLine(), lastLineHandle.text.length),
message: message,
- }
+ };
found.push(err);
}
else if (key) {
- const path = key.replace(/^\[|\]$/g, "").split(/\.|[[\]]+/).filter(Boolean)
+ const path = key.replace(/^\[|\]$/g, "").split(/\.|[[\]]+/).filter(Boolean);
const parsedError = getArrayPositionalFromAst(ast, path);
if (!parsedError) {
console.warn("Something went wrong parsing error:", error);
@@ -167,7 +167,7 @@ CodeMirror.registerHelper("lint", "mgl", (text: string, opts: any, doc: any) =>
message: message,
});
}
- })
+ });
}
return found;
diff --git a/src/libs/definitions.d.ts b/src/libs/definitions.d.ts
index b742e1de..00c2b58c 100644
--- a/src/libs/definitions.d.ts
+++ b/src/libs/definitions.d.ts
@@ -6,7 +6,7 @@ export type OnStyleChangedOpts = {
save?: boolean;
addRevision?: boolean;
initialLoad?: boolean;
-}
+};
export type OnStyleChangedCallback = (newStyle: StyleSpecificationWithId, opts: OnStyleChangedOpts={}) => void;
diff --git a/src/libs/diffmessage.ts b/src/libs/diffmessage.ts
index b2dcdce2..b3c31f3b 100644
--- a/src/libs/diffmessage.ts
+++ b/src/libs/diffmessage.ts
@@ -1,14 +1,14 @@
-import {diff} from '@maplibre/maplibre-gl-style-spec'
-import type {StyleSpecification} from 'maplibre-gl'
+import {diff} from "@maplibre/maplibre-gl-style-spec";
+import type {StyleSpecification} from "maplibre-gl";
function diffMessages(beforeStyle: StyleSpecification, afterStyle: StyleSpecification) {
- const changes = diff(beforeStyle, afterStyle)
- return changes.map(cmd => cmd.command + ' ' + cmd.args.join(' '))
+ const changes = diff(beforeStyle, afterStyle);
+ return changes.map(cmd => cmd.command + " " + cmd.args.join(" "));
}
export function undoMessages(beforeStyle: StyleSpecification, afterStyle: StyleSpecification) {
- return diffMessages(beforeStyle, afterStyle).map(m => 'Undo ' + m)
+ return diffMessages(beforeStyle, afterStyle).map(m => "Undo " + m);
}
export function redoMessages(beforeStyle: StyleSpecification, afterStyle: StyleSpecification) {
- return diffMessages(beforeStyle, afterStyle).map(m => 'Redo ' + m)
+ return diffMessages(beforeStyle, afterStyle).map(m => "Redo " + m);
}
diff --git a/src/libs/field-spec-additional.ts b/src/libs/field-spec-additional.ts
index 97de17b5..982eb732 100644
--- a/src/libs/field-spec-additional.ts
+++ b/src/libs/field-spec-additional.ts
@@ -1,4 +1,4 @@
-import { TFunction } from "i18next";
+import { type TFunction } from "i18next";
const spec = (t: TFunction) => ({
maputnik: {
@@ -31,6 +31,6 @@ const spec = (t: TFunction) => ({
doc: t("Choose the default Maputnik renderer for this style.")
},
}
-})
+});
export default spec;
diff --git a/src/libs/filterops.ts b/src/libs/filterops.ts
index 49e4195d..42291f37 100644
--- a/src/libs/filterops.ts
+++ b/src/libs/filterops.ts
@@ -1,7 +1,7 @@
-import latest from '@maplibre/maplibre-gl-style-spec/dist/latest.json'
+import latest from "@maplibre/maplibre-gl-style-spec/dist/latest.json";
-export const combiningFilterOps = ['all', 'any', 'none'];
-export const setFilterOps = ['in', '!in'];
+export const combiningFilterOps = ["all", "any", "none"];
+export const setFilterOps = ["in", "!in"];
export const otherFilterOps = Object
.keys(latest.filter_operator.values)
.filter(op => combiningFilterOps.indexOf(op) < 0);
diff --git a/src/libs/highlight.ts b/src/libs/highlight.ts
index 511e35e6..ea5d6991 100644
--- a/src/libs/highlight.ts
+++ b/src/libs/highlight.ts
@@ -1,42 +1,42 @@
-import stylegen from '@maplibre/maplibre-gl-inspect/lib/stylegen'
-import colors from '@maplibre/maplibre-gl-inspect/lib/colors'
-import type {FilterSpecification,LayerSpecification } from 'maplibre-gl'
+import stylegen from "@maplibre/maplibre-gl-inspect/lib/stylegen";
+import colors from "@maplibre/maplibre-gl-inspect/lib/colors";
+import type {FilterSpecification,LayerSpecification } from "maplibre-gl";
export type HighlightedLayer = LayerSpecification & {filter?: FilterSpecification};
function changeLayer(l: HighlightedLayer, layer: LayerSpecification) {
- if(l.type === 'circle') {
- l.paint!['circle-radius'] = 3
- } else if(l.type === 'line') {
- l.paint!['line-width'] = 2
+ if(l.type === "circle") {
+ l.paint!["circle-radius"] = 3;
+ } else if(l.type === "line") {
+ l.paint!["line-width"] = 2;
}
if("filter" in layer) {
- l.filter = layer.filter
+ l.filter = layer.filter;
} else {
- delete l['filter']
+ delete l["filter"];
}
- l.id = l.id + '_highlight'
- return l
+ l.id = l.id + "_highlight";
+ return l;
}
export function colorHighlightedLayer(layer?: LayerSpecification): HighlightedLayer | null {
- if(!layer || layer.type === 'background' || layer.type === 'raster') return null
+ if(!layer || layer.type === "background" || layer.type === "raster") return null;
- const sourceLayerId = layer['source-layer'] || ''
+ const sourceLayerId = layer["source-layer"] || "";
const color = colors.brightColor(sourceLayerId, 1);
- if(layer.type === "fill" || layer.type === 'fill-extrusion') {
- return changeLayer(stylegen.polygonLayer(color, color, layer.source, layer['source-layer']), layer)
+ if(layer.type === "fill" || layer.type === "fill-extrusion") {
+ return changeLayer(stylegen.polygonLayer(color, color, layer.source, layer["source-layer"]), layer);
}
- if(layer.type === "symbol" || layer.type === 'circle') {
- return changeLayer(stylegen.circleLayer(color, layer.source, layer['source-layer']), layer)
+ if(layer.type === "symbol" || layer.type === "circle") {
+ return changeLayer(stylegen.circleLayer(color, layer.source, layer["source-layer"]), layer);
}
- if(layer.type === 'line') {
- return changeLayer(stylegen.lineLayer(color, layer.source, layer['source-layer']), layer)
+ if(layer.type === "line") {
+ return changeLayer(stylegen.lineLayer(color, layer.source, layer["source-layer"]), layer);
}
- return null
+ return null;
}
diff --git a/src/libs/label-from-field-name.ts b/src/libs/label-from-field-name.ts
index d6e4a064..bc991240 100644
--- a/src/libs/label-from-field-name.ts
+++ b/src/libs/label-from-field-name.ts
@@ -1,10 +1,10 @@
-import capitalize from 'lodash.capitalize'
+import capitalize from "lodash.capitalize";
export default function labelFromFieldName(fieldName: string) {
let label;
- const parts = fieldName.split('-');
+ const parts = fieldName.split("-");
if (parts.length > 1) {
- label = fieldName.split('-').slice(1).join(' ');
+ label = fieldName.split("-").slice(1).join(" ");
}
else {
label = fieldName;
diff --git a/src/libs/layer.ts b/src/libs/layer.ts
index 263f311c..f364fcad 100644
--- a/src/libs/layer.ts
+++ b/src/libs/layer.ts
@@ -1,27 +1,27 @@
-import {latest} from '@maplibre/maplibre-gl-style-spec'
-import { LayerSpecification } from 'maplibre-gl'
+import {latest} from "@maplibre/maplibre-gl-style-spec";
+import { type LayerSpecification } from "maplibre-gl";
export function changeType(layer: LayerSpecification, newType: string) {
- const changedPaintProps: LayerSpecification["paint"] = { ...layer.paint }
+ const changedPaintProps: LayerSpecification["paint"] = { ...layer.paint };
Object.keys(changedPaintProps).forEach(propertyName => {
- if(!(propertyName in latest['paint_' + newType])) {
- delete changedPaintProps[propertyName as keyof LayerSpecification["paint"]]
+ if(!(propertyName in latest["paint_" + newType])) {
+ delete changedPaintProps[propertyName as keyof LayerSpecification["paint"]];
}
- })
+ });
- const changedLayoutProps: LayerSpecification["layout"] = { ...layer.layout }
+ const changedLayoutProps: LayerSpecification["layout"] = { ...layer.layout };
Object.keys(changedLayoutProps).forEach(propertyName => {
- if(!(propertyName in latest['layout_' + newType])) {
- delete changedLayoutProps[propertyName as keyof LayerSpecification["layout"]]
+ if(!(propertyName in latest["layout_" + newType])) {
+ delete changedLayoutProps[propertyName as keyof LayerSpecification["layout"]];
}
- })
+ });
return {
...layer,
paint: changedPaintProps,
layout: changedLayoutProps,
type: newType,
- }
+ };
}
/** A {@property} in either the paint our layout {@group} has changed
@@ -61,30 +61,30 @@ export function changeProperty(layer: LayerSpecification, group: keyof LayerSpec
...layer[group] as any,
[property]: newValue
}
- }
+ };
} else {
return {
...layer,
[property]: newValue
- }
+ };
}
}
}
export function layerPrefix(name: string) {
- return name.replace(' ', '-').replace('_', '-').split('-')[0]
+ return name.replace(" ", "-").replace("_", "-").split("-")[0];
}
export function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
- const currentLayerPrefix = layerPrefix(layers[idx].id)
- let closestIdx = idx
+ const currentLayerPrefix = layerPrefix(layers[idx].id);
+ let closestIdx = idx;
for (let i = idx; i > 0; i--) {
- const previousLayerPrefix = layerPrefix(layers[i-1].id)
+ const previousLayerPrefix = layerPrefix(layers[i-1].id);
if(previousLayerPrefix === currentLayerPrefix) {
- closestIdx = i - 1
+ closestIdx = i - 1;
} else {
- return closestIdx
+ return closestIdx;
}
}
- return closestIdx
+ return closestIdx;
}
diff --git a/src/libs/layerwatcher.ts b/src/libs/layerwatcher.ts
index c0fb1f30..518411ae 100644
--- a/src/libs/layerwatcher.ts
+++ b/src/libs/layerwatcher.ts
@@ -1,11 +1,11 @@
-import throttle from 'lodash.throttle'
-import isEqual from 'lodash.isequal'
-import { Map } from 'maplibre-gl';
+import throttle from "lodash.throttle";
+import isEqual from "lodash.isequal";
+import { type Map } from "maplibre-gl";
export type LayerWatcherOptions = {
onSourcesChange?: (sources: { [sourceId: string]: string[] }) => void;
onVectorLayersChange?: (vectorLayers: { [vectorLayerId: string]: { [propertyName: string]: { [propertyValue: string]: {} } } }) => void;
-}
+};
/** Listens to map events to build up a store of available vector
* layers contained in the tiles */
@@ -17,65 +17,65 @@ export default class LayerWatcher {
_vectorLayers: { [vectorLayerId: string]: { [propertyName: string]: { [propertyValue: string]: {} } } };
constructor(opts: LayerWatcherOptions = {}) {
- this.onSourcesChange = opts.onSourcesChange || (() => {})
- this.onVectorLayersChange = opts.onVectorLayersChange || (() => {})
+ this.onSourcesChange = opts.onSourcesChange || (() => {});
+ this.onVectorLayersChange = opts.onVectorLayersChange || (() => {});
- this._sources = {}
- this._vectorLayers = {}
+ this._sources = {};
+ this._vectorLayers = {};
// Since we scan over all features we want to avoid this as much as
// possible and only do it after a batch of data has loaded because
// we only care eventuall about knowing the fields in the vector layers
- this.throttledAnalyzeVectorLayerFields = throttle(this.analyzeVectorLayerFields, 5000)
+ this.throttledAnalyzeVectorLayerFields = throttle(this.analyzeVectorLayerFields, 5000);
}
analyzeMap(map: Map) {
- const previousSources = { ...this._sources }
+ const previousSources = { ...this._sources };
Object.keys(map.style.sourceCaches).forEach(sourceId => {
//NOTE: This heavily depends on the internal API of Maplibre GL
//so this breaks between Maplibre GL JS releases
this._sources[sourceId] = map.style.sourceCaches[sourceId]._source.vectorLayerIds as string[];
- })
+ });
if(!isEqual(previousSources, this._sources)) {
- this.onSourcesChange(this._sources)
+ this.onSourcesChange(this._sources);
}
- this.throttledAnalyzeVectorLayerFields(map)
+ this.throttledAnalyzeVectorLayerFields(map);
}
analyzeVectorLayerFields(map: Map) {
- const previousVectorLayers = { ...this._vectorLayers }
+ const previousVectorLayers = { ...this._vectorLayers };
Object.keys(this._sources).forEach(sourceId => {
(this._sources[sourceId] || []).forEach(vectorLayerId => {
- const knownProperties = this._vectorLayers[vectorLayerId] || {}
- const params = { sourceLayer: vectorLayerId }
+ const knownProperties = this._vectorLayers[vectorLayerId] || {};
+ const params = { sourceLayer: vectorLayerId };
map.querySourceFeatures(sourceId, params as any).forEach(feature => {
Object.keys(feature.properties).forEach(propertyName => {
- const knownPropertyValues = knownProperties[propertyName] || {}
- knownPropertyValues[feature.properties[propertyName]] = {}
- knownProperties[propertyName] = knownPropertyValues
- })
- })
+ const knownPropertyValues = knownProperties[propertyName] || {};
+ knownPropertyValues[feature.properties[propertyName]] = {};
+ knownProperties[propertyName] = knownPropertyValues;
+ });
+ });
- this._vectorLayers[vectorLayerId] = knownProperties
- })
- })
+ this._vectorLayers[vectorLayerId] = knownProperties;
+ });
+ });
if(!isEqual(previousVectorLayers, this._vectorLayers)) {
- this.onVectorLayersChange(this._vectorLayers)
+ this.onVectorLayersChange(this._vectorLayers);
}
}
/** Access all known sources and their vector tile ids */
get sources() {
- return this._sources
+ return this._sources;
}
get vectorLayers() {
- return this._vectorLayers
+ return this._vectorLayers;
}
}
diff --git a/src/libs/maplibre-rtl.ts b/src/libs/maplibre-rtl.ts
index d1e4ca46..7c172159 100644
--- a/src/libs/maplibre-rtl.ts
+++ b/src/libs/maplibre-rtl.ts
@@ -1,3 +1,3 @@
-import MapLibreGl from "maplibre-gl"
+import MapLibreGl from "maplibre-gl";
-MapLibreGl.setRTLTextPlugin('https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js', false);
+MapLibreGl.setRTLTextPlugin("https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js", false);
diff --git a/src/libs/metadata.ts b/src/libs/metadata.ts
index dcc01243..fde41f74 100644
--- a/src/libs/metadata.ts
+++ b/src/libs/metadata.ts
@@ -1,44 +1,44 @@
-import npmurl from 'url'
+import npmurl from "url";
function loadJSON(url: string, defaultValue: any, cb: (...args: any[]) => void) {
fetch(url, {
- mode: 'cors',
+ mode: "cors",
credentials: "same-origin"
})
.then((response) => {
if (!response.ok) {
- throw new Error('Failed to load metadata for ' + url);
+ throw new Error("Failed to load metadata for " + url);
}
return response.json();
})
.then((body) => {
- cb(body)
+ cb(body);
})
.catch(() => {
- console.warn('Can not load metadata for ' + url + ', using default value ' + defaultValue);
- cb(defaultValue)
- })
+ console.warn("Can not load metadata for " + url + ", using default value " + defaultValue);
+ cb(defaultValue);
+ });
}
export function downloadGlyphsMetadata(urlTemplate: string, cb: (...args: any[]) => void) {
- if(!urlTemplate) return cb([])
+ if(!urlTemplate) return cb([]);
// Special handling because Tileserver GL serves the fontstacks metadata differently
// https://github.com/klokantech/tileserver-gl/pull/104#issuecomment-274444087
const urlObj = npmurl.parse(urlTemplate);
- const normPathPart = '/%7Bfontstack%7D/%7Brange%7D.pbf';
+ const normPathPart = "/%7Bfontstack%7D/%7Brange%7D.pbf";
if(urlObj.pathname === normPathPart) {
- urlObj.pathname = '/fontstacks.json';
+ urlObj.pathname = "/fontstacks.json";
} else {
- urlObj.pathname = urlObj.pathname!.replace(normPathPart, '.json');
+ urlObj.pathname = urlObj.pathname!.replace(normPathPart, ".json");
}
const url = npmurl.format(urlObj);
- loadJSON(url, [], cb)
+ loadJSON(url, [], cb);
}
export function downloadSpriteMetadata(baseUrl: string, cb: (...args: any[]) => void) {
- if(!baseUrl) return cb([])
- const url = baseUrl + '.json'
- loadJSON(url, {}, glyphs => cb(Object.keys(glyphs)))
+ if(!baseUrl) return cb([]);
+ const url = baseUrl + ".json";
+ loadJSON(url, {}, glyphs => cb(Object.keys(glyphs)));
}
diff --git a/src/libs/non-source-layers.ts b/src/libs/non-source-layers.ts
index fa75dcfc..13f61026 100644
--- a/src/libs/non-source-layers.ts
+++ b/src/libs/non-source-layers.ts
@@ -1 +1 @@
-export const NON_SOURCE_LAYERS = ['background', 'raster', 'hillshade', 'heatmap', 'color-relief']
+export const NON_SOURCE_LAYERS = ["background", "raster", "hillshade", "heatmap", "color-relief"];
diff --git a/src/libs/revisions.ts b/src/libs/revisions.ts
index c03b68ad..848432f2 100644
--- a/src/libs/revisions.ts
+++ b/src/libs/revisions.ts
@@ -1,4 +1,4 @@
-import { StyleSpecificationWithId } from "./definitions";
+import { type StyleSpecificationWithId } from "./definitions";
export class RevisionStore {
revisions: StyleSpecificationWithId[];
@@ -6,16 +6,16 @@ export class RevisionStore {
constructor(initialRevisions=[]) {
- this.revisions = initialRevisions
- this.currentIdx = initialRevisions.length - 1
+ this.revisions = initialRevisions;
+ this.currentIdx = initialRevisions.length - 1;
}
get latest() {
- return this.revisions[this.revisions.length - 1]
+ return this.revisions[this.revisions.length - 1];
}
get current() {
- return this.revisions[this.currentIdx]
+ return this.revisions[this.currentIdx];
}
addRevision(revision: StyleSpecificationWithId) {
@@ -23,8 +23,8 @@ export class RevisionStore {
// and ensure current index is at end of list
this.revisions = this.revisions.slice(0, this.currentIdx + 1);
- this.revisions.push(revision)
- this.currentIdx++
+ this.revisions.push(revision);
+ this.currentIdx++;
//}
}
@@ -37,7 +37,7 @@ export class RevisionStore {
redo() {
if(this.currentIdx < this.revisions.length - 1) {
- this.currentIdx++
+ this.currentIdx++;
}
return this.current;
}
diff --git a/src/libs/sort-numerically.ts b/src/libs/sort-numerically.ts
index e19261bf..f94cdc6b 100644
--- a/src/libs/sort-numerically.ts
+++ b/src/libs/sort-numerically.ts
@@ -3,10 +3,10 @@ export default function(num1: string | number, num2: string| number) {
const b = +num2;
if(a < b) {
- return -1
+ return -1;
}
else if(a > b) {
- return 1
+ return 1;
}
else {
return 0;
diff --git a/src/libs/source.ts b/src/libs/source.ts
index a9737c70..4c092d9f 100644
--- a/src/libs/source.ts
+++ b/src/libs/source.ts
@@ -2,26 +2,26 @@ import type {SourceSpecification} from "maplibre-gl";
import type {StyleSpecificationWithId} from "./definitions";
export function deleteSource(mapStyle: StyleSpecificationWithId, sourceId: string) {
- const remainingSources = { ...mapStyle.sources}
- delete remainingSources[sourceId]
+ const remainingSources = { ...mapStyle.sources};
+ delete remainingSources[sourceId];
return {
...mapStyle,
sources: remainingSources
- }
+ };
}
export function addSource(mapStyle: StyleSpecificationWithId, sourceId: string, source: SourceSpecification) {
- return changeSource(mapStyle, sourceId, source)
+ return changeSource(mapStyle, sourceId, source);
}
export function changeSource(mapStyle: StyleSpecificationWithId, sourceId: string, source: SourceSpecification) {
const changedSources = {
...mapStyle.sources,
[sourceId]: source
- }
+ };
return {
...mapStyle,
sources: changedSources
- }
+ };
}
diff --git a/src/libs/spec-helper.ts b/src/libs/spec-helper.ts
index a9f78bbf..304372cc 100644
--- a/src/libs/spec-helper.ts
+++ b/src/libs/spec-helper.ts
@@ -1,18 +1,18 @@
/**
* If we don't have a default value just make one up
*/
-export function findDefaultFromSpec(spec: { type: 'string' | 'color' | 'boolean' | 'array', default?: any }) {
- if (Object.prototype.hasOwnProperty.call(spec, 'default')) {
+export function findDefaultFromSpec(spec: { type: "string" | "color" | "boolean" | "array", default?: any }) {
+ if (Object.prototype.hasOwnProperty.call(spec, "default")) {
return spec.default;
}
const defaults = {
- 'color': '#000000',
- 'string': '',
- 'boolean': false,
- 'number': 0,
- 'array': [],
- }
+ "color": "#000000",
+ "string": "",
+ "boolean": false,
+ "number": 0,
+ "array": [],
+ };
- return defaults[spec.type] || '';
+ return defaults[spec.type] || "";
}
diff --git a/src/libs/store/apistore.ts b/src/libs/store/apistore.ts
index 5357a52b..8bd4045c 100644
--- a/src/libs/store/apistore.ts
+++ b/src/libs/store/apistore.ts
@@ -1,11 +1,11 @@
-import style from '../style'
-import {format} from '@maplibre/maplibre-gl-style-spec'
-import ReconnectingWebSocket from 'reconnecting-websocket'
-import type {IStyleStore, OnStyleChangedCallback, StyleSpecificationWithId} from '../definitions'
+import style from "../style";
+import {format} from "@maplibre/maplibre-gl-style-spec";
+import ReconnectingWebSocket from "reconnecting-websocket";
+import type {IStyleStore, OnStyleChangedCallback, StyleSpecificationWithId} from "../definitions";
export type ApiStyleStoreOptions = {
onLocalStyleChange?: OnStyleChangedCallback
-}
+};
export class ApiStyleStore implements IStyleStore {
@@ -15,51 +15,51 @@ export class ApiStyleStore implements IStyleStore {
onLocalStyleChange: OnStyleChangedCallback;
constructor(opts: ApiStyleStoreOptions) {
- this.onLocalStyleChange = opts.onLocalStyleChange || (() => {})
- const port = window.location.port
- const host = 'localhost'
- this.localUrl = `http://${host}:${port}`
- this.websocketUrl = `ws://${host}:${port}/ws`
- this.init = this.init.bind(this)
+ this.onLocalStyleChange = opts.onLocalStyleChange || (() => {});
+ const port = window.location.port;
+ const host = "localhost";
+ this.localUrl = `http://${host}:${port}`;
+ this.websocketUrl = `ws://${host}:${port}/ws`;
+ this.init = this.init.bind(this);
}
async init(): Promise {
try {
- const response = await fetch(this.localUrl + '/styles', {mode: 'cors'});
+ const response = await fetch(this.localUrl + "/styles", {mode: "cors"});
const body = await response.json();
const styleIds = body;
- this.latestStyleId = styleIds[0]
+ this.latestStyleId = styleIds[0];
this.notifyLocalChanges();
} catch {
- throw new Error('Can not connect to style API');
+ throw new Error("Can not connect to style API");
}
}
notifyLocalChanges() {
- const connection = new ReconnectingWebSocket(this.websocketUrl)
+ const connection = new ReconnectingWebSocket(this.websocketUrl);
connection.onmessage = e => {
- if(!e.data) return
- console.log('Received style update from API')
- let parsedStyle = style.emptyStyle
+ if(!e.data) return;
+ console.log("Received style update from API");
+ let parsedStyle = style.emptyStyle;
try {
- parsedStyle = JSON.parse(e.data)
+ parsedStyle = JSON.parse(e.data);
} catch(err) {
- console.error(err)
+ console.error(err);
}
- const updatedStyle = style.ensureStyleValidity(parsedStyle)
- this.onLocalStyleChange(updatedStyle)
- }
+ const updatedStyle = style.ensureStyleValidity(parsedStyle);
+ this.onLocalStyleChange(updatedStyle);
+ };
}
async getLatestStyle(): Promise {
if(this.latestStyleId) {
- const response = await fetch(this.localUrl + '/styles/' + this.latestStyleId, {
- mode: 'cors',
+ const response = await fetch(this.localUrl + "/styles/" + this.latestStyleId, {
+ mode: "cors",
});
const body = await response.json();
return style.ensureStyleValidity(body);
} else {
- throw new Error('No latest style available. You need to init the api backend first.')
+ throw new Error("No latest style available. You need to init the api backend first.");
}
}
@@ -71,18 +71,18 @@ export class ApiStyleStore implements IStyleStore {
)
);
- const id = mapStyle.id
- fetch(this.localUrl + '/styles/' + id, {
+ const id = mapStyle.id;
+ fetch(this.localUrl + "/styles/" + id, {
method: "PUT",
- mode: 'cors',
+ mode: "cors",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: styleJSON
})
.catch(function(error) {
- if(error) console.error(error)
- })
- return mapStyle
+ if(error) console.error(error);
+ });
+ return mapStyle;
}
}
diff --git a/src/libs/store/style-store-factory.ts b/src/libs/store/style-store-factory.ts
index f20657d7..ee9c0811 100644
--- a/src/libs/store/style-store-factory.ts
+++ b/src/libs/store/style-store-factory.ts
@@ -1,5 +1,5 @@
///
-import { IStyleStore, OnStyleChangedCallback } from "../definitions";
+import { type IStyleStore, type OnStyleChangedCallback } from "../definitions";
import { getStyleUrlFromAddressbarAndRemoveItIfNeeded, loadStyleUrl } from "../urlopen";
import { ApiStyleStore } from "./apistore";
import { StyleStore } from "./stylestore";
@@ -8,7 +8,7 @@ export async function createStyleStore(onStyleChanged: OnStyleChangedCallback):
const styleUrl = getStyleUrlFromAddressbarAndRemoveItIfNeeded();
const useStyleUrl = styleUrl && window.confirm("Load style from URL: " + styleUrl + " and discard current changes?");
let styleStore: IStyleStore;
- if (import.meta.env.MODE === 'desktop' && !useStyleUrl) {
+ if (import.meta.env.MODE === "desktop" && !useStyleUrl) {
const apiStyleStore = new ApiStyleStore({
onLocalStyleChange: mapStyle => onStyleChanged(mapStyle, {save: false}),
});
diff --git a/src/libs/store/stylestore.ts b/src/libs/store/stylestore.ts
index 49f5e469..b7629803 100644
--- a/src/libs/store/stylestore.ts
+++ b/src/libs/store/stylestore.ts
@@ -1,16 +1,16 @@
-import style from '../style'
-import {loadStyleUrl} from '../urlopen'
-import publicSources from '../../config/styles.json'
-import type {IStyleStore, StyleSpecificationWithId} from '../definitions'
+import style from "../style";
+import {loadStyleUrl} from "../urlopen";
+import publicSources from "../../config/styles.json";
+import type {IStyleStore, StyleSpecificationWithId} from "../definitions";
-const storagePrefix = "maputnik"
-const stylePrefix = 'style'
+const storagePrefix = "maputnik";
+const stylePrefix = "style";
const storageKeys = {
- latest: [storagePrefix, 'latest_style'].join(':'),
- accessToken: [storagePrefix, 'access_token'].join(':')
-}
+ latest: [storagePrefix, "latest_style"].join(":"),
+ accessToken: [storagePrefix, "access_token"].join(":")
+};
-const defaultStyleUrl = publicSources[0].url
+const defaultStyleUrl = publicSources[0].url;
// Fetch a default style via URL and return it or a fallback style via callback
export function loadDefaultStyle(): Promise {
@@ -19,35 +19,35 @@ export function loadDefaultStyle(): Promise {
// Return style ids and dates of all styles stored in local storage
function loadStoredStyles() {
- const styles = []
+ const styles = [];
for (let i = 0; i < window.localStorage.length; i++) {
- const key = window.localStorage.key(i)
+ const key = window.localStorage.key(i);
if(isStyleKey(key!)) {
- styles.push(fromKey(key!))
+ styles.push(fromKey(key!));
}
}
- return styles
+ return styles;
}
function isStyleKey(key: string) {
- const parts = key.split(":")
- return parts.length === 3 && parts[0] === storagePrefix && parts[1] === stylePrefix
+ const parts = key.split(":");
+ return parts.length === 3 && parts[0] === storagePrefix && parts[1] === stylePrefix;
}
// Load style id from key
function fromKey(key: string) {
if(!isStyleKey(key)) {
- throw "Key is not a valid style key"
+ throw "Key is not a valid style key";
}
- const parts = key.split(":")
- const styleId = parts[2]
- return styleId
+ const parts = key.split(":");
+ const styleId = parts[2];
+ return styleId;
}
// Calculate key that identifies the style with a version
function styleKey(styleId: string) {
- return [storagePrefix, stylePrefix, styleId].join(":")
+ return [storagePrefix, stylePrefix, styleId].join(":");
}
// Manages many possible styles that are stored in the local storage
@@ -68,7 +68,7 @@ export class StyleStore implements IStyleStore {
for (let i = 0; i < window.localStorage.length; i++) {
const key = window.localStorage.key(i) as string;
if(key.startsWith(storagePrefix)) {
- window.localStorage.removeItem(key)
+ window.localStorage.removeItem(key);
}
}
}
@@ -79,7 +79,7 @@ export class StyleStore implements IStyleStore {
return loadDefaultStyle();
}
const styleId = window.localStorage.getItem(storageKeys.latest) as string;
- const styleItem = window.localStorage.getItem(styleKey(styleId))
+ const styleItem = window.localStorage.getItem(styleKey(styleId));
if (styleItem) {
return JSON.parse(styleItem) as StyleSpecificationWithId;
@@ -89,30 +89,30 @@ export class StyleStore implements IStyleStore {
// Save current style replacing previous version
save(mapStyle: StyleSpecificationWithId) {
- mapStyle = style.ensureStyleValidity(mapStyle)
- const key = styleKey(mapStyle.id)
+ mapStyle = style.ensureStyleValidity(mapStyle);
+ const key = styleKey(mapStyle.id);
const saveFn = () => {
- window.localStorage.setItem(key, JSON.stringify(mapStyle))
- window.localStorage.setItem(storageKeys.latest, mapStyle.id)
- }
+ window.localStorage.setItem(key, JSON.stringify(mapStyle));
+ window.localStorage.setItem(storageKeys.latest, mapStyle.id);
+ };
try {
- saveFn()
+ saveFn();
} catch (e) {
// Handle quota exceeded error
if (e instanceof DOMException && (
e.code === 22 || // Firefox
e.code === 1014 || // Firefox
- e.name === 'QuotaExceededError' ||
- e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
+ e.name === "QuotaExceededError" ||
+ e.name === "NS_ERROR_DOM_QUOTA_REACHED"
)) {
- this.purge()
- saveFn() // Retry after clearing
+ this.purge();
+ saveFn(); // Retry after clearing
} else {
- throw e
+ throw e;
}
}
- return mapStyle
+ return mapStyle;
}
}
diff --git a/src/libs/style.ts b/src/libs/style.ts
index 31f8cf52..dcb7f25e 100644
--- a/src/libs/style.ts
+++ b/src/libs/style.ts
@@ -1,21 +1,21 @@
-import {derefLayers} from '@maplibre/maplibre-gl-style-spec'
-import type {StyleSpecification, LayerSpecification} from 'maplibre-gl'
-import tokens from '../config/tokens.json'
-import type {StyleSpecificationWithId} from './definitions'
+import {derefLayers} from "@maplibre/maplibre-gl-style-spec";
+import type {StyleSpecification, LayerSpecification} from "maplibre-gl";
+import tokens from "../config/tokens.json";
+import type {StyleSpecificationWithId} from "./definitions";
// Empty style is always used if no style could be restored or fetched
const emptyStyle = ensureStyleValidity({
version: 8,
sources: {},
layers: [],
-})
+});
function generateId() {
- return Math.random().toString(36).substring(2, 9)
+ return Math.random().toString(36).substring(2, 9);
}
function ensureHasId(style: StyleSpecification & { id?: string }): StyleSpecificationWithId {
- if(!('id' in style) || !style.id) {
+ if(!("id" in style) || !style.id) {
style.id = generateId();
}
return style as StyleSpecificationWithId;
@@ -23,81 +23,81 @@ function ensureHasId(style: StyleSpecification & { id?: string }): StyleSpecific
function ensureHasNoInteractive(style: StyleSpecificationWithId) {
const changedLayers = style.layers.map(layer => {
- const changedLayer: LayerSpecification & { interactive?: any } = { ...layer }
- delete changedLayer.interactive
- return changedLayer
- })
+ const changedLayer: LayerSpecification & { interactive?: any } = { ...layer };
+ delete changedLayer.interactive;
+ return changedLayer;
+ });
return {
...style,
layers: changedLayers
- }
+ };
}
function ensureHasNoRefs(style: StyleSpecificationWithId) {
return {
...style,
layers: derefLayers(style.layers)
- }
+ };
}
function ensureStyleValidity(style: StyleSpecification): StyleSpecificationWithId {
- return ensureHasNoInteractive(ensureHasNoRefs(ensureHasId(style)))
+ return ensureHasNoInteractive(ensureHasNoRefs(ensureHasId(style)));
}
function indexOfLayer(layers: LayerSpecification[], layerId: string) {
for (let i = 0; i < layers.length; i++) {
if(layers[i].id === layerId) {
- return i
+ return i;
}
}
- return null
+ return null;
}
function getAccessToken(sourceName: string, mapStyle: StyleSpecification, opts: {allowFallback?: boolean}) {
const metadata = mapStyle.metadata || {} as any;
- let accessToken = metadata[`maputnik:${sourceName}_access_token`]
+ let accessToken = metadata[`maputnik:${sourceName}_access_token`];
if(opts.allowFallback && !accessToken) {
- accessToken = tokens[sourceName as keyof typeof tokens]
+ accessToken = tokens[sourceName as keyof typeof tokens];
}
return accessToken;
}
function replaceSourceAccessToken(mapStyle: StyleSpecification, sourceName: string, opts={}) {
- const source = mapStyle.sources[sourceName]
- if(!source) return mapStyle
- if(!("url" in source) || !source.url) return mapStyle
+ const source = mapStyle.sources[sourceName];
+ if(!source) return mapStyle;
+ if(!("url" in source) || !source.url) return mapStyle;
- let authSourceName = sourceName
+ let authSourceName = sourceName;
if(sourceName === "thunderforest_transport" || sourceName === "thunderforest_outdoors") {
- authSourceName = "thunderforest"
+ 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"
+ authSourceName = "stadia";
}
else if (("url" in source) && source.url?.match(/\.locationiq\.com/)) {
- authSourceName = "locationiq"
+ authSourceName = "locationiq";
}
- const accessToken = getAccessToken(authSourceName, mapStyle, opts)
+ const accessToken = getAccessToken(authSourceName, mapStyle, opts);
if(!accessToken) {
// Early exit.
return mapStyle;
}
- let sourceUrl: string
+ 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}`
+ sourceUrl = `${source.url}?api_key=${accessToken}`;
} else {
- sourceUrl = source.url.replace('{key}', accessToken)
+ sourceUrl = source.url.replace("{key}", accessToken);
}
const changedSources = {
@@ -106,42 +106,42 @@ function replaceSourceAccessToken(mapStyle: StyleSpecification, sourceName: stri
...source,
url: sourceUrl
}
- }
+ };
const changedStyle = {
...mapStyle,
sources: changedSources
- }
- return changedStyle
+ };
+ return changedStyle;
}
function replaceAccessTokens(mapStyle: StyleSpecification, opts={}) {
- let changedStyle = mapStyle
+ let changedStyle = mapStyle;
Object.keys(mapStyle.sources).forEach((sourceName) => {
changedStyle = replaceSourceAccessToken(changedStyle, sourceName, opts);
- })
+ });
if (mapStyle.glyphs && (mapStyle.glyphs.match(/\.tilehosting\.com/) || mapStyle.glyphs.match(/\.maptiler\.com/))) {
const newAccessToken = getAccessToken("openmaptiles", mapStyle, opts);
if (newAccessToken) {
changedStyle = {
...changedStyle,
- glyphs: mapStyle.glyphs.replace('{key}', newAccessToken)
- }
+ glyphs: mapStyle.glyphs.replace("{key}", newAccessToken)
+ };
}
}
- return changedStyle
+ return changedStyle;
}
function stripAccessTokens(mapStyle: StyleSpecification) {
const changedMetadata = {
...mapStyle.metadata as any
};
- delete changedMetadata['maputnik:openmaptiles_access_token'];
- delete changedMetadata['maputnik:thunderforest_access_token'];
- delete changedMetadata['maputnik:stadia_access_token'];
- delete changedMetadata['maputnik:locationiq_access_token'];
+ delete changedMetadata["maputnik:openmaptiles_access_token"];
+ delete changedMetadata["maputnik:thunderforest_access_token"];
+ delete changedMetadata["maputnik:stadia_access_token"];
+ delete changedMetadata["maputnik:locationiq_access_token"];
return {
...mapStyle,
metadata: changedMetadata
@@ -156,4 +156,4 @@ export default {
getAccessToken,
replaceAccessTokens,
stripAccessTokens,
-}
+};
diff --git a/src/libs/urlopen.ts b/src/libs/urlopen.ts
index b7426227..a793f081 100644
--- a/src/libs/urlopen.ts
+++ b/src/libs/urlopen.ts
@@ -1,27 +1,27 @@
-import style from './style'
-import { StyleSpecificationWithId } from './definitions';
+import style from "./style";
+import { type StyleSpecificationWithId } from "./definitions";
export function getStyleUrlFromAddressbarAndRemoveItIfNeeded(): string | null {
const initialUrl = new URL(window.location.href);
- const styleUrl = initialUrl.searchParams.get('style');
+ const styleUrl = initialUrl.searchParams.get("style");
if (styleUrl) {
- initialUrl.searchParams.delete('style');
- window.history.replaceState({}, document.title, initialUrl.toString())
+ initialUrl.searchParams.delete("style");
+ window.history.replaceState({}, document.title, initialUrl.toString());
}
return styleUrl;
}
export async function loadStyleUrl(styleUrl: string): Promise {
- console.log('Loading style', styleUrl)
+ console.log("Loading style", styleUrl);
try {
const response = await fetch(styleUrl, {
- mode: 'cors',
+ mode: "cors",
credentials: "same-origin"
});
const body = await response.json();
return style.ensureStyleValidity(body);
} catch {
- console.warn('Could not fetch default style: ' + styleUrl)
- return style.emptyStyle
+ console.warn("Could not fetch default style: " + styleUrl);
+ return style.emptyStyle;
}
}
diff --git a/src/libs/zoomcontrol.ts b/src/libs/zoomcontrol.ts
index 94c7795e..ee4749c6 100644
--- a/src/libs/zoomcontrol.ts
+++ b/src/libs/zoomcontrol.ts
@@ -1,4 +1,4 @@
-import {Map} from 'maplibre-gl';
+import {type Map} from "maplibre-gl";
export default class ZoomControl {
_map: Map| undefined = undefined;
@@ -9,8 +9,8 @@ export default class ZoomControl {
onAdd(map: Map) {
this._map = map;
- this._container = document.createElement('div');
- this._container.className = 'maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-zoom';
+ 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.setLabel("Zoom:");
this.addEventListeners();
@@ -31,9 +31,9 @@ export default class ZoomControl {
}
addEventListeners (){
- this._map!.on('render', () => this.updateZoomLevel());
- this._map!.on('zoomIn', () => this.updateZoomLevel());
- this._map!.on('zoomOut', () => this.updateZoomLevel());
+ this._map!.on("render", () => this.updateZoomLevel());
+ this._map!.on("zoomIn", () => this.updateZoomLevel());
+ this._map!.on("zoomOut", () => this.updateZoomLevel());
}
onRemove() {