mirror of
https://github.com/maputnik/editor.git
synced 2026-03-13 13:50:02 +00:00
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. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/microsoft/TypeScript/releases">typescript's releases</a>.</em></p> <blockquote> <h2>TypeScript 5.9</h2> <p>Release notes pending.</p> <!-- raw HTML omitted --> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed issues query for Typescript 5.9.1 (RC)</a>.</li> <li>[[No specific changes for TypeScript 5.9.2 (Stable)]]</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 5.9 RC</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9-rc/">release announcement</a></p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed issues query for Typescript 5.9.1 (RC)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 5.9 Beta</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9-beta/">release announcement</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="be86783155"><code>be86783</code></a> Give more specific errors for <code>verbatimModuleSyntax</code> (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62113">#62113</a>)</li> <li><a href="22ef57786f"><code>22ef577</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250714...</li> <li><a href="d5a414cd1d"><code>d5a414c</code></a> Don't use <code>noErrorTruncation</code> when printing types with <code>maximumLength</code> set (#...</li> <li><a href="f14b5c8a2f"><code>f14b5c8</code></a> Remove unused and confusing dom.iterable.d.ts file (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62037">#62037</a>)</li> <li><a href="2778e84ed8"><code>2778e84</code></a> Restore AbortSignal.abort (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62086">#62086</a>)</li> <li><a href="65cb4bd2d5"><code>65cb4bd</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250710...</li> <li><a href="9e20e032ef"><code>9e20e03</code></a> Clear out checker-level stacks on pop (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62016">#62016</a>)</li> <li><a href="87740bc7fe"><code>87740bc</code></a> Fix for Issue 61081 (<a href="https://redirect.github.com/microsoft/TypeScript/issues/61221">#61221</a>)</li> <li><a href="833a8d492c"><code>833a8d4</code></a> Fix Symbol completion priority and cursor positioning (<a href="https://redirect.github.com/microsoft/TypeScript/issues/61945">#61945</a>)</li> <li><a href="0018c9ff12"><code>0018c9f</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250702...</li> <li>Additional commits viewable in <a href="https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2">compare view</a></li> </ul> </details> <br /> [](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) --- <details> <summary>Dependabot commands and options</summary> <br /> 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 <dependency name> 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) </details> > **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Harel M <harel.mazor@gmail.com>
This commit is contained in:
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
2
src/libs/definitions.d.ts
vendored
2
src/libs/definitions.d.ts
vendored
@@ -6,7 +6,7 @@ export type OnStyleChangedOpts = {
|
||||
save?: boolean;
|
||||
addRevision?: boolean;
|
||||
initialLoad?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export type OnStyleChangedCallback = (newStyle: StyleSpecificationWithId, opts: OnStyleChangedOpts={}) => void;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const NON_SOURCE_LAYERS = ['background', 'raster', 'hillshade', 'heatmap', 'color-relief']
|
||||
export const NON_SOURCE_LAYERS = ["background", "raster", "hillshade", "heatmap", "color-relief"];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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] || "";
|
||||
}
|
||||
|
||||
@@ -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<void> {
|
||||
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<StyleSpecificationWithId> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// <reference types="vite/client" />
|
||||
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}),
|
||||
});
|
||||
|
||||
@@ -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<StyleSpecificationWithId> {
|
||||
@@ -19,35 +19,35 @@ export function loadDefaultStyle(): Promise<StyleSpecificationWithId> {
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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<StyleSpecificationWithId> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user