diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f76160..0494d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ The format is based on Keep a Changelog and the project follows Semantic Version ### Changed +- Upgrade the location map to MapLibre GL JS 6 while keeping its worker bundled + locally for Chromium and Firefox extension pages. Maps now require WebGL2. + - The interface language can be chosen in Settings. Automatic still follows the browser language. Popup, sidebar, and Settings update without a reload. - Language choices show the English name and the name from the active translation. diff --git a/package.json b/package.json index 47af874..15e3722 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "maplibre-gl": "^5.24.0", + "maplibre-gl": "^6.4.1", "react": "^19.2.7", "react-dom": "^19.2.7", "sonner": "^2.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c3ef09..7e322fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -85,8 +85,8 @@ importers: specifier: ^1.1.1 version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) maplibre-gl: - specifier: ^5.24.0 - version: 5.24.0 + specifier: ^6.4.1 + version: 6.4.1 react: specifier: 19.2.7 version: 19.2.7 @@ -873,41 +873,34 @@ packages: '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} - '@mapbox/jsonlint-lines-primitives@2.0.2': - resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} - engines: {node: '>= 0.6'} + '@mapbox/jsonlint-lines-primitives@2.0.3': + resolution: {integrity: sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==} + engines: {node: '>= 22'} '@mapbox/point-geometry@1.1.0': resolution: {integrity: sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==} - '@mapbox/tiny-sdf@2.1.0': - resolution: {integrity: sha512-uFJhNh36BR4OCuWIEiWaEix9CA2WzT6CAIcqVjWYpnx8+QDtS+oC4QehRrx5cX4mgWs37MmKnwUejeHxVymzNg==} + '@mapbox/tiny-sdf@2.2.0': + resolution: {integrity: sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==} - '@mapbox/unitbezier@0.0.1': - resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} + '@mapbox/unitbezier@1.0.0': + resolution: {integrity: sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==} - '@mapbox/vector-tile@2.0.4': - resolution: {integrity: sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==} + '@mapbox/vector-tile@3.0.0': + resolution: {integrity: sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==} - '@mapbox/whoots-js@3.1.0': - resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} - engines: {node: '>=6.0.0'} - - '@maplibre/geojson-vt@5.0.4': - resolution: {integrity: sha512-KGg9sma45S+stfH9vPCJk1J0lSDLWZgCT9Y8u8qWZJyjFlP8MNP1WGTxIMYJZjDvVT3PDn05kN1C95Sut1HpgQ==} + '@maplibre/geojson-vt@6.1.1': + resolution: {integrity: sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==} - '@maplibre/geojson-vt@6.1.0': - resolution: {integrity: sha512-2eIY4gZxeKIVOZVNkAMb+5NgXhgsMQpOveTQAvnp53LYqHGJZDidk7Ew0Tged9PThidpbS+NFTh0g4zivhPDzQ==} - - '@maplibre/maplibre-gl-style-spec@24.8.1': - resolution: {integrity: sha512-zxa92qF96ZNojLxeAjnaRpjVCy+swoUNJvDhtpC90k7u5F0TMr4GmvNqMKvYrMoPB8d7gRSXbMG1hBbmgESIsw==} + '@maplibre/maplibre-gl-style-spec@26.4.4': + resolution: {integrity: sha512-hG4RZR4PBd/+6A3ODdZ3AnQRF106ZQk1y3bhwDg8bH/A4Oz2tnRUJVVWs9BZa6gXZ1d3UKe89C+Mm+olGBELvA==} hasBin: true - '@maplibre/mlt@1.1.8': - resolution: {integrity: sha512-8vtfYGidr1rNkv5IwIoU2lfe3Oy+Wa8HluzQYcQi9cveU9K3pweAal/poQj4GJ0K/EW4bTQp2wVAs09g2yDRZg==} + '@maplibre/mlt@1.3.0': + resolution: {integrity: sha512-7M2O7ABM80Oi8XPkfkrjKB8mOBIxGoVgkA52Mu4RMWoBvvMdagQ522+WxVYujZsMpqIr3BpzrTbXrm4k8lCzCQ==} - '@maplibre/vt-pbf@4.3.0': - resolution: {integrity: sha512-jIvp8F5hQCcreqOOpEt42TJMUlsrEcpf/kI1T2v85YrQRV6PPXUcEXUg5karKtH6oh47XJZ4kHu56pUkOuqA7w==} + '@maplibre/vt-pbf@4.3.2': + resolution: {integrity: sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==} '@mdn/browser-compat-data@8.1.0': resolution: {integrity: sha512-BNlUjp+9O6gtIHPVZEGFb5rgtuWW8weR+mSKfLOevxbfoZv5DRe3N4ZTEpXiIm5wfR7+kqHu8malCCgP6USrlg==} @@ -1965,9 +1958,6 @@ packages: '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - '@types/supercluster@7.1.3': - resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} - '@typescript-eslint/eslint-plugin@8.70.1': resolution: {integrity: sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2802,8 +2792,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - earcut@3.0.2: - resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} + earcut@3.2.4: + resolution: {integrity: sha512-FHc6yNpnTORB0tM5kmZ03iD2mDuNakDE2lvf4Hw1XkfxtEHIGVi01B/GqUSwx+NcC1WGjidAfpTXzeALtPtfpg==} ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -3618,8 +3608,8 @@ packages: jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} - kdbush@4.0.2: - resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + kdbush@4.1.0: + resolution: {integrity: sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==} keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -3810,8 +3800,8 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - maplibre-gl@5.24.0: - resolution: {integrity: sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==} + maplibre-gl@6.4.1: + resolution: {integrity: sha512-KzxQKtfBu/pSz1C+yW1hNS9eyj2h2lC7ufdAi6/SEt177n3oAfDfmUmslRfJdXY7ReAFBcnvwsqmiyoDhtA9GQ==} engines: {node: '>=16.14.0', npm: '>=8.1.0'} marky@1.3.0: @@ -4041,8 +4031,8 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pbf@4.0.1: - resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} + pbf@5.1.2: + resolution: {integrity: sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==} hasBin: true pend@1.2.0: @@ -4378,9 +4368,6 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rw@1.3.3: - resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - safe-array-concat@1.1.3: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} @@ -4644,9 +4631,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - supercluster@8.0.1: - resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -5649,51 +5633,42 @@ snapshots: '@keyv/serialize@1.1.1': {} - '@mapbox/jsonlint-lines-primitives@2.0.2': {} + '@mapbox/jsonlint-lines-primitives@2.0.3': {} '@mapbox/point-geometry@1.1.0': {} - '@mapbox/tiny-sdf@2.1.0': {} + '@mapbox/tiny-sdf@2.2.0': {} - '@mapbox/unitbezier@0.0.1': {} + '@mapbox/unitbezier@1.0.0': {} - '@mapbox/vector-tile@2.0.4': + '@mapbox/vector-tile@3.0.0': dependencies: '@mapbox/point-geometry': 1.1.0 '@types/geojson': 7946.0.16 - pbf: 4.0.1 - - '@mapbox/whoots-js@3.1.0': {} + pbf: 5.1.2 - '@maplibre/geojson-vt@5.0.4': {} - - '@maplibre/geojson-vt@6.1.0': + '@maplibre/geojson-vt@6.1.1': dependencies: - kdbush: 4.0.2 + kdbush: 4.1.0 - '@maplibre/maplibre-gl-style-spec@24.8.1': + '@maplibre/maplibre-gl-style-spec@26.4.4': dependencies: - '@mapbox/jsonlint-lines-primitives': 2.0.2 - '@mapbox/unitbezier': 0.0.1 + '@mapbox/jsonlint-lines-primitives': 2.0.3 + '@mapbox/unitbezier': 1.0.0 json-stringify-pretty-compact: 4.0.0 minimist: 1.2.8 quickselect: 3.0.0 - rw: 1.3.3 tinyqueue: 3.0.0 - '@maplibre/mlt@1.1.8': + '@maplibre/mlt@1.3.0': dependencies: '@mapbox/point-geometry': 1.1.0 - '@maplibre/vt-pbf@4.3.0': + '@maplibre/vt-pbf@4.3.2': dependencies: '@mapbox/point-geometry': 1.1.0 - '@mapbox/vector-tile': 2.0.4 - '@maplibre/geojson-vt': 5.0.4 '@types/geojson': 7946.0.16 - '@types/supercluster': 7.1.3 - pbf: 4.0.1 - supercluster: 8.0.1 + pbf: 5.1.2 '@mdn/browser-compat-data@8.1.0': {} @@ -6610,10 +6585,6 @@ snapshots: '@types/resolve@1.20.6': {} - '@types/supercluster@7.1.3': - dependencies: - '@types/geojson': 7946.0.16 - '@typescript-eslint/eslint-plugin@8.70.1(@typescript-eslint/parser@8.70.1(eslint@10.11.0(jiti@1.21.7))(typescript@6.0.3))(eslint@10.11.0(jiti@1.21.7))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -7500,7 +7471,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - earcut@3.0.2: {} + earcut@3.2.4: {} ecdsa-sig-formatter@1.0.11: dependencies: @@ -8501,7 +8472,7 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 - kdbush@4.0.2: {} + kdbush@4.1.0: {} keyv@4.5.4: dependencies: @@ -8658,24 +8629,22 @@ snapshots: make-error@1.3.6: {} - maplibre-gl@5.24.0: + maplibre-gl@6.4.1: dependencies: - '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/point-geometry': 1.1.0 - '@mapbox/tiny-sdf': 2.1.0 - '@mapbox/unitbezier': 0.0.1 - '@mapbox/vector-tile': 2.0.4 - '@mapbox/whoots-js': 3.1.0 - '@maplibre/geojson-vt': 6.1.0 - '@maplibre/maplibre-gl-style-spec': 24.8.1 - '@maplibre/mlt': 1.1.8 - '@maplibre/vt-pbf': 4.3.0 + '@mapbox/tiny-sdf': 2.2.0 + '@mapbox/unitbezier': 1.0.0 + '@mapbox/vector-tile': 3.0.0 + '@maplibre/geojson-vt': 6.1.1 + '@maplibre/maplibre-gl-style-spec': 26.4.4 + '@maplibre/mlt': 1.3.0 + '@maplibre/vt-pbf': 4.3.2 '@types/geojson': 7946.0.16 - earcut: 3.0.2 + earcut: 3.2.4 gl-matrix: 3.4.4 - kdbush: 4.0.2 + kdbush: 4.1.0 murmurhash-js: 1.0.0 - pbf: 4.0.1 + pbf: 5.1.2 potpack: 2.1.0 quickselect: 3.0.0 tinyqueue: 3.0.0 @@ -8958,7 +8927,7 @@ snapshots: pathval@2.0.1: {} - pbf@4.0.1: + pbf@5.1.2: dependencies: resolve-protobuf-schema: 2.1.0 @@ -9312,8 +9281,6 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rw@1.3.3: {} - safe-array-concat@1.1.3: dependencies: call-bind: 1.0.9 @@ -9623,10 +9590,6 @@ snapshots: tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 - supercluster@8.0.1: - dependencies: - kdbush: 4.0.2 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 diff --git a/src/ui/options/components/map/ProfileDraftMap.tsx b/src/ui/options/components/map/ProfileDraftMap.tsx index b972ef3..972e443 100644 --- a/src/ui/options/components/map/ProfileDraftMap.tsx +++ b/src/ui/options/components/map/ProfileDraftMap.tsx @@ -1,6 +1,6 @@ import "maplibre-gl/dist/maplibre-gl.css"; -import type maplibreglType from "maplibre-gl"; +import type * as maplibreglType from "maplibre-gl"; import type { AddLayerObject, GeoJSONSource } from "maplibre-gl"; import type { MutableRefObject, ReactNode } from "react"; import { useEffect, useRef } from "react"; diff --git a/src/ui/options/components/map/maplibre-csp.test.ts b/src/ui/options/components/map/maplibre-csp.test.ts index efcb6b5..e8cedd9 100644 --- a/src/ui/options/components/map/maplibre-csp.test.ts +++ b/src/ui/options/components/map/maplibre-csp.test.ts @@ -4,14 +4,12 @@ const { setWorkerUrl } = vi.hoisted(() => ({ setWorkerUrl: vi.fn(), })); -vi.mock("maplibre-gl/dist/maplibre-gl-csp.js", () => ({ - default: { - setWorkerUrl, - }, +vi.mock("maplibre-gl", () => ({ + setWorkerUrl, })); -vi.mock("maplibre-gl/dist/maplibre-gl-csp-worker.js?url", () => ({ - default: "/assets/maplibre-gl-csp-worker.js", +vi.mock("maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url", () => ({ + default: "/assets/maplibre-gl-worker.js", })); describe("maplibre-csp", () => { @@ -21,17 +19,17 @@ describe("maplibre-csp", () => { vi.unstubAllGlobals(); }); - it("configures the CSP worker against the current extension page origin", async () => { - vi.stubGlobal( - "location", - new URL("chrome-extension://test/src/ui/options/index.html"), - ); + it.each(["chrome-extension://test", "moz-extension://test"])( + "configures the bundled worker against the %s page origin", + async (origin) => { + vi.stubGlobal("location", new URL(`${origin}/src/ui/options/index.html`)); - const module = await import("@/ui/options/components/map/maplibre-csp"); + const module = await import("@/ui/options/components/map/maplibre-csp"); - expect(setWorkerUrl).toHaveBeenCalledWith( - "chrome-extension://test/assets/maplibre-gl-csp-worker.js", - ); - expect(module.default).toHaveProperty("setWorkerUrl", setWorkerUrl); - }); + expect(setWorkerUrl).toHaveBeenCalledWith( + `${origin}/assets/maplibre-gl-worker.js`, + ); + expect(module.default).toHaveProperty("setWorkerUrl", setWorkerUrl); + }, + ); }); diff --git a/src/ui/options/components/map/maplibre-csp.ts b/src/ui/options/components/map/maplibre-csp.ts index 413f73b..61fa87c 100644 --- a/src/ui/options/components/map/maplibre-csp.ts +++ b/src/ui/options/components/map/maplibre-csp.ts @@ -1,8 +1,6 @@ -import type maplibreglType from "maplibre-gl"; -import maplibreWorkerUrl from "maplibre-gl/dist/maplibre-gl-csp-worker.js?url"; -import maplibreglRuntime from "maplibre-gl/dist/maplibre-gl-csp.js"; - -const maplibregl = maplibreglRuntime as typeof maplibreglType; +import * as maplibregl from "maplibre-gl"; +// Bundle the worker's shared ESM imports too; a plain ?url would leave them missing. +import maplibreWorkerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url"; const resolvedWorkerUrl = typeof globalThis.location?.href === "string" diff --git a/src/ui/options/components/map/maplibre-gl-csp.d.ts b/src/ui/options/components/map/maplibre-gl-csp.d.ts deleted file mode 100644 index 69d8c9e..0000000 --- a/src/ui/options/components/map/maplibre-gl-csp.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -declare module "maplibre-gl/dist/maplibre-gl-csp.js" { - import type maplibregl from "maplibre-gl"; - - const runtime: typeof maplibregl; - export default runtime; -} - -declare module "maplibre-gl/dist/maplibre-gl-csp-worker.js?url" { - const workerUrl: string; - export default workerUrl; -} diff --git a/src/ui/options/components/map/profile-map-marker.ts b/src/ui/options/components/map/profile-map-marker.ts index 30621c2..dc3263f 100644 --- a/src/ui/options/components/map/profile-map-marker.ts +++ b/src/ui/options/components/map/profile-map-marker.ts @@ -1,4 +1,4 @@ -import type maplibreglType from "maplibre-gl"; +import type * as maplibreglType from "maplibre-gl"; import type { MapMouseEvent } from "maplibre-gl"; import type { MutableRefObject } from "react";