@geolibre/core 3.4.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +353 -152
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +132 -1102
- package/dist/index.mjs.map +1 -1
- package/dist/{project-diff-Bua7fBME.mjs → project-diff-CSG1AgSK.mjs} +2341 -68
- package/dist/project-diff-CSG1AgSK.mjs.map +1 -0
- package/dist/{project-diff-BD23T4xv.d.mts → project-diff-aMF0z5Bo.d.mts} +156 -41
- package/dist/project-diff-aMF0z5Bo.d.mts.map +1 -0
- package/dist/worker-safe.d.mts +2 -2
- package/dist/worker-safe.mjs +1 -2
- package/package.json +4 -4
- package/dist/project-diff-BD23T4xv.d.mts.map +0 -1
- package/dist/project-diff-Bua7fBME.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as GEOCODING_PROVIDERS, $i as getPlanetaryBasemapById, $n as groupMemberIndices, $r as getBuildEnvironment, $t as CESIUM_BING_AERIAL_ASSET_ID, A as normalizeSecondaryMapViews, Aa as styleValue, Ai as sameCesiumImagery, An as createStyleLibraryEntryId, Ar as isValidMetadataDate, At as selectedGeocodingLocator, B as storyMapHasContent, Bi as ELLIPSOIDS, Bn as normalizePrintLayoutConfig, Br as evaluateMapExpression, Bt as PROJECT_CREDENTIAL_FIELDS, C as normalizeModelGraph, Ca as OPENFREEMAP_BASEMAPS, Ci as parseMapCrsEpsgCode, Cn as isGeoArrowBatch, Cr as reapplyLayerJoins, Ct as normalizeArcGISLocatorUrl, D as normalizeProcessingHistory, Da as detectNonGeographicCoordinates, Di as availableCesiumBasemap, Dn as STYLE_LIBRARY_BUNDLE_TYPE, Dr as STAC_PROCESSING_EXTENSION, Dt as parseArcGISSuggestions, E as normalizePrimaryRenderer, Ea as SQL_QUERY_SOURCE_KIND, Ei as CESIUM_BASEMAPS, En as RAMP_STYLE_KEYS, Er as stripVirtualFieldColumns, Et as parseArcGISLocatorInfo, F as projectFromStore, Fi as getRegionalBasemapById, Fn as sanitizeLayerStylePatch, Fr as parseMetadataKeywords, Ft as DEFAULT_STORY_CHAPTER_DURATION_SECONDS, G as DEFAULT_REVERSE_GEOCODE_ENDPOINT, Gi as bodyLengthToEarth, Gn as scrubCommentsForRemovedLayers, Gr as removeTrailingJsonCommas, Gt as redactCredentials, H as CARTOCIUDAD_PUBLIC_HOST, Hi as PLANETARY_BASEMAP_GROUPS, Hn as scrubPrintLayoutForLayers, Hr as inferFieldTypes, Ht as isCredentialFieldName, I as resolveMapGrid, Ii as getRegionalBasemapByStyleUrl, In as serializeStyleLibrary, Ir as stacAssetMediaType, It as MAX_STORY_CHAPTER_DURATION_SECONDS, J as GEOCODE_LAT_KEY, Ji as getActiveBodyRadiusRatio, Jn as DEFAULT_LAYER_GROUP_OPACITY, Jr as SELECTION_MODES, Jt as setRegistryPublishableSettings, K as GEOCODE_ATTRIBUTE_PREFIX, Ki as earthAreaToBody, Kn as scrubLegendForRemovedLayers, Kr as substituteExpressionVariables, Kt as redactProjectCredentials, L as serializeProject, Li as isRegionalBasemapSentinel, Ln as DEFAULT_PRINT_LAYOUT, Lr as validateLayerDescriptiveMetadata, Lt as MIN_STORY_CHAPTER_DURATION_SECONDS, M as normalizeWidgets, Mi as REGIONAL_BASEMAPS, Mn as isStyleLibraryTargetLayer, Mr as isValidMetadataUrl, Mt as setGeocodingTokenProvider, N as parseProject, Ni as REGIONAL_BASEMAP_GROUPS, Nn as normalizeStyleLibraryEntries, Nr as metadataDateToRfc3339, Nt as shouldThrottle, O as normalizeProjectComments, Oa as isDuckDBQueryLayer, Oi as basemapToCesiumImagery, On as STYLE_LIBRARY_BUNDLE_VERSION, Or as STAC_VERSION, Ot as resolveGeocoderConfig, P as portableWmsTileUrl, Pi as REGIONAL_BASEMAP_SENTINEL_PREFIX, Pn as parseStyleLibrary, Pr as normalizeLayerDescriptiveMetadata, Pt as unmatchedGeocodeFeature, Q as GEOCODE_STATUS_KEY, Qi as getEllipsoid, Qn as effectiveLayerRenderState, Qr as getArcgisApiKey, Qt as resolveHeaderReferences, R as serializeProjectWithLayerCache, Ri as DEFAULT_ELLIPSOID_ID, Rn as createDefaultPrintLayout, Rr as EXPRESSION_FUNCTION_CATEGORIES, Rt as normalizeStoryChapterDurationSeconds, S as normalizeMapViewState, Sa as NETCDF_IMAGE_SOURCE_KIND, Si as normalizeMapCrs, Sn as geoArrowToFeatureCollection, Sr as layerJoinKey, St as nominatimReverseResultToDisplay, T as normalizeObiaWorkbench, Ta as PROTOMAPS_BASEMAPS, Ti as normalizeArcgisWkid, Tn as BUILT_IN_STYLE_PRESETS, Tr as applyLayerVirtualFields, Tt as normalizeGeocodingProviderId, U as DEFAULT_FORWARD_GEOCODE_ENDPOINT, Ui as PLANETARY_BASEMAP_SENTINEL_PREFIX, Un as scrubPrintLayoutForRemovedLayers, Ur as isStyleSpecColor, Ut as isCredentialUrlParam, V as CARTOCIUDAD_MIN_INTERVAL_MS, Vi as PLANETARY_BASEMAPS, Vn as printLayoutConfigsEqual, Vr as formatExpressionPreviewValue, Vt as PUBLISHABLE_PLUGIN_SETTINGS, W as DEFAULT_GEOCODING_PROVIDER_ID, Wi as PLANET_SWITCHER_OPTIONS, Wn as removedLayerIdSet, Wr as matchFeaturesByExpression, Wt as redactConfigurationCredentials, X as GEOCODE_PROVIDER_KEY, Xi as getActiveMeanRadiusMeters, Xn as buildLayerPanelUnits, Xr as featureSelectionId, Xt as hasHeaderReferences, Y as GEOCODE_LON_KEY, Yi as getActiveEllipsoid, Yn as applyGroupEffects, Yr as applySelectionMode, Yt as allowsCredentialHeaders, Z as GEOCODE_SCORE_KEY, Zi as getActiveSemiMajorAxisMeters, Zn as buildLayerTree, Zr as invertSelection, Zt as isHeaderReferenceOnly, _ as normalizeBookmarkGroups, _a as LAYER_TYPES, _i as MAP_CRS_CHANGE_EVENT, _n as czmlSource, _r as resolveRolePrivileges, _t as geocoderSupportsSuggest, a as DEFAULT_PROJECT_NAME, aa as DEFAULT_BASEMAP, ai as getRuntimeEnvironment, an as cesiumIonAssetKind, ar as reorderLayerGroupInPanel, at as arcgisLocatorInputField, b as normalizeLegendConfig, ba as MAX_PROCESSING_HISTORY, bi as deriveTileMatrixSet, bn as computeGeoArrowBBox, br as cascadeLayerJoinRefresh, bt as nextDelayMs, c as createDefaultMapView, ca as DEFAULT_LAYER_STYLE, ci as decodePolyline, cn as isCesiumOnlyLayer, cr as ROLE_PRIVILEGES, ct as csvRowsToGeocodeRequests, d as createProjectTemplate, da as DEFAULT_PRIMARY_RENDERER, di as geoJSONToPolylineStr, dn as cesiumKmlSource, dr as hasAppPrivilege, dt as geocodeMatchToFeature, ea as getPlanetaryBasemapByStyleUrl, ei as getCesiumIonToken, en as CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, er as layerGroupDepth, et as GeocoderServiceError, f as detachProjectCopy, fa as DEFAULT_PROJECT_PREFERENCES, fi as polylineStrToGeoJSON, fn as createCesiumKmlLayer, fr as inferLayerCapabilities, ft as geocodeReverse, g as normalizeBlankBackgroundColor, ga as LARGE_VECTOR_FEATURE_THRESHOLD, gi as transformGeojsonElevation, gn as createCzmlLayer, gr as resolveLayerCapabilities, gt as geocoderSupportsReverse, h as isSessionOnlyLayer, ha as DUCKDB_VECTOR_ROUTE_BYTES, hi as horizontalBbox, hn as CZML_SOURCE_KIND, hr as normalizeLayerCapabilities, ht as geocoderNeedsApiKey, i as previewValue, ia as BLEND_MODES, ii as getProtomapsStyleUrl, in as cesiumIonAssetId, ir as normalizeGroupContiguity, it as PUBLIC_GEOCODE_ROW_CAP, j as normalizeStoryMap, ji as CHINA_BASEMAPS, jn as extractStyleLibraryStyle, jr as isValidMetadataEmail, jt as setGeocodingFetch, k as normalizeProjectInteraction, ka as shouldUseTiledRendering, ki as normalizeCesiumBasemap, kn as SYMBOL_STYLE_KEYS, kr as buildLayerStacItem, kt as rowCap, l as createEmptyProject, la as DEFAULT_LEGEND_CONFIG, li as decodePolylineDetailed, ln as parseCesiumIonAssetId, lr as appPrivilegeReason, lt as fetchArcGISLocatorInfo, m as isAllowedPluginManifestUrl, ma as DUCKDB_VECTOR_FEATURE_WARN_COUNT, mi as geojsonHasZCoordinates, mn as CZML_QUICK_PICKS, mr as normalizeAppPrivileges, mt as geocoderMinIntervalMs, n as diffProjects, na as setActiveEllipsoidId, ni as getMapboxAccessToken, nn as CESIUM_ION_SOURCE_KIND, nr as layerGroupSortability, nt as NOMINATIM_MIN_INTERVAL_MS, o as MAX_PROJECT_BOOKMARKS, oa as DEFAULT_BLEND_MODE, oi as getSpatialExtensionPath, on as createCesiumIonLayer, or as sortLayerGroupInPanel, ot as buildForwardGeocodeUrl, p as hydrateProjectLayer, pa as DEFAULT_STORY_MAP, pi as unescapePolyline, pn as isCesiumKmlLayer, pr as intersectPrivileges, pt as geocodeSuggest, q as GEOCODE_DISPLAY_NAME_KEY, qi as earthLengthToBody, qn as scrubWidgetsForRemovedLayers, qr as validateMapExpression, qt as redactUrlCredentials, r as jsonValuesEqual, ra as BLANK_BASEMAP, ri as getProtomapsApiKey, rn as CESIUM_OSM_BUILDINGS_ASSET_ID, rr as layerPanelGroupHeaders, rt as NOMINATIM_PUBLIC_HOST, s as applyProjectToStore, sa as DEFAULT_DASHBOARD_COLUMNS, si as batchDecodePolylines, sn as isCesiumIonLayer, sr as ALL_APP_PRIVILEGES, st as buildReverseGeocodeUrl, t as diffFeatureCollections, ta as meanRadiusMeters, ti as getGoogleMapsApiKey, tn as CESIUM_ION_QUICK_PICKS, tr as layerGroupMoveability, tt as GeocoderUnsupportedError, u as createProjectLayerSerializationCache, ua as DEFAULT_MAP_GRID_LAYOUT, ui as encodePolyline, un as CESIUM_KML_SOURCE_KIND, ur as createDefaultAppCapabilities, ut as geocodeForward, v as normalizeBookmarks, va as MAX_DASHBOARD_COLUMNS, vi as MAP_CRS_PRESETS, vn as isCzmlLayer, vr as applyJoinsToLayer, vt as getGeocoderConfig, w as normalizeModels, wa as PROJECT_VERSION, wi as ARCGIS_PROJECTION_PRESETS, wn as withRasterSourceDefaults, wr as stripJoinFields, wt as normalizeGeocodingLocator, x as normalizeMapLayout, xa as MIN_DASHBOARD_COLUMNS, xi as getMapCrsPreset, xn as featureCollectionToGeoArrow, xr as collectTransitiveJoinSourceIds, xt as nominatimResultToFeature, y as normalizeDashboardColumns, ya as MAX_MAP_GRID_DIM, yi as adaptBboxTemplateToCrs, yn as parseCzml, yr as applyLayerJoins, yt as getGeocodingProvider, z as serializeProjectWithLayerCacheAsync, zi as EARTH_MEAN_RADIUS_METERS, zn as isDefaultPrintLayout, zr as compileFeatureExpression, zt as MAX_REDACT_DEPTH } from "./project-diff-CSG1AgSK.mjs";
|
|
2
2
|
import { Color, featureFilter, latest, normalizePropertyExpression } from "@maplibre/maplibre-gl-style-spec";
|
|
3
3
|
import { create } from "zustand";
|
|
4
4
|
import { temporal } from "zundo";
|
|
5
5
|
import { v4 } from "uuid";
|
|
6
6
|
import { shallow } from "zustand/shallow";
|
|
7
7
|
import { useShallow } from "zustand/react/shallow";
|
|
8
|
-
|
|
8
|
+
// src/diagram.ts
|
|
9
9
|
/**
|
|
10
10
|
* Hard cap on how many features get a diagram. Each diagram is rasterized into
|
|
11
11
|
* an icon atlas, so an unbounded layer (e.g. a million-point parquet) would
|
|
@@ -210,8 +210,7 @@ function diagramPixelSize(datum, style, maxSizeValue) {
|
|
|
210
210
|
if (maxSizeValue <= 0 || datum.sizeValue <= 0) return 8;
|
|
211
211
|
return Math.max(8, size * Math.sqrt(datum.sizeValue / maxSizeValue));
|
|
212
212
|
}
|
|
213
|
-
|
|
214
|
-
//#region src/marker-shape.ts
|
|
213
|
+
// src/marker-shape.ts
|
|
215
214
|
/**
|
|
216
215
|
* Trace the outline of a built-in marker {@link MarkerShape} onto a 2D canvas
|
|
217
216
|
* path, centered in a `size`×`size` box. The caller supplies the fill/stroke;
|
|
@@ -372,8 +371,7 @@ function resolveSvgSource(markup) {
|
|
|
372
371
|
if (trimmed.startsWith("data:")) return trimmed;
|
|
373
372
|
return null;
|
|
374
373
|
}
|
|
375
|
-
|
|
376
|
-
//#region src/hyperlink.ts
|
|
374
|
+
// src/hyperlink.ts
|
|
377
375
|
/**
|
|
378
376
|
* Return a whole-value HTTP(S) URL that is safe to expose as an attribute link.
|
|
379
377
|
*
|
|
@@ -394,8 +392,7 @@ function attributeLinkUrl(value) {
|
|
|
394
392
|
return null;
|
|
395
393
|
}
|
|
396
394
|
}
|
|
397
|
-
|
|
398
|
-
//#region src/photo.ts
|
|
395
|
+
// src/photo.ts
|
|
399
396
|
/**
|
|
400
397
|
* Feature-property keys for inline photo images, shared by the app and the map
|
|
401
398
|
* package so neither hardcodes a second copy that could drift. These keys are
|
|
@@ -413,8 +410,7 @@ const PHOTO_PROPERTY = "photo";
|
|
|
413
410
|
* format a browser cannot display at native size (TIFF/HEIC).
|
|
414
411
|
*/
|
|
415
412
|
const PHOTO_FULL_PROPERTY = "photo_full";
|
|
416
|
-
|
|
417
|
-
//#region src/color-ramp.ts
|
|
413
|
+
// src/color-ramp.ts
|
|
418
414
|
/** The built-in color ramps offered by the style panels. */
|
|
419
415
|
const VECTOR_COLOR_RAMPS = [
|
|
420
416
|
{
|
|
@@ -942,8 +938,7 @@ function naturalClassBreaks(values, count) {
|
|
|
942
938
|
breaks[0] = sorted[0];
|
|
943
939
|
return breaks;
|
|
944
940
|
}
|
|
945
|
-
|
|
946
|
-
//#region src/paths.ts
|
|
941
|
+
// src/paths.ts
|
|
947
942
|
const PATH_TRAVERSAL = /(?:^|[/\\])\.\.(?:[/\\]|$)/;
|
|
948
943
|
/**
|
|
949
944
|
* Whether a path contains a `..` directory-traversal segment. Used to reject a
|
|
@@ -975,178 +970,7 @@ function hasPathTraversal(path) {
|
|
|
975
970
|
function isAbsoluteFilesystemPath(path) {
|
|
976
971
|
return path.startsWith("/") || /^[a-z]:[\\/]/i.test(path);
|
|
977
972
|
}
|
|
978
|
-
|
|
979
|
-
//#region src/runtime-env.ts
|
|
980
|
-
const buildEnv = typeof __GEOLIBRE_BUILD_ENV__ === "undefined" ? {} : __GEOLIBRE_BUILD_ENV__;
|
|
981
|
-
/**
|
|
982
|
-
* The allowlisted build-time environment, with no runtime overlay.
|
|
983
|
-
*
|
|
984
|
-
* For settings that must be fixed by the build and NOT overridable by a
|
|
985
|
-
* `.geolibre.json` a user opened — the auth gate, the deployment profile, the
|
|
986
|
-
* embed origin allowlist. Routing those through {@link getRuntimeEnvironment}
|
|
987
|
-
* would let project-supplied `__GEOLIBRE_RUNTIME_ENV__` values relax them.
|
|
988
|
-
*
|
|
989
|
-
* Callers should prefer this over reading `import.meta.env` directly: a
|
|
990
|
-
* whole-object read defeats Vite's per-key replacement and inlines every
|
|
991
|
-
* `VITE_` var on the build machine into the chunk.
|
|
992
|
-
*
|
|
993
|
-
* @returns The build-time environment record.
|
|
994
|
-
*/
|
|
995
|
-
function getBuildEnvironment() {
|
|
996
|
-
return buildEnv;
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Merges build-time env with project runtime env (the latter wins). Falls back
|
|
1000
|
-
* to build-time env alone outside a browser (e.g. in tests).
|
|
1001
|
-
*
|
|
1002
|
-
* @returns The resolved environment variables.
|
|
1003
|
-
*/
|
|
1004
|
-
function getRuntimeEnvironment() {
|
|
1005
|
-
if (typeof window === "undefined") return buildEnv;
|
|
1006
|
-
return {
|
|
1007
|
-
...buildEnv,
|
|
1008
|
-
...window.__GEOLIBRE_RUNTIME_ENV__ ?? {}
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
/**
|
|
1012
|
-
* Resolves a local DuckDB spatial extension path from the runtime environment.
|
|
1013
|
-
*
|
|
1014
|
-
* When `VITE_DUCKDB_SPATIAL_EXTENSION_PATH` is set, DuckDB consumers (the
|
|
1015
|
-
* desktop app's own loader and the Add Vector panel's maplibre-gl-vector
|
|
1016
|
-
* control) load the spatial extension from this path with `LOAD '<path>'`
|
|
1017
|
-
* instead of installing it from the remote repository, which hangs in
|
|
1018
|
-
* sandboxed or firewalled environments. Lives in `@geolibre/core` so every
|
|
1019
|
-
* consumer shares one implementation.
|
|
1020
|
-
*
|
|
1021
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1022
|
-
* injectable for testing.
|
|
1023
|
-
* @returns The trimmed extension path, or undefined when unset.
|
|
1024
|
-
*/
|
|
1025
|
-
function getSpatialExtensionPath(env) {
|
|
1026
|
-
return (env ?? getRuntimeEnvironment()).VITE_DUCKDB_SPATIAL_EXTENSION_PATH?.trim() || void 0;
|
|
1027
|
-
}
|
|
1028
|
-
/**
|
|
1029
|
-
* Resolves the Protomaps API key from the runtime environment.
|
|
1030
|
-
*
|
|
1031
|
-
* Protomaps' hosted styles require an API key embedded in the style URL. The
|
|
1032
|
-
* key is supplied via `VITE_PROTOMAPS_API_KEY` (baked in at build time for the
|
|
1033
|
-
* web demo; see the deploy workflow). When unset, the Protomaps basemaps are
|
|
1034
|
-
* unavailable and should be hidden from the UI.
|
|
1035
|
-
*
|
|
1036
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1037
|
-
* injectable for testing.
|
|
1038
|
-
* @returns The trimmed API key, or undefined when unset.
|
|
1039
|
-
*/
|
|
1040
|
-
function getProtomapsApiKey(env) {
|
|
1041
|
-
return (env ?? getRuntimeEnvironment()).VITE_PROTOMAPS_API_KEY?.trim() || void 0;
|
|
1042
|
-
}
|
|
1043
|
-
/**
|
|
1044
|
-
* Resolves the Google Maps API key from the runtime environment.
|
|
1045
|
-
*
|
|
1046
|
-
* GeoLibre's browser-facing builds normally use `VITE_GOOGLE_MAPS_API_KEY`.
|
|
1047
|
-
* The bare `GOOGLE_MAPS_API_KEY` fallback is reached two ways: (1) the desktop
|
|
1048
|
-
* Vite config copies it to `VITE_GOOGLE_MAPS_API_KEY` at build time for local
|
|
1049
|
-
* shell testing (`vite.config.ts`'s `envPrefix` does not include the bare
|
|
1050
|
-
* name), and (2) a project's own runtime environment variables
|
|
1051
|
-
* (`window.__GEOLIBRE_RUNTIME_ENV__`), which are not subject to Vite's
|
|
1052
|
-
* envPrefix allowlist at all.
|
|
1053
|
-
*
|
|
1054
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1055
|
-
* injectable for testing.
|
|
1056
|
-
* @returns The trimmed API key, or undefined when unset.
|
|
1057
|
-
*/
|
|
1058
|
-
function getGoogleMapsApiKey(env) {
|
|
1059
|
-
const runtimeEnv = env ?? getRuntimeEnvironment();
|
|
1060
|
-
return runtimeEnv.VITE_GOOGLE_MAPS_API_KEY?.trim() || runtimeEnv.GOOGLE_MAPS_API_KEY?.trim() || void 0;
|
|
1061
|
-
}
|
|
1062
|
-
/**
|
|
1063
|
-
* Resolves the Mapbox access token from the runtime environment.
|
|
1064
|
-
*
|
|
1065
|
-
* The basemap control's Mapbox styles authenticate with the user's own token.
|
|
1066
|
-
* It is supplied via `VITE_MAPBOX_ACCESS_TOKEN` (baked in at build time from the
|
|
1067
|
-
* bare `MAPBOX_TOKEN` env var, which `vite.config.ts` copies into the prefixed
|
|
1068
|
-
* name — the spelling Mapbox's own tooling uses) or set at runtime through
|
|
1069
|
-
* Settings → Environment variables (`window.__GEOLIBRE_RUNTIME_ENV__`, which
|
|
1070
|
-
* bypasses Vite's envPrefix allowlist, so a bare `MAPBOX_TOKEN` entry works
|
|
1071
|
-
* there too). When unset, the Mapbox basemaps prompt for a token in the basemap
|
|
1072
|
-
* panel's API keys view instead.
|
|
1073
|
-
*
|
|
1074
|
-
* Note the precedence, shared with {@link getGoogleMapsApiKey} and
|
|
1075
|
-
* {@link getCesiumIonToken}: the prefixed name always wins over the bare one,
|
|
1076
|
-
* and `getRuntimeEnvironment` merges build-time and runtime vars into one
|
|
1077
|
-
* record. So a build that baked in `VITE_MAPBOX_ACCESS_TOKEN` is overridden at
|
|
1078
|
-
* runtime by a Settings entry under that *same* prefixed name; a bare
|
|
1079
|
-
* `MAPBOX_TOKEN` entry is a fallback for when nothing was baked in, not a way
|
|
1080
|
-
* to override a baked token.
|
|
1081
|
-
*
|
|
1082
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1083
|
-
* injectable for testing.
|
|
1084
|
-
* @returns The trimmed token, or undefined when unset.
|
|
1085
|
-
*/
|
|
1086
|
-
function getMapboxAccessToken(env) {
|
|
1087
|
-
const runtimeEnv = env ?? getRuntimeEnvironment();
|
|
1088
|
-
return runtimeEnv.VITE_MAPBOX_ACCESS_TOKEN?.trim() || runtimeEnv.MAPBOX_TOKEN?.trim() || void 0;
|
|
1089
|
-
}
|
|
1090
|
-
/**
|
|
1091
|
-
* Resolves the ArcGIS API key from the runtime environment.
|
|
1092
|
-
*
|
|
1093
|
-
* The ArcGIS renderer draws the translated project basemap and non-Esri layers
|
|
1094
|
-
* without a key; Esri's basemap styles and location services require one
|
|
1095
|
-
* (an ArcGIS Location Platform or ArcGIS Online API key credential). It is
|
|
1096
|
-
* supplied via `VITE_ARCGIS_API_KEY` (baked in at build time from the bare
|
|
1097
|
-
* `ARCGIS_API_KEY` env var, which `vite.config.ts` copies into the prefixed
|
|
1098
|
-
* name) or set at runtime through Settings → Environment variables
|
|
1099
|
-
* (`window.__GEOLIBRE_RUNTIME_ENV__`, so a bare `ARCGIS_API_KEY` entry works
|
|
1100
|
-
* there too). Same precedence as {@link getMapboxAccessToken}.
|
|
1101
|
-
*
|
|
1102
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1103
|
-
* injectable for testing.
|
|
1104
|
-
* @returns The trimmed key, or undefined when unset.
|
|
1105
|
-
*/
|
|
1106
|
-
function getArcgisApiKey(env) {
|
|
1107
|
-
const runtimeEnv = env ?? getRuntimeEnvironment();
|
|
1108
|
-
return runtimeEnv.VITE_ARCGIS_API_KEY?.trim() || runtimeEnv.ARCGIS_API_KEY?.trim() || void 0;
|
|
1109
|
-
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Resolves the Cesium Ion access token from the runtime environment.
|
|
1112
|
-
*
|
|
1113
|
-
* Cesium World Terrain and Ion World Imagery need a Cesium Ion token. It is
|
|
1114
|
-
* supplied via `VITE_CESIUM_TOKEN` (baked in at build time from the bare
|
|
1115
|
-
* `CESIUM_TOKEN` env var, which `vite.config.ts` copies into the prefixed name)
|
|
1116
|
-
* or set at runtime through Settings → Environment variables
|
|
1117
|
-
* (`window.__GEOLIBRE_RUNTIME_ENV__`, which bypasses Vite's envPrefix allowlist,
|
|
1118
|
-
* so a bare `CESIUM_TOKEN` entry works there too).
|
|
1119
|
-
*
|
|
1120
|
-
* The 3D-globe view itself does **not** need one: it draws the project basemap
|
|
1121
|
-
* as its base imagery whenever that basemap has a raster form (see
|
|
1122
|
-
* {@link basemapToCesiumImagery}), and falls back to Ion World Imagery — or, with
|
|
1123
|
-
* no token, to OpenStreetMap — for the ones that do not. So an absent token
|
|
1124
|
-
* costs terrain and the quality of that fallback, not the view.
|
|
1125
|
-
*
|
|
1126
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1127
|
-
* injectable for testing.
|
|
1128
|
-
* @returns The trimmed token, or undefined when unset.
|
|
1129
|
-
*/
|
|
1130
|
-
function getCesiumIonToken(env) {
|
|
1131
|
-
const runtimeEnv = env ?? getRuntimeEnvironment();
|
|
1132
|
-
return runtimeEnv.VITE_CESIUM_TOKEN?.trim() || runtimeEnv.CESIUM_TOKEN?.trim() || void 0;
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Builds a full Protomaps v5 style URL for a flavor, injecting the API key.
|
|
1136
|
-
*
|
|
1137
|
-
* @param flavor - The Protomaps flavor name (e.g. `light`, `dark`, `white`,
|
|
1138
|
-
* `grayscale`, `black`).
|
|
1139
|
-
* @param env - Environment record (defaults to the runtime environment);
|
|
1140
|
-
* injectable for testing.
|
|
1141
|
-
* @returns The resolved style URL, or undefined when no API key is configured.
|
|
1142
|
-
*/
|
|
1143
|
-
function getProtomapsStyleUrl(flavor, env) {
|
|
1144
|
-
const key = getProtomapsApiKey(env);
|
|
1145
|
-
if (!key) return void 0;
|
|
1146
|
-
return `https://api.protomaps.com/styles/v5/${encodeURIComponent(flavor)}/en.json?key=${encodeURIComponent(key)}`;
|
|
1147
|
-
}
|
|
1148
|
-
//#endregion
|
|
1149
|
-
//#region src/routing.ts
|
|
973
|
+
// src/routing.ts
|
|
1150
974
|
/**
|
|
1151
975
|
* Routing / network-analysis client and pure helpers backing the Processing →
|
|
1152
976
|
* Network tools (isochrones / service areas, OD cost matrices).
|
|
@@ -1470,8 +1294,7 @@ function requestRoute(endpoint, body, signal) {
|
|
|
1470
1294
|
function requestNavigationRoute(endpoint, body, signal) {
|
|
1471
1295
|
return postJson(`${stripTrailingSlash(endpoint)}/route`, body, signal);
|
|
1472
1296
|
}
|
|
1473
|
-
|
|
1474
|
-
//#region src/vector-color.ts
|
|
1297
|
+
// src/vector-color.ts
|
|
1475
1298
|
/** Whether a color value is a data-driven expression rather than a flat color. */
|
|
1476
1299
|
function isVectorColorExpression(value) {
|
|
1477
1300
|
return Array.isArray(value);
|
|
@@ -2252,8 +2075,7 @@ function extrusionColorValue(style) {
|
|
|
2252
2075
|
if (vectorExpression !== flat) return vectorExpression;
|
|
2253
2076
|
return parseJsonExpression(styleValue(style, "extrusionAdvancedStyleEnabled") ? styleValue(style, "extrusionColorExpression") : "") ?? flat;
|
|
2254
2077
|
}
|
|
2255
|
-
|
|
2256
|
-
//#region src/style-layer-evaluator.ts
|
|
2078
|
+
// src/style-layer-evaluator.ts
|
|
2257
2079
|
const GEOMETRY_TYPE = {
|
|
2258
2080
|
Point: 1,
|
|
2259
2081
|
LineString: 2,
|
|
@@ -2332,8 +2154,7 @@ function createStyleLayerEvaluator(layer) {
|
|
|
2332
2154
|
}
|
|
2333
2155
|
};
|
|
2334
2156
|
}
|
|
2335
|
-
|
|
2336
|
-
//#region src/document-locale.ts
|
|
2157
|
+
// src/document-locale.ts
|
|
2337
2158
|
/**
|
|
2338
2159
|
* The document language, so formatted numbers and dates follow the UI locale.
|
|
2339
2160
|
*
|
|
@@ -2345,8 +2166,7 @@ function createStyleLayerEvaluator(layer) {
|
|
|
2345
2166
|
function documentLocale() {
|
|
2346
2167
|
return (typeof document !== "undefined" ? document.documentElement.lang.trim() : "") || void 0;
|
|
2347
2168
|
}
|
|
2348
|
-
|
|
2349
|
-
//#region src/label-number-format.ts
|
|
2169
|
+
// src/label-number-format.ts
|
|
2350
2170
|
/**
|
|
2351
2171
|
* Locale-aware number formatting for map labels (issue #2336).
|
|
2352
2172
|
*
|
|
@@ -2562,8 +2382,7 @@ function labelFieldTextField(labels, fallbackLocale) {
|
|
|
2562
2382
|
function formatLabelNumberSample(locale, decimals) {
|
|
2563
2383
|
return labelNumberFormatter(resolveLabelNumberLocale(locale), decimals).format(LABEL_NUMBER_SAMPLE);
|
|
2564
2384
|
}
|
|
2565
|
-
|
|
2566
|
-
//#region src/external-native-paint.ts
|
|
2385
|
+
// src/external-native-paint.ts
|
|
2567
2386
|
/**
|
|
2568
2387
|
* Whether a layer is drawn by a **custom render layer** its control created — a
|
|
2569
2388
|
* deck.gl overlay, 3D Tiles, or Add Vector Layer's own MapLibre layers — rather
|
|
@@ -2646,8 +2465,7 @@ function rendererAppliesOpacity(layer, renderer) {
|
|
|
2646
2465
|
function isAdoptedVectorAwaitingFeatures(layer) {
|
|
2647
2466
|
return layer.metadata.sourceKind === "maplibre-gl-vector-adopted" && !layer.geojson;
|
|
2648
2467
|
}
|
|
2649
|
-
|
|
2650
|
-
//#region src/attribute-form.ts
|
|
2468
|
+
// src/attribute-form.ts
|
|
2651
2469
|
/** Look up the configuration for a field, if any. */
|
|
2652
2470
|
function getAttributeFormField(form, field) {
|
|
2653
2471
|
return form?.fields.find((entry) => entry.field === field);
|
|
@@ -2881,8 +2699,50 @@ function featureForEvaluation(properties, feature) {
|
|
|
2881
2699
|
properties
|
|
2882
2700
|
};
|
|
2883
2701
|
}
|
|
2884
|
-
|
|
2885
|
-
|
|
2702
|
+
// src/map-click-claims.ts
|
|
2703
|
+
/**
|
|
2704
|
+
* Map tools that own the map's clicks while they draw (the Measure control
|
|
2705
|
+
* placing points, the Geo Editor sketching a shape) register a claim here, and
|
|
2706
|
+
* the Identify click handlers stand down while any claim holds. Without it a
|
|
2707
|
+
* click meant as a measure vertex also opens an Identify popup over the layer
|
|
2708
|
+
* underneath (issue #3237).
|
|
2709
|
+
*
|
|
2710
|
+
* A claim is a predicate read at click time rather than a flag the tool sets,
|
|
2711
|
+
* so a tool whose drawing state changes without an event (Measure stops
|
|
2712
|
+
* drawing silently when its panel collapses) never leaves a stale claim.
|
|
2713
|
+
*/
|
|
2714
|
+
const claims = /* @__PURE__ */ new Set();
|
|
2715
|
+
/**
|
|
2716
|
+
* Register a tool whose drawing state claims the map's clicks.
|
|
2717
|
+
*
|
|
2718
|
+
* Args:
|
|
2719
|
+
* isClaiming: Returns true while the tool is drawing and owns map clicks.
|
|
2720
|
+
*
|
|
2721
|
+
* Returns:
|
|
2722
|
+
* A function that removes the claim.
|
|
2723
|
+
*/
|
|
2724
|
+
function registerMapClickClaim(isClaiming) {
|
|
2725
|
+
const entry = () => isClaiming();
|
|
2726
|
+
claims.add(entry);
|
|
2727
|
+
return () => {
|
|
2728
|
+
claims.delete(entry);
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2731
|
+
/**
|
|
2732
|
+
* Whether a registered map tool currently owns the map's clicks.
|
|
2733
|
+
*
|
|
2734
|
+
* Returns:
|
|
2735
|
+
* True when any registered claim reports that its tool is drawing.
|
|
2736
|
+
*/
|
|
2737
|
+
function isMapClickClaimed() {
|
|
2738
|
+
for (const isClaiming of claims) try {
|
|
2739
|
+
if (isClaiming()) return true;
|
|
2740
|
+
} catch (error) {
|
|
2741
|
+
console.warn("[GeoLibre] A map click claim could not be read", error);
|
|
2742
|
+
}
|
|
2743
|
+
return false;
|
|
2744
|
+
}
|
|
2745
|
+
// src/popup.ts
|
|
2886
2746
|
/** Match an inline base64 raster image (excludes SVG, which can carry scripts). */
|
|
2887
2747
|
const INLINE_IMAGE_DATA_URL = /^data:image\/(?!svg)[\w.+-]+;base64,/i;
|
|
2888
2748
|
/**
|
|
@@ -3225,8 +3085,7 @@ function isSafePopupUrl(value, allowDataImage = false) {
|
|
|
3225
3085
|
if (/^https?:\/\//i.test(trimmed)) return true;
|
|
3226
3086
|
return allowDataImage && INLINE_IMAGE_DATA_URL.test(trimmed);
|
|
3227
3087
|
}
|
|
3228
|
-
|
|
3229
|
-
//#region src/quick-filters.ts
|
|
3088
|
+
// src/quick-filters.ts
|
|
3230
3089
|
/**
|
|
3231
3090
|
* Quick filters (issue #2114): per-layer, data-driven filter controls that
|
|
3232
3091
|
* compile down to the MapLibre filter a layer already supports.
|
|
@@ -3465,8 +3324,7 @@ function clearQuickFilterValues(filters) {
|
|
|
3465
3324
|
text: filter.kind === "text" ? "" : filter.text
|
|
3466
3325
|
}));
|
|
3467
3326
|
}
|
|
3468
|
-
|
|
3469
|
-
//#region src/layer-filters.ts
|
|
3327
|
+
// src/layer-filters.ts
|
|
3470
3328
|
/**
|
|
3471
3329
|
* Return a layer's persisted expression filter when it has a usable array
|
|
3472
3330
|
* shape, otherwise return null.
|
|
@@ -3501,8 +3359,7 @@ function compileLayerFilters(layer) {
|
|
|
3501
3359
|
function hasActiveLayerFilter(layer) {
|
|
3502
3360
|
return compileLayerFilters(layer) !== null;
|
|
3503
3361
|
}
|
|
3504
|
-
|
|
3505
|
-
//#region src/deployment-capabilities.ts
|
|
3362
|
+
// src/deployment-capabilities.ts
|
|
3506
3363
|
/** Every capability, in a stable order for docs and tests. */
|
|
3507
3364
|
const DEPLOYMENT_CAPABILITIES = [
|
|
3508
3365
|
"project:edit",
|
|
@@ -3555,8 +3412,7 @@ function parseDeploymentCapabilities(raw) {
|
|
|
3555
3412
|
}
|
|
3556
3413
|
return granted;
|
|
3557
3414
|
}
|
|
3558
|
-
|
|
3559
|
-
//#region src/store/capabilities-slice.ts
|
|
3415
|
+
// src/store/capabilities-slice.ts
|
|
3560
3416
|
/**
|
|
3561
3417
|
* What this deployment and this session may do: deployment capabilities
|
|
3562
3418
|
* (issue #1673) and the application role / privilege model (issue #1672).
|
|
@@ -3612,8 +3468,7 @@ const createCapabilitiesSlice = (set, get) => ({
|
|
|
3612
3468
|
return hasAppPrivilege(get().capabilities, privilege);
|
|
3613
3469
|
}
|
|
3614
3470
|
});
|
|
3615
|
-
|
|
3616
|
-
//#region src/store/collaboration-slice.ts
|
|
3471
|
+
// src/store/collaboration-slice.ts
|
|
3617
3472
|
/**
|
|
3618
3473
|
* A fresh, inactive collaboration slice (no live session). Frozen (like
|
|
3619
3474
|
* DEFAULT_LEGEND_CONFIG) to guard against accidental in-place mutation; store
|
|
@@ -3671,8 +3526,7 @@ const createCollaborationSlice = (set) => ({
|
|
|
3671
3526
|
}
|
|
3672
3527
|
}))
|
|
3673
3528
|
});
|
|
3674
|
-
|
|
3675
|
-
//#region src/store/session-slice.ts
|
|
3529
|
+
// src/store/session-slice.ts
|
|
3676
3530
|
/** Reserved Identify target for querying every visible queryable layer at once. */
|
|
3677
3531
|
const IDENTIFY_ALL_LAYERS_ID = "__geolibre_identify_all_layers__";
|
|
3678
3532
|
/**
|
|
@@ -3801,8 +3655,7 @@ const createSessionSlice = (set) => ({
|
|
|
3801
3655
|
}),
|
|
3802
3656
|
setAttributeFilter: (filter) => set({ attributeFilter: filter })
|
|
3803
3657
|
});
|
|
3804
|
-
|
|
3805
|
-
//#region src/store/layer-removal.ts
|
|
3658
|
+
// src/store/layer-removal.ts
|
|
3806
3659
|
/**
|
|
3807
3660
|
* Reference scrubbing shared by the actions that delete layers (`removeLayer`
|
|
3808
3661
|
* and `removeLayerGroup` with `removeChildren`), so a deleted layer never
|
|
@@ -3867,8 +3720,7 @@ function cascadeJoinRefreshForRemoved(layers, layerIds) {
|
|
|
3867
3720
|
for (const id of removedLayerIdSet(layerIds)) current = cascadeLayerJoinRefresh(current, id);
|
|
3868
3721
|
return current;
|
|
3869
3722
|
}
|
|
3870
|
-
|
|
3871
|
-
//#region src/store/layer-groups-slice.ts
|
|
3723
|
+
// src/store/layer-groups-slice.ts
|
|
3872
3724
|
/**
|
|
3873
3725
|
* Layer-panel folders: create, rename, nest, reorder, sort and delete groups,
|
|
3874
3726
|
* and move layers between them. `layerGroups` is tracked by undo history
|
|
@@ -4059,8 +3911,7 @@ const createLayerGroupsSlice = (set, get) => ({
|
|
|
4059
3911
|
};
|
|
4060
3912
|
})
|
|
4061
3913
|
});
|
|
4062
|
-
|
|
4063
|
-
//#region src/file-name.ts
|
|
3914
|
+
// src/file-name.ts
|
|
4064
3915
|
/**
|
|
4065
3916
|
* A bare Android SAF document ID, as the browser `File.name` carries after a
|
|
4066
3917
|
* native import: a known volume prefix (`primary:`, `home:`, `raw:`, `msf:`, or a
|
|
@@ -4098,8 +3949,7 @@ function uniqueImportedLayerName(name, names) {
|
|
|
4098
3949
|
while (existing.has(candidate)) candidate = `${name}_${suffix++}`;
|
|
4099
3950
|
return candidate;
|
|
4100
3951
|
}
|
|
4101
|
-
|
|
4102
|
-
//#region src/layer-defaults.ts
|
|
3952
|
+
// src/layer-defaults.ts
|
|
4103
3953
|
/**
|
|
4104
3954
|
* Initial styling for a newly added vector layer (issue #1519).
|
|
4105
3955
|
*
|
|
@@ -4288,8 +4138,7 @@ function isInitialLayerStyle(style, geojson) {
|
|
|
4288
4138
|
};
|
|
4289
4139
|
return style.fillOpacity === expected.fillOpacity && style.strokeWidth === expected.strokeWidth && style.circleRadius === expected.circleRadius;
|
|
4290
4140
|
}
|
|
4291
|
-
|
|
4292
|
-
//#region src/layer-style-clipboard.ts
|
|
4141
|
+
// src/layer-style-clipboard.ts
|
|
4293
4142
|
/**
|
|
4294
4143
|
* `metadata.sourceKind` marking a deck.gl COG raster managed by the
|
|
4295
4144
|
* maplibre-gl-raster control. Mirrors `RASTER_SOURCE_KIND` in
|
|
@@ -4400,8 +4249,7 @@ function rescaleEntryCount(state) {
|
|
|
4400
4249
|
if (state.mode === "rgb") return Array.isArray(state.bands) ? state.bands.length : 3;
|
|
4401
4250
|
return 1;
|
|
4402
4251
|
}
|
|
4403
|
-
|
|
4404
|
-
//#region src/layer-style-file.ts
|
|
4252
|
+
// src/layer-style-file.ts
|
|
4405
4253
|
/** `type` tag identifying a layer styles file. */
|
|
4406
4254
|
const LAYER_STYLES_FILE_TYPE = "geolibre-layer-styles";
|
|
4407
4255
|
/** Format version written by {@link serializeLayerStylesFile}. */
|
|
@@ -4596,8 +4444,7 @@ function matchLayerStyleEntry(layer, entries) {
|
|
|
4596
4444
|
patch
|
|
4597
4445
|
} : null;
|
|
4598
4446
|
}
|
|
4599
|
-
|
|
4600
|
-
//#region src/store/layers-slice.ts
|
|
4447
|
+
// src/store/layers-slice.ts
|
|
4601
4448
|
/**
|
|
4602
4449
|
* The layer types {@link AppState.addTileLayer} accepts. Each renders through
|
|
4603
4450
|
* the raster tile path, which is why the layer's `source.type` is always
|
|
@@ -4612,7 +4459,8 @@ const RASTER_TILE_LAYER_TYPES = /* @__PURE__ */ new Set([
|
|
|
4612
4459
|
const createLayersSlice = (set, get) => ({
|
|
4613
4460
|
layers: [],
|
|
4614
4461
|
copiedLayerStyle: null,
|
|
4615
|
-
addLayer: (
|
|
4462
|
+
addLayer: (inputLayer, beforeLayerId = null) => set((s) => {
|
|
4463
|
+
let layer = withRasterSourceDefaults(inputLayer);
|
|
4616
4464
|
const layers = [...s.layers];
|
|
4617
4465
|
const { sourcePath } = layer;
|
|
4618
4466
|
if (sourcePath && (!/^[a-z][a-z0-9+.-]*:\/\//i.test(sourcePath) || /^(content|file):\/\//i.test(sourcePath)) && isSourceDerivedLayerName(layer.name, sourcePath)) layer = {
|
|
@@ -4656,10 +4504,19 @@ const createLayersSlice = (set, get) => ({
|
|
|
4656
4504
|
isDirty: true
|
|
4657
4505
|
})),
|
|
4658
4506
|
updateLayer: (id, patch) => set((s) => {
|
|
4659
|
-
let layers = s.layers.map((l) =>
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4507
|
+
let layers = s.layers.map((l) => {
|
|
4508
|
+
if (l.id !== id) return l;
|
|
4509
|
+
const updated = {
|
|
4510
|
+
...l,
|
|
4511
|
+
...patch
|
|
4512
|
+
};
|
|
4513
|
+
if (patch.geojson !== void 0 && !("geoarrow" in patch)) delete updated.geoarrow;
|
|
4514
|
+
else if ("geoarrow" in patch) {
|
|
4515
|
+
if (patch.geoarrow === null || patch.geoarrow === void 0) delete updated.geoarrow;
|
|
4516
|
+
else updated.geoarrow = patch.geoarrow;
|
|
4517
|
+
}
|
|
4518
|
+
return updated;
|
|
4519
|
+
});
|
|
4663
4520
|
if (patch.geojson !== void 0) {
|
|
4664
4521
|
if (patch.joins === void 0 && patch.virtualFields === void 0) layers = layers.map((l) => l.id === id && (l.joins?.length || l.virtualFields?.length) ? applyJoinsToLayer(l, layers) : l);
|
|
4665
4522
|
layers = cascadeLayerJoinRefresh(layers, id);
|
|
@@ -4793,8 +4650,14 @@ const createLayersSlice = (set, get) => ({
|
|
|
4793
4650
|
isDirty: true
|
|
4794
4651
|
};
|
|
4795
4652
|
}),
|
|
4796
|
-
addGeoJsonLayer: (name, geojson, sourcePath, beforeLayerId = null) => {
|
|
4653
|
+
addGeoJsonLayer: (name, geojson, sourcePath, beforeLayerId = null, extra) => {
|
|
4797
4654
|
const id = v4();
|
|
4655
|
+
let geoarrow = extra?.geoarrow;
|
|
4656
|
+
if (!geoarrow && shouldUseTiledRendering(geojson)) try {
|
|
4657
|
+
geoarrow = featureCollectionToGeoArrow(geojson) ?? void 0;
|
|
4658
|
+
} catch (err) {
|
|
4659
|
+
console.warn("[GeoLibre] GeoArrow batch conversion failed; falling back to GeoJSON", err);
|
|
4660
|
+
}
|
|
4798
4661
|
const layer = {
|
|
4799
4662
|
id,
|
|
4800
4663
|
name,
|
|
@@ -4807,8 +4670,9 @@ const createLayersSlice = (set, get) => ({
|
|
|
4807
4670
|
layers: get().layers,
|
|
4808
4671
|
overrides: { simpleStyleEnabled: hasSimpleStyleProperties(geojson) }
|
|
4809
4672
|
}),
|
|
4810
|
-
metadata: {},
|
|
4673
|
+
metadata: { ...extra?.metadata },
|
|
4811
4674
|
geojson,
|
|
4675
|
+
...geoarrow ? { geoarrow } : {},
|
|
4812
4676
|
sourcePath
|
|
4813
4677
|
};
|
|
4814
4678
|
get().addLayer(layer, beforeLayerId);
|
|
@@ -4871,8 +4735,7 @@ const createLayersSlice = (set, get) => ({
|
|
|
4871
4735
|
return id;
|
|
4872
4736
|
}
|
|
4873
4737
|
});
|
|
4874
|
-
|
|
4875
|
-
//#region src/layer-library.ts
|
|
4738
|
+
// src/layer-library.ts
|
|
4876
4739
|
/** `type` discriminator of an exported Layer Library bundle file. */
|
|
4877
4740
|
const LAYER_LIBRARY_BUNDLE_TYPE = "geolibre-layer-library";
|
|
4878
4741
|
/** Current bundle format version, for forward-compatible readers. */
|
|
@@ -5532,8 +5395,7 @@ function createLayerLibraryEntryId() {
|
|
|
5532
5395
|
if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
|
|
5533
5396
|
return `layer-lib-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
5534
5397
|
}
|
|
5535
|
-
|
|
5536
|
-
//#region src/store/libraries-slice.ts
|
|
5398
|
+
// src/store/libraries-slice.ts
|
|
5537
5399
|
/**
|
|
5538
5400
|
* The Style Manager, Layer Library and Template Library. The app-level lists
|
|
5539
5401
|
* live outside the project lifecycle (persisted by the desktop app); only the
|
|
@@ -5576,8 +5438,7 @@ const createLibrariesSlice = (set) => ({
|
|
|
5576
5438
|
saveTemplateEntry: (entry) => set((s) => ({ templateLibrary: s.templateLibrary.some((t) => t.id === entry.id) ? s.templateLibrary.map((t) => t.id === entry.id ? entry : t) : [...s.templateLibrary, entry] })),
|
|
5577
5439
|
deleteTemplateEntry: (id) => set((s) => ({ templateLibrary: s.templateLibrary.filter((t) => t.id !== id) }))
|
|
5578
5440
|
});
|
|
5579
|
-
|
|
5580
|
-
//#region src/store/map-view-slice.ts
|
|
5441
|
+
// src/store/map-view-slice.ts
|
|
5581
5442
|
/**
|
|
5582
5443
|
* The map workspace: the primary camera, the basemap, project preferences, the
|
|
5583
5444
|
* multi-map grid and its secondary panes, and which engine draws the primary
|
|
@@ -5825,8 +5686,7 @@ const createMapViewSlice = (set) => ({
|
|
|
5825
5686
|
isDirty: true
|
|
5826
5687
|
})
|
|
5827
5688
|
});
|
|
5828
|
-
|
|
5829
|
-
//#region src/store/processing-slice.ts
|
|
5689
|
+
// src/store/processing-slice.ts
|
|
5830
5690
|
/**
|
|
5831
5691
|
* Saved processing models (issue #344) and the Processing History log
|
|
5832
5692
|
* (issue #1292). Both are saved with the project.
|
|
@@ -5872,8 +5732,7 @@ const createProcessingSlice = (set) => ({
|
|
|
5872
5732
|
isDirty: true
|
|
5873
5733
|
} : { obiaWorkbench })
|
|
5874
5734
|
});
|
|
5875
|
-
|
|
5876
|
-
//#region src/store/project-content-slice.ts
|
|
5735
|
+
// src/store/project-content-slice.ts
|
|
5877
5736
|
/**
|
|
5878
5737
|
* Project content that sits beside the layers: review comments (issue #1518),
|
|
5879
5738
|
* Dashboard widgets (issue #401) and the story map. All of it is saved with the
|
|
@@ -6049,8 +5908,7 @@ const createProjectContentSlice = (set) => ({
|
|
|
6049
5908
|
};
|
|
6050
5909
|
})
|
|
6051
5910
|
});
|
|
6052
|
-
|
|
6053
|
-
//#region src/history.ts
|
|
5911
|
+
// src/history.ts
|
|
6054
5912
|
/**
|
|
6055
5913
|
* Runtime-settable window (ms) used to coalesce rapid history-producing changes
|
|
6056
5914
|
* (e.g. a continuous opacity/style slider drag) into a single undo entry. Tests
|
|
@@ -6178,8 +6036,7 @@ function leadingDebounce(fn, getWait) {
|
|
|
6178
6036
|
};
|
|
6179
6037
|
return wrapped;
|
|
6180
6038
|
}
|
|
6181
|
-
|
|
6182
|
-
//#region src/store/undo-history.ts
|
|
6039
|
+
// src/store/undo-history.ts
|
|
6183
6040
|
/**
|
|
6184
6041
|
* Undo/redo for the app store. zundo's `temporal` middleware tracks only the
|
|
6185
6042
|
* project-data fields that {@link partializeHistory} lists (layers, groups,
|
|
@@ -6438,8 +6295,7 @@ function clearHistory() {
|
|
|
6438
6295
|
notifyProjectRestoreHistory();
|
|
6439
6296
|
}
|
|
6440
6297
|
}
|
|
6441
|
-
|
|
6442
|
-
//#region src/store/project-slice.ts
|
|
6298
|
+
// src/store/project-slice.ts
|
|
6443
6299
|
/**
|
|
6444
6300
|
* Project identity and lifecycle: name, path, dirty flag, recent projects, and
|
|
6445
6301
|
* the project-level settings that have no richer home (plugins, legend, print
|
|
@@ -6588,8 +6444,7 @@ const createProjectSlice = (set, get) => ({
|
|
|
6588
6444
|
});
|
|
6589
6445
|
}
|
|
6590
6446
|
});
|
|
6591
|
-
|
|
6592
|
-
//#region src/store/ui-slice.ts
|
|
6447
|
+
// src/store/ui-slice.ts
|
|
6593
6448
|
const createUiSlice = (set) => ({
|
|
6594
6449
|
ui: {
|
|
6595
6450
|
processingOpen: false,
|
|
@@ -6785,8 +6640,7 @@ const createUiSlice = (set) => ({
|
|
|
6785
6640
|
styleManagerOpen: open
|
|
6786
6641
|
} }))
|
|
6787
6642
|
});
|
|
6788
|
-
|
|
6789
|
-
//#region src/store.ts
|
|
6643
|
+
// src/store.ts
|
|
6790
6644
|
/**
|
|
6791
6645
|
* The app store: one Zustand store wrapped in zundo's undo history, composed
|
|
6792
6646
|
* from the slices under `./store/` (zustand's slices pattern). The split is
|
|
@@ -6844,8 +6698,7 @@ function useAppCapability(privilege) {
|
|
|
6844
6698
|
reason: appPrivilegeReason(capabilities, privilege)
|
|
6845
6699
|
};
|
|
6846
6700
|
}
|
|
6847
|
-
|
|
6848
|
-
//#region src/selection-actions.ts
|
|
6701
|
+
// src/selection-actions.ts
|
|
6849
6702
|
/**
|
|
6850
6703
|
* Store-touching selection helpers. Kept out of `selection.ts` so that module
|
|
6851
6704
|
* stays a pure, directly testable set of functions over id arrays.
|
|
@@ -6873,8 +6726,7 @@ function applyMatchedSelection(targetLayerId, matchedIds, mode) {
|
|
|
6873
6726
|
store.selectFeatures(next);
|
|
6874
6727
|
return next.length;
|
|
6875
6728
|
}
|
|
6876
|
-
|
|
6877
|
-
//#region src/scale-units.ts
|
|
6729
|
+
// src/scale-units.ts
|
|
6878
6730
|
/** Conversion constants shared by every scale-bar denomination. */
|
|
6879
6731
|
const FEET_PER_METER = 3.2808398950131235;
|
|
6880
6732
|
const METERS_PER_FOOT = .3048;
|
|
@@ -6938,8 +6790,7 @@ function scaleSpan(maxMeters, unit) {
|
|
|
6938
6790
|
label
|
|
6939
6791
|
};
|
|
6940
6792
|
}
|
|
6941
|
-
|
|
6942
|
-
//#region src/elevation.ts
|
|
6793
|
+
// src/elevation.ts
|
|
6943
6794
|
/** Open-Meteo accepts at most 100 coordinates per elevation request. */
|
|
6944
6795
|
const MAX_POINTS_PER_REQUEST = 100;
|
|
6945
6796
|
/** Abort an elevation request that has not responded within this window. */
|
|
@@ -7137,8 +6988,7 @@ function createPointerElevationResolver(options) {
|
|
|
7137
6988
|
dispose: invalidate
|
|
7138
6989
|
};
|
|
7139
6990
|
}
|
|
7140
|
-
|
|
7141
|
-
//#region src/camera-altitude.ts
|
|
6991
|
+
// src/camera-altitude.ts
|
|
7142
6992
|
/**
|
|
7143
6993
|
* Camera altitude ("Eye alt") for the status bar — issue #1816.
|
|
7144
6994
|
*
|
|
@@ -7185,8 +7035,7 @@ function formatCameraAltitude(meters, unit) {
|
|
|
7185
7035
|
maximumFractionDigits: digits
|
|
7186
7036
|
})} ${label}`;
|
|
7187
7037
|
}
|
|
7188
|
-
|
|
7189
|
-
//#region src/layers-file.ts
|
|
7038
|
+
// src/layers-file.ts
|
|
7190
7039
|
/** `type` tag identifying a layers file. */
|
|
7191
7040
|
const LAYERS_FILE_TYPE = "geolibre-layers";
|
|
7192
7041
|
/** Format version written by {@link serializeLayersFile}. */
|
|
@@ -7392,8 +7241,7 @@ function addLayersToProject(project, content) {
|
|
|
7392
7241
|
layerGroups: [...groups, ...structuredClone(layerGroups)]
|
|
7393
7242
|
};
|
|
7394
7243
|
}
|
|
7395
|
-
|
|
7396
|
-
//#region src/pixel-format.ts
|
|
7244
|
+
// src/pixel-format.ts
|
|
7397
7245
|
/**
|
|
7398
7246
|
* Trim a float sample to something readable. A 32-bit raster value decoded to a
|
|
7399
7247
|
* JS double prints all 17 digits of its binary representation
|
|
@@ -7409,8 +7257,7 @@ function formatPixelValue(value) {
|
|
|
7409
7257
|
if (Number.isInteger(value)) return String(value);
|
|
7410
7258
|
return String(Number(value.toPrecision(6)));
|
|
7411
7259
|
}
|
|
7412
|
-
|
|
7413
|
-
//#region src/s3.ts
|
|
7260
|
+
// src/s3.ts
|
|
7414
7261
|
/** SigV4 allows a presigned URL to live at most seven days. */
|
|
7415
7262
|
const S3_MAX_PRESIGN_SECONDS = 604800;
|
|
7416
7263
|
const S3_SCHEME = /^s3a?:\/\//i;
|
|
@@ -7811,8 +7658,7 @@ async function explainS3ReadError(url, error, translate) {
|
|
|
7811
7658
|
origin
|
|
7812
7659
|
}) : fallback, location.bucket, origin, error);
|
|
7813
7660
|
}
|
|
7814
|
-
|
|
7815
|
-
//#region src/storymap-sample.ts
|
|
7661
|
+
// src/storymap-sample.ts
|
|
7816
7662
|
const SAMPLE_ASSET_BASE = "https://opengeos.org/maplibre-gl-storymaps/assets";
|
|
7817
7663
|
/**
|
|
7818
7664
|
* Build a ready-to-play sample story map.
|
|
@@ -7931,8 +7777,7 @@ function createSampleStoryMap() {
|
|
|
7931
7777
|
]
|
|
7932
7778
|
};
|
|
7933
7779
|
}
|
|
7934
|
-
|
|
7935
|
-
//#region src/storymap-playback.ts
|
|
7780
|
+
// src/storymap-playback.ts
|
|
7936
7781
|
/** The clamped opacity recorded for a layer, or undefined when untouched. */
|
|
7937
7782
|
function recordedStoryOpacity(opacities, layerId) {
|
|
7938
7783
|
const value = opacities?.[layerId];
|
|
@@ -8018,8 +7863,7 @@ function storyLocationView(location, current) {
|
|
|
8018
7863
|
bearing: location.bearing ?? current.bearing
|
|
8019
7864
|
};
|
|
8020
7865
|
}
|
|
8021
|
-
|
|
8022
|
-
//#region src/storymap-io.ts
|
|
7866
|
+
// src/storymap-io.ts
|
|
8023
7867
|
/**
|
|
8024
7868
|
* Serialize a story map to pretty-printed JSON for export.
|
|
8025
7869
|
*
|
|
@@ -8062,7 +7906,8 @@ const CSV_HEADERS = [
|
|
|
8062
7906
|
"mapAnimation",
|
|
8063
7907
|
"rotateAnimation",
|
|
8064
7908
|
"onChapterEnter",
|
|
8065
|
-
"onChapterExit"
|
|
7909
|
+
"onChapterExit",
|
|
7910
|
+
"durationSeconds"
|
|
8066
7911
|
];
|
|
8067
7912
|
/**
|
|
8068
7913
|
* Serialize a story map's chapters to CSV (one row per chapter).
|
|
@@ -8090,7 +7935,8 @@ function serializeStoryMapCsv(storymap) {
|
|
|
8090
7935
|
c.mapAnimation,
|
|
8091
7936
|
String(c.rotateAnimation),
|
|
8092
7937
|
JSON.stringify(c.onChapterEnter),
|
|
8093
|
-
JSON.stringify(c.onChapterExit)
|
|
7938
|
+
JSON.stringify(c.onChapterExit),
|
|
7939
|
+
String(c.durationSeconds ?? "")
|
|
8094
7940
|
].map(csvEscape).join(","));
|
|
8095
7941
|
return rows.join("\n") + "\n";
|
|
8096
7942
|
}
|
|
@@ -8145,6 +7991,7 @@ function parseStoryMapCsv(text, base) {
|
|
|
8145
7991
|
},
|
|
8146
7992
|
mapAnimation: get("mapanimation").trim() || "flyTo",
|
|
8147
7993
|
rotateAnimation: bool("rotateanimation"),
|
|
7994
|
+
durationSeconds: get("durationseconds").trim() ? Number(get("durationseconds")) : void 0,
|
|
8148
7995
|
onChapterEnter: jsonArray("onchapterenter"),
|
|
8149
7996
|
onChapterExit: jsonArray("onchapterexit")
|
|
8150
7997
|
};
|
|
@@ -8194,8 +8041,7 @@ function parseCsvRows(text) {
|
|
|
8194
8041
|
}
|
|
8195
8042
|
return rows;
|
|
8196
8043
|
}
|
|
8197
|
-
|
|
8198
|
-
//#region src/layer-selectors.ts
|
|
8044
|
+
// src/layer-selectors.ts
|
|
8199
8045
|
/**
|
|
8200
8046
|
* Narrow subscriptions to the store's `layers` array.
|
|
8201
8047
|
*
|
|
@@ -8336,816 +8182,7 @@ function useLayerSummaries() {
|
|
|
8336
8182
|
function useLayersWhen(active) {
|
|
8337
8183
|
return useAppStore(selectLayersWhen(active));
|
|
8338
8184
|
}
|
|
8339
|
-
|
|
8340
|
-
//#region src/geocoding.ts
|
|
8341
|
-
/**
|
|
8342
|
-
* Geocoding client and pure helpers shared by the batch-geocode dialog and the
|
|
8343
|
-
* reverse-geocode plugin.
|
|
8344
|
-
*
|
|
8345
|
-
* This module lives in `@geolibre/core` rather than `@geolibre/processing`
|
|
8346
|
-
* because `@geolibre/plugins` depends on core but not on processing, and the
|
|
8347
|
-
* reverse-geocode plugin needs the same client. The pure helpers (URL builders,
|
|
8348
|
-
* result mappers, pacing) carry no React or MapLibre dependency so they can be
|
|
8349
|
-
* unit-tested without a browser or network.
|
|
8350
|
-
*
|
|
8351
|
-
* Providers: geocoding is dispatched through a small {@link GeocodingProvider}
|
|
8352
|
-
* registry so alternatives to Nominatim (ArcGIS World Geocoder, CartoCiudad, Mapbox,
|
|
8353
|
-
* Pelias, Google) can be selected per project. Each provider builds its own request
|
|
8354
|
-
* URLs and normalizes its response into a {@link GeocodeMatch} (forward) or a
|
|
8355
|
-
* {@link ReverseGeocodeDisplay} (reverse), so the dialog and plugin stay
|
|
8356
|
-
* provider-agnostic. Nominatim is the default.
|
|
8357
|
-
*
|
|
8358
|
-
* The 1 request/second throttle and the row cap are part of Nominatim's public
|
|
8359
|
-
* usage policy and are therefore applied ONLY to the default public host; a
|
|
8360
|
-
* self-hosted endpoint relaxes both, and keyed providers (Mapbox/ArcGIS/Google)
|
|
8361
|
-
* are paced by their own quotas, not by us.
|
|
8362
|
-
*
|
|
8363
|
-
* Browser fetch cannot set `User-Agent`/`Referer`, so the app is identified to
|
|
8364
|
-
* Nominatim via the optional `email` query parameter plus the automatically
|
|
8365
|
-
* sent `Referer`. The desktop build overrides this with a native (Tauri) fetch
|
|
8366
|
-
* via {@link setGeocodingFetch} — see the note there. See
|
|
8367
|
-
* docs/user-guide/data-integrations.md#geocoding.
|
|
8368
|
-
*/
|
|
8369
|
-
const DEFAULT_FORWARD_GEOCODE_ENDPOINT = "https://nominatim.openstreetmap.org/search";
|
|
8370
|
-
const DEFAULT_REVERSE_GEOCODE_ENDPOINT = "https://nominatim.openstreetmap.org/reverse";
|
|
8371
|
-
/** Host whose public usage policy (1 req/sec, bulk limits) we must respect. */
|
|
8372
|
-
const NOMINATIM_PUBLIC_HOST = "nominatim.openstreetmap.org";
|
|
8373
|
-
/** Minimum spacing between requests to the public Nominatim endpoint. */
|
|
8374
|
-
const NOMINATIM_MIN_INTERVAL_MS = 1100;
|
|
8375
|
-
/** Host of the free, unkeyed public CartoCiudad geocoder (IGN/CNIG). */
|
|
8376
|
-
const CARTOCIUDAD_PUBLIC_HOST = "cartociudad.es";
|
|
8377
|
-
/**
|
|
8378
|
-
* Courtesy spacing (~5 req/sec) between requests to the public CartoCiudad
|
|
8379
|
-
* endpoint. Unlike {@link NOMINATIM_MIN_INTERVAL_MS} this is not a published
|
|
8380
|
-
* policy — IGN documents no rate limit — it is our own conservative default so
|
|
8381
|
-
* a large batch does not burst at a free public government service. See
|
|
8382
|
-
* {@link geocoderMinIntervalMs}.
|
|
8383
|
-
*/
|
|
8384
|
-
const CARTOCIUDAD_MIN_INTERVAL_MS = 200;
|
|
8385
|
-
/** Max rows a single batch run will geocode against the public endpoint. */
|
|
8386
|
-
const PUBLIC_GEOCODE_ROW_CAP = 1e3;
|
|
8387
|
-
/** Property keys added to each geocoded feature. */
|
|
8388
|
-
const GEOCODE_LAT_KEY = "geocode_lat";
|
|
8389
|
-
const GEOCODE_LON_KEY = "geocode_lon";
|
|
8390
|
-
const GEOCODE_DISPLAY_NAME_KEY = "geocode_display_name";
|
|
8391
|
-
const GEOCODE_SCORE_KEY = "geocode_importance";
|
|
8392
|
-
/** Provider id that produced (or failed to produce) a match, when stamped. */
|
|
8393
|
-
const GEOCODE_PROVIDER_KEY = "geocode_provider";
|
|
8394
|
-
/** Whether a row matched, when stamped. See {@link GeocodeStatus}. */
|
|
8395
|
-
const GEOCODE_STATUS_KEY = "geocode_status";
|
|
8396
|
-
/** The provider used when none is configured. */
|
|
8397
|
-
const DEFAULT_GEOCODING_PROVIDER_ID = "nominatim";
|
|
8398
|
-
function coerceScore(value) {
|
|
8399
|
-
if (value === void 0 || value === null || value === "") return null;
|
|
8400
|
-
const num = Number(value);
|
|
8401
|
-
return Number.isFinite(num) ? num : null;
|
|
8402
|
-
}
|
|
8403
|
-
/** Append `base` to `existing`, suffixing `_2`, `_3`, ... if the key collides. */
|
|
8404
|
-
function uniqueKey(base, existing) {
|
|
8405
|
-
if (!(base in existing)) return base;
|
|
8406
|
-
let suffix = 2;
|
|
8407
|
-
while (`${base}_${suffix}` in existing) suffix += 1;
|
|
8408
|
-
return `${base}_${suffix}`;
|
|
8409
|
-
}
|
|
8410
|
-
/**
|
|
8411
|
-
* Coerce an address-parts record to `Record<string, string>`. Provider address
|
|
8412
|
-
* objects can carry numbers (ArcGIS `Score`/`X`/`Y`, Pelias coordinates), so
|
|
8413
|
-
* values are stringified rather than unsafely cast; null/undefined are dropped.
|
|
8414
|
-
*/
|
|
8415
|
-
function stringifyParts(obj) {
|
|
8416
|
-
const parts = {};
|
|
8417
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
8418
|
-
if (value === null || value === void 0) continue;
|
|
8419
|
-
parts[key] = typeof value === "string" ? value : String(value);
|
|
8420
|
-
}
|
|
8421
|
-
return parts;
|
|
8422
|
-
}
|
|
8423
|
-
/** Read a string property off an unknown object, or undefined. */
|
|
8424
|
-
function readString(obj, key) {
|
|
8425
|
-
if (obj && typeof obj === "object" && key in obj) {
|
|
8426
|
-
const value = obj[key];
|
|
8427
|
-
if (typeof value === "string") return value;
|
|
8428
|
-
if (typeof value === "number") return String(value);
|
|
8429
|
-
}
|
|
8430
|
-
}
|
|
8431
|
-
/** Build a Nominatim forward-geocoding URL (jsonv2, address details on). */
|
|
8432
|
-
function buildForwardGeocodeUrl(endpoint, query, options = {}) {
|
|
8433
|
-
const url = new URL(endpoint);
|
|
8434
|
-
url.searchParams.set("q", query);
|
|
8435
|
-
url.searchParams.set("format", "jsonv2");
|
|
8436
|
-
url.searchParams.set("addressdetails", "1");
|
|
8437
|
-
url.searchParams.set("limit", String(options.limit ?? 1));
|
|
8438
|
-
if (options.email) url.searchParams.set("email", options.email);
|
|
8439
|
-
return url.toString();
|
|
8440
|
-
}
|
|
8441
|
-
/** Build a Nominatim reverse-geocoding URL (jsonv2, address details on). */
|
|
8442
|
-
function buildReverseGeocodeUrl(endpoint, lon, lat, options = {}) {
|
|
8443
|
-
const url = new URL(endpoint);
|
|
8444
|
-
url.searchParams.set("lat", String(lat));
|
|
8445
|
-
url.searchParams.set("lon", String(lon));
|
|
8446
|
-
url.searchParams.set("format", "jsonv2");
|
|
8447
|
-
url.searchParams.set("addressdetails", "1");
|
|
8448
|
-
if (options.zoom !== void 0) url.searchParams.set("zoom", String(options.zoom));
|
|
8449
|
-
if (options.email) url.searchParams.set("email", options.email);
|
|
8450
|
-
return url.toString();
|
|
8451
|
-
}
|
|
8452
|
-
/** Map one Nominatim forward result onto a normalized match, or null. */
|
|
8453
|
-
function nominatimForwardResultToMatch(result) {
|
|
8454
|
-
const lat = Number(result.lat);
|
|
8455
|
-
const lon = Number(result.lon);
|
|
8456
|
-
if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
|
|
8457
|
-
return {
|
|
8458
|
-
lat,
|
|
8459
|
-
lon,
|
|
8460
|
-
displayName: result.display_name ?? "",
|
|
8461
|
-
score: coerceScore(result.importance)
|
|
8462
|
-
};
|
|
8463
|
-
}
|
|
8464
|
-
/**
|
|
8465
|
-
* Convert a normalized {@link GeocodeMatch} into a point Feature whose
|
|
8466
|
-
* properties carry the original CSV row plus `geocode_lat`/`geocode_lon`/
|
|
8467
|
-
* `geocode_display_name`/`geocode_importance`. The added keys are de-duplicated
|
|
8468
|
-
* against the original columns so an existing `geocode_lat` is not clobbered.
|
|
8469
|
-
* Geometry coordinates are `[lon, lat]`. Returns null when the match has no
|
|
8470
|
-
* finite coordinates.
|
|
8471
|
-
*
|
|
8472
|
-
* `extra.providerId`, when passed, also stamps `geocode_provider` and
|
|
8473
|
-
* `geocode_status: "matched"` (dropped when omitted, so the existing
|
|
8474
|
-
* `GeocodeDialog` call site keeps its current output unchanged).
|
|
8475
|
-
*/
|
|
8476
|
-
function geocodeMatchToFeature(match, originalRow = {}, extra) {
|
|
8477
|
-
if (!Number.isFinite(match.lat) || !Number.isFinite(match.lon)) return null;
|
|
8478
|
-
const properties = { ...originalRow };
|
|
8479
|
-
const added = {
|
|
8480
|
-
[GEOCODE_LAT_KEY]: match.lat,
|
|
8481
|
-
[GEOCODE_LON_KEY]: match.lon,
|
|
8482
|
-
[GEOCODE_DISPLAY_NAME_KEY]: match.displayName ?? "",
|
|
8483
|
-
[GEOCODE_SCORE_KEY]: match.score
|
|
8484
|
-
};
|
|
8485
|
-
if (extra?.providerId) {
|
|
8486
|
-
added[GEOCODE_PROVIDER_KEY] = extra.providerId;
|
|
8487
|
-
added[GEOCODE_STATUS_KEY] = "matched";
|
|
8488
|
-
}
|
|
8489
|
-
for (const [key, value] of Object.entries(added)) properties[uniqueKey(key, properties)] = value;
|
|
8490
|
-
return {
|
|
8491
|
-
type: "Feature",
|
|
8492
|
-
geometry: {
|
|
8493
|
-
type: "Point",
|
|
8494
|
-
coordinates: [match.lon, match.lat]
|
|
8495
|
-
},
|
|
8496
|
-
properties
|
|
8497
|
-
};
|
|
8498
|
-
}
|
|
8499
|
-
/**
|
|
8500
|
-
* Build a null-geometry Feature for a CSV row that could not be geocoded, so
|
|
8501
|
-
* it is kept (not silently dropped) alongside the matched point features.
|
|
8502
|
-
* Mirrors the null-geometry shape {@link parseDelimitedTextLayer} already uses
|
|
8503
|
-
* for a non-spatial attribute table. Stamps `geocode_status: "unmatched"` and
|
|
8504
|
-
* `geocode_provider`, de-duplicated against the original columns the same way
|
|
8505
|
-
* {@link geocodeMatchToFeature} does.
|
|
8506
|
-
*/
|
|
8507
|
-
function unmatchedGeocodeFeature(originalRow, providerId) {
|
|
8508
|
-
const properties = { ...originalRow };
|
|
8509
|
-
const added = {
|
|
8510
|
-
[GEOCODE_STATUS_KEY]: "unmatched",
|
|
8511
|
-
[GEOCODE_PROVIDER_KEY]: providerId
|
|
8512
|
-
};
|
|
8513
|
-
for (const [key, value] of Object.entries(added)) properties[uniqueKey(key, properties)] = value;
|
|
8514
|
-
return {
|
|
8515
|
-
type: "Feature",
|
|
8516
|
-
geometry: null,
|
|
8517
|
-
properties
|
|
8518
|
-
};
|
|
8519
|
-
}
|
|
8520
|
-
/**
|
|
8521
|
-
* Convert a Nominatim forward result into a point Feature. Retained as a thin
|
|
8522
|
-
* wrapper over {@link geocodeMatchToFeature} for callers and tests that work
|
|
8523
|
-
* directly with Nominatim results. Returns null when the result has no finite
|
|
8524
|
-
* coordinates.
|
|
8525
|
-
*/
|
|
8526
|
-
function nominatimResultToFeature(result, originalRow = {}) {
|
|
8527
|
-
const match = nominatimForwardResultToMatch(result);
|
|
8528
|
-
return match ? geocodeMatchToFeature(match, originalRow) : null;
|
|
8529
|
-
}
|
|
8530
|
-
/**
|
|
8531
|
-
* Resolve a Nominatim reverse result to a display string and address parts, or
|
|
8532
|
-
* null when the point could not be reverse-geocoded.
|
|
8533
|
-
*/
|
|
8534
|
-
function nominatimReverseResultToDisplay(result) {
|
|
8535
|
-
if (!result || result.error) return null;
|
|
8536
|
-
const displayName = result.display_name?.trim();
|
|
8537
|
-
if (!displayName) return null;
|
|
8538
|
-
return {
|
|
8539
|
-
displayName,
|
|
8540
|
-
parts: result.address ?? {}
|
|
8541
|
-
};
|
|
8542
|
-
}
|
|
8543
|
-
const nominatimProvider = {
|
|
8544
|
-
id: "nominatim",
|
|
8545
|
-
label: "Nominatim (OpenStreetMap)",
|
|
8546
|
-
forward: true,
|
|
8547
|
-
reverse: true,
|
|
8548
|
-
requiresApiKey: false,
|
|
8549
|
-
acceptsApiKey: false,
|
|
8550
|
-
defaultForwardEndpoint: DEFAULT_FORWARD_GEOCODE_ENDPOINT,
|
|
8551
|
-
defaultReverseEndpoint: DEFAULT_REVERSE_GEOCODE_ENDPOINT,
|
|
8552
|
-
buildForwardUrl: (config, query, options) => buildForwardGeocodeUrl(config.forwardEndpoint, query, {
|
|
8553
|
-
email: options.email,
|
|
8554
|
-
limit: options.limit
|
|
8555
|
-
}),
|
|
8556
|
-
parseForward: (data) => Array.isArray(data) ? data.map(nominatimForwardResultToMatch).filter((m) => m !== null) : [],
|
|
8557
|
-
buildReverseUrl: (config, lon, lat, options) => buildReverseGeocodeUrl(config.reverseEndpoint, lon, lat, {
|
|
8558
|
-
email: options.email,
|
|
8559
|
-
zoom: options.zoom
|
|
8560
|
-
}),
|
|
8561
|
-
parseReverse: (data) => nominatimReverseResultToDisplay(data && typeof data === "object" ? data : null)
|
|
8562
|
-
};
|
|
8563
|
-
/** Read a GeoJSON FeatureCollection's features array, or []. */
|
|
8564
|
-
function geojsonFeatures(data) {
|
|
8565
|
-
if (data && typeof data === "object" && Array.isArray(data.features)) return data.features.filter((f) => !!f && typeof f === "object");
|
|
8566
|
-
return [];
|
|
8567
|
-
}
|
|
8568
|
-
/** Pull `[lon, lat]` from a GeoJSON Point geometry, or null. */
|
|
8569
|
-
function pointCoords(feature) {
|
|
8570
|
-
const coords = feature.geometry?.coordinates;
|
|
8571
|
-
if (Array.isArray(coords) && coords.length >= 2) {
|
|
8572
|
-
const lon = Number(coords[0]);
|
|
8573
|
-
const lat = Number(coords[1]);
|
|
8574
|
-
if (Number.isFinite(lon) && Number.isFinite(lat)) return [lon, lat];
|
|
8575
|
-
}
|
|
8576
|
-
return null;
|
|
8577
|
-
}
|
|
8578
|
-
const peliasProvider = {
|
|
8579
|
-
id: "pelias",
|
|
8580
|
-
label: "Pelias",
|
|
8581
|
-
forward: true,
|
|
8582
|
-
reverse: true,
|
|
8583
|
-
requiresApiKey: false,
|
|
8584
|
-
acceptsApiKey: true,
|
|
8585
|
-
defaultForwardEndpoint: "https://api.geocode.earth/v1/search",
|
|
8586
|
-
defaultReverseEndpoint: "https://api.geocode.earth/v1/reverse",
|
|
8587
|
-
buildForwardUrl: (config, query, options) => {
|
|
8588
|
-
const url = new URL(config.forwardEndpoint);
|
|
8589
|
-
url.searchParams.set("text", query);
|
|
8590
|
-
if (options.limit) url.searchParams.set("size", String(options.limit));
|
|
8591
|
-
if (config.apiKey) url.searchParams.set("api_key", config.apiKey);
|
|
8592
|
-
return url.toString();
|
|
8593
|
-
},
|
|
8594
|
-
parseForward: (data) => geojsonFeatures(data).map((feature) => {
|
|
8595
|
-
const coords = pointCoords(feature);
|
|
8596
|
-
if (!coords) return null;
|
|
8597
|
-
const props = feature.properties ?? {};
|
|
8598
|
-
return {
|
|
8599
|
-
lon: coords[0],
|
|
8600
|
-
lat: coords[1],
|
|
8601
|
-
displayName: readString(props, "label") ?? "",
|
|
8602
|
-
score: coerceScore(props.confidence)
|
|
8603
|
-
};
|
|
8604
|
-
}).filter((m) => m !== null),
|
|
8605
|
-
buildReverseUrl: (config, lon, lat) => {
|
|
8606
|
-
const url = new URL(config.reverseEndpoint);
|
|
8607
|
-
url.searchParams.set("point.lat", String(lat));
|
|
8608
|
-
url.searchParams.set("point.lon", String(lon));
|
|
8609
|
-
if (config.apiKey) url.searchParams.set("api_key", config.apiKey);
|
|
8610
|
-
return url.toString();
|
|
8611
|
-
},
|
|
8612
|
-
parseReverse: (data) => {
|
|
8613
|
-
const feature = geojsonFeatures(data)[0];
|
|
8614
|
-
if (!feature) return null;
|
|
8615
|
-
const props = feature.properties ?? {};
|
|
8616
|
-
const displayName = readString(props, "label")?.trim();
|
|
8617
|
-
return displayName ? {
|
|
8618
|
-
displayName,
|
|
8619
|
-
parts: stringifyParts(props)
|
|
8620
|
-
} : null;
|
|
8621
|
-
}
|
|
8622
|
-
};
|
|
8623
|
-
const arcgisProvider = {
|
|
8624
|
-
id: "arcgis",
|
|
8625
|
-
label: "ArcGIS World Geocoder",
|
|
8626
|
-
forward: true,
|
|
8627
|
-
reverse: true,
|
|
8628
|
-
requiresApiKey: true,
|
|
8629
|
-
acceptsApiKey: true,
|
|
8630
|
-
defaultForwardEndpoint: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates",
|
|
8631
|
-
defaultReverseEndpoint: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode",
|
|
8632
|
-
buildForwardUrl: (config, query, options) => {
|
|
8633
|
-
const url = new URL(config.forwardEndpoint);
|
|
8634
|
-
url.searchParams.set("SingleLine", query);
|
|
8635
|
-
url.searchParams.set("f", "json");
|
|
8636
|
-
url.searchParams.set("outFields", "Match_addr");
|
|
8637
|
-
if (options.limit) url.searchParams.set("maxLocations", String(options.limit));
|
|
8638
|
-
if (config.apiKey) url.searchParams.set("token", config.apiKey);
|
|
8639
|
-
return url.toString();
|
|
8640
|
-
},
|
|
8641
|
-
parseForward: (data) => {
|
|
8642
|
-
return (data && typeof data === "object" && Array.isArray(data.candidates) ? data.candidates : []).map((candidate) => {
|
|
8643
|
-
const location = candidate.location;
|
|
8644
|
-
const lon = Number(location?.x);
|
|
8645
|
-
const lat = Number(location?.y);
|
|
8646
|
-
if (!Number.isFinite(lon) || !Number.isFinite(lat)) return null;
|
|
8647
|
-
return {
|
|
8648
|
-
lon,
|
|
8649
|
-
lat,
|
|
8650
|
-
displayName: readString(candidate, "address") ?? "",
|
|
8651
|
-
score: coerceScore(candidate.score)
|
|
8652
|
-
};
|
|
8653
|
-
}).filter((m) => m !== null);
|
|
8654
|
-
},
|
|
8655
|
-
buildReverseUrl: (config, lon, lat) => {
|
|
8656
|
-
const url = new URL(config.reverseEndpoint);
|
|
8657
|
-
url.searchParams.set("location", `${lon},${lat}`);
|
|
8658
|
-
url.searchParams.set("f", "json");
|
|
8659
|
-
if (config.apiKey) url.searchParams.set("token", config.apiKey);
|
|
8660
|
-
return url.toString();
|
|
8661
|
-
},
|
|
8662
|
-
parseReverse: (data) => {
|
|
8663
|
-
const address = data && typeof data === "object" ? data.address : void 0;
|
|
8664
|
-
if (!address || typeof address !== "object") return null;
|
|
8665
|
-
const displayName = (readString(address, "LongLabel") ?? readString(address, "Match_addr"))?.trim();
|
|
8666
|
-
return displayName ? {
|
|
8667
|
-
displayName,
|
|
8668
|
-
parts: stringifyParts(address)
|
|
8669
|
-
} : null;
|
|
8670
|
-
}
|
|
8671
|
-
};
|
|
8672
|
-
const mapboxProvider = {
|
|
8673
|
-
id: "mapbox",
|
|
8674
|
-
label: "Mapbox",
|
|
8675
|
-
forward: true,
|
|
8676
|
-
reverse: true,
|
|
8677
|
-
requiresApiKey: true,
|
|
8678
|
-
acceptsApiKey: true,
|
|
8679
|
-
defaultForwardEndpoint: "https://api.mapbox.com/geocoding/v5/mapbox.places",
|
|
8680
|
-
defaultReverseEndpoint: "https://api.mapbox.com/geocoding/v5/mapbox.places",
|
|
8681
|
-
buildForwardUrl: (config, query, options) => {
|
|
8682
|
-
const base = config.forwardEndpoint.replace(/\/+$/, "");
|
|
8683
|
-
const url = new URL(`${base}/${encodeURIComponent(query)}.json`);
|
|
8684
|
-
if (options.limit) url.searchParams.set("limit", String(options.limit));
|
|
8685
|
-
if (config.apiKey) url.searchParams.set("access_token", config.apiKey);
|
|
8686
|
-
return url.toString();
|
|
8687
|
-
},
|
|
8688
|
-
parseForward: (data) => geojsonFeatures(data).map((feature) => {
|
|
8689
|
-
const center = feature.center;
|
|
8690
|
-
let coords = null;
|
|
8691
|
-
if (Array.isArray(center) && center.length >= 2) {
|
|
8692
|
-
const lon = Number(center[0]);
|
|
8693
|
-
const lat = Number(center[1]);
|
|
8694
|
-
if (Number.isFinite(lon) && Number.isFinite(lat)) coords = [lon, lat];
|
|
8695
|
-
}
|
|
8696
|
-
coords ??= pointCoords(feature);
|
|
8697
|
-
if (!coords) return null;
|
|
8698
|
-
return {
|
|
8699
|
-
lon: coords[0],
|
|
8700
|
-
lat: coords[1],
|
|
8701
|
-
displayName: readString(feature, "place_name") ?? "",
|
|
8702
|
-
score: coerceScore(feature.relevance)
|
|
8703
|
-
};
|
|
8704
|
-
}).filter((m) => m !== null),
|
|
8705
|
-
buildReverseUrl: (config, lon, lat) => {
|
|
8706
|
-
const base = config.reverseEndpoint.replace(/\/+$/, "");
|
|
8707
|
-
const url = new URL(`${base}/${lon},${lat}.json`);
|
|
8708
|
-
if (config.apiKey) url.searchParams.set("access_token", config.apiKey);
|
|
8709
|
-
return url.toString();
|
|
8710
|
-
},
|
|
8711
|
-
parseReverse: (data) => {
|
|
8712
|
-
const feature = geojsonFeatures(data)[0];
|
|
8713
|
-
if (!feature) return null;
|
|
8714
|
-
const displayName = readString(feature, "place_name")?.trim();
|
|
8715
|
-
return displayName ? {
|
|
8716
|
-
displayName,
|
|
8717
|
-
parts: stringifyParts(feature.properties ?? {})
|
|
8718
|
-
} : null;
|
|
8719
|
-
}
|
|
8720
|
-
};
|
|
8721
|
-
/**
|
|
8722
|
-
* Detect a Google Geocoding API error embedded in an HTTP 200 body. Google v3
|
|
8723
|
-
* returns REQUEST_DENIED / OVER_QUERY_LIMIT / INVALID_REQUEST and friends with
|
|
8724
|
-
* a 200 status and the failure only in the `status` field, so `response.ok`
|
|
8725
|
-
* alone would silently turn those into empty results. Returns null for OK and
|
|
8726
|
-
* ZERO_RESULTS (a successful empty match).
|
|
8727
|
-
*/
|
|
8728
|
-
function googleErrorMessage(data) {
|
|
8729
|
-
const status = readString(data, "status");
|
|
8730
|
-
if (!status || status === "OK" || status === "ZERO_RESULTS") return null;
|
|
8731
|
-
const detail = readString(data, "error_message");
|
|
8732
|
-
return detail ? `Google geocoder error: ${status} - ${detail}` : `Google geocoder error: ${status}`;
|
|
8733
|
-
}
|
|
8734
|
-
const googleProvider = {
|
|
8735
|
-
id: "google",
|
|
8736
|
-
label: "Google",
|
|
8737
|
-
forward: true,
|
|
8738
|
-
reverse: true,
|
|
8739
|
-
requiresApiKey: true,
|
|
8740
|
-
acceptsApiKey: true,
|
|
8741
|
-
browserCorsRestricted: true,
|
|
8742
|
-
defaultForwardEndpoint: "https://maps.googleapis.com/maps/api/geocode/json",
|
|
8743
|
-
defaultReverseEndpoint: "https://maps.googleapis.com/maps/api/geocode/json",
|
|
8744
|
-
buildForwardUrl: (config, query) => {
|
|
8745
|
-
const url = new URL(config.forwardEndpoint);
|
|
8746
|
-
url.searchParams.set("address", query);
|
|
8747
|
-
if (config.apiKey) url.searchParams.set("key", config.apiKey);
|
|
8748
|
-
return url.toString();
|
|
8749
|
-
},
|
|
8750
|
-
parseForward: (data) => {
|
|
8751
|
-
const error = googleErrorMessage(data);
|
|
8752
|
-
if (error) throw new Error(error);
|
|
8753
|
-
return parseGoogleResults(data);
|
|
8754
|
-
},
|
|
8755
|
-
buildReverseUrl: (config, lon, lat) => {
|
|
8756
|
-
const url = new URL(config.reverseEndpoint);
|
|
8757
|
-
url.searchParams.set("latlng", `${lat},${lon}`);
|
|
8758
|
-
if (config.apiKey) url.searchParams.set("key", config.apiKey);
|
|
8759
|
-
return url.toString();
|
|
8760
|
-
},
|
|
8761
|
-
parseReverse: (data) => {
|
|
8762
|
-
const error = googleErrorMessage(data);
|
|
8763
|
-
if (error) throw new Error(error);
|
|
8764
|
-
const displayName = readString((data && typeof data === "object" && Array.isArray(data.results) ? data.results : [])[0], "formatted_address")?.trim();
|
|
8765
|
-
return displayName ? {
|
|
8766
|
-
displayName,
|
|
8767
|
-
parts: {}
|
|
8768
|
-
} : null;
|
|
8769
|
-
}
|
|
8770
|
-
};
|
|
8771
|
-
/** Map a Google Geocoding API `results` array onto normalized matches. */
|
|
8772
|
-
function parseGoogleResults(data) {
|
|
8773
|
-
return (data && typeof data === "object" && Array.isArray(data.results) ? data.results : []).map((result) => {
|
|
8774
|
-
const location = result.geometry?.location;
|
|
8775
|
-
const lat = Number(location?.lat);
|
|
8776
|
-
const lon = Number(location?.lng);
|
|
8777
|
-
if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
|
|
8778
|
-
return {
|
|
8779
|
-
lat,
|
|
8780
|
-
lon,
|
|
8781
|
-
displayName: readString(result, "formatted_address") ?? "",
|
|
8782
|
-
score: null
|
|
8783
|
-
};
|
|
8784
|
-
}).filter((m) => m !== null);
|
|
8785
|
-
}
|
|
8786
|
-
/**
|
|
8787
|
-
* Read a CartoCiudad `lat`/`lng` field as a finite number, or null when the
|
|
8788
|
-
* field is absent, blank, or not numeric (`"NaN"` and `"invalid"` included).
|
|
8789
|
-
* Guarding the raw value matters because `Number(null)` is 0, which would turn
|
|
8790
|
-
* a coordinate-less response into a match in the Gulf of Guinea.
|
|
8791
|
-
*/
|
|
8792
|
-
function cartociudadCoordinate(value) {
|
|
8793
|
-
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
8794
|
-
if (typeof value !== "string" || !value.trim()) return null;
|
|
8795
|
-
const parsed = Number(value);
|
|
8796
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
8797
|
-
}
|
|
8798
|
-
/** Validated WGS84 position for a result, or null when it carries none. */
|
|
8799
|
-
function cartociudadCoords(r) {
|
|
8800
|
-
const lat = cartociudadCoordinate(r.lat);
|
|
8801
|
-
const lon = cartociudadCoordinate(r.lng);
|
|
8802
|
-
if (lat === null || lon === null) return null;
|
|
8803
|
-
if (lat < -90 || lat > 90 || lon < -180 || lon > 180) return null;
|
|
8804
|
-
return {
|
|
8805
|
-
lat,
|
|
8806
|
-
lon
|
|
8807
|
-
};
|
|
8808
|
-
}
|
|
8809
|
-
/** Default endpoints for the public CartoCiudad REST API (no auth required). */
|
|
8810
|
-
const CARTOCIUDAD_FORWARD_ENDPOINT = "https://www.cartociudad.es/geocoder/api/geocoder/find";
|
|
8811
|
-
const CARTOCIUDAD_REVERSE_ENDPOINT = "https://www.cartociudad.es/geocoder/api/geocoder/reverseGeocode";
|
|
8812
|
-
/**
|
|
8813
|
-
* Build a human-readable display name from CartoCiudad address fields.
|
|
8814
|
-
* Format: "Tip Via Address Num, CP Poblacion (Province)"
|
|
8815
|
-
*/
|
|
8816
|
-
function cartociudadDisplayName(r) {
|
|
8817
|
-
const parts = [];
|
|
8818
|
-
const streetParts = [r.tip_via, r.address].filter((s) => s && String(s).trim()).map((s) => String(s).trim());
|
|
8819
|
-
if (streetParts.length) {
|
|
8820
|
-
let street = streetParts.join(" ");
|
|
8821
|
-
const portalNumber = r.portalNumber === void 0 || r.portalNumber === null ? "" : String(r.portalNumber).trim();
|
|
8822
|
-
if (portalNumber) street += ` ${portalNumber}`;
|
|
8823
|
-
parts.push(street);
|
|
8824
|
-
}
|
|
8825
|
-
const localityName = [r.poblacion, r.muni].find((s) => s && String(s).trim());
|
|
8826
|
-
const locality = [r.postalCode, localityName].filter((s) => s && String(s).trim()).map((s) => String(s).trim()).join(" ");
|
|
8827
|
-
if (locality) parts.push(locality);
|
|
8828
|
-
const province = r.province ? String(r.province).trim() : "";
|
|
8829
|
-
if (province) parts.push(`(${province})`);
|
|
8830
|
-
return parts.join(", ") || r.address || r.poblacion || r.muni || "";
|
|
8831
|
-
}
|
|
8832
|
-
/** All selectable geocoding providers, Nominatim first (the default). */
|
|
8833
|
-
const GEOCODING_PROVIDERS = [
|
|
8834
|
-
nominatimProvider,
|
|
8835
|
-
peliasProvider,
|
|
8836
|
-
arcgisProvider,
|
|
8837
|
-
mapboxProvider,
|
|
8838
|
-
googleProvider,
|
|
8839
|
-
{
|
|
8840
|
-
id: "cartociudad",
|
|
8841
|
-
label: "CartoCiudad (IGN España)",
|
|
8842
|
-
forward: true,
|
|
8843
|
-
reverse: true,
|
|
8844
|
-
requiresApiKey: false,
|
|
8845
|
-
acceptsApiKey: false,
|
|
8846
|
-
defaultForwardEndpoint: CARTOCIUDAD_FORWARD_ENDPOINT,
|
|
8847
|
-
defaultReverseEndpoint: CARTOCIUDAD_REVERSE_ENDPOINT,
|
|
8848
|
-
buildForwardUrl: (config, query) => {
|
|
8849
|
-
const url = new URL(config.forwardEndpoint);
|
|
8850
|
-
url.searchParams.set("q", query);
|
|
8851
|
-
return url.toString();
|
|
8852
|
-
},
|
|
8853
|
-
parseForward: (data) => {
|
|
8854
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) return [];
|
|
8855
|
-
const r = data;
|
|
8856
|
-
const coords = cartociudadCoords(r);
|
|
8857
|
-
if (!coords) return [];
|
|
8858
|
-
const displayName = cartociudadDisplayName(r).trim();
|
|
8859
|
-
if (!displayName) return [];
|
|
8860
|
-
return [{
|
|
8861
|
-
lat: coords.lat,
|
|
8862
|
-
lon: coords.lon,
|
|
8863
|
-
displayName,
|
|
8864
|
-
score: null
|
|
8865
|
-
}];
|
|
8866
|
-
},
|
|
8867
|
-
buildReverseUrl: (config, lon, lat) => {
|
|
8868
|
-
const url = new URL(config.reverseEndpoint);
|
|
8869
|
-
url.searchParams.set("lat", String(lat));
|
|
8870
|
-
url.searchParams.set("lon", String(lon));
|
|
8871
|
-
return url.toString();
|
|
8872
|
-
},
|
|
8873
|
-
parseReverse: (data) => {
|
|
8874
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) return null;
|
|
8875
|
-
const r = data;
|
|
8876
|
-
if (!cartociudadCoords(r)) return null;
|
|
8877
|
-
const displayName = cartociudadDisplayName(r).trim();
|
|
8878
|
-
if (!displayName) return null;
|
|
8879
|
-
const parts = {};
|
|
8880
|
-
for (const [key, value] of Object.entries({
|
|
8881
|
-
type: r.type,
|
|
8882
|
-
tip_via: r.tip_via,
|
|
8883
|
-
address: r.address,
|
|
8884
|
-
portalNumber: r.portalNumber,
|
|
8885
|
-
postalCode: r.postalCode,
|
|
8886
|
-
poblacion: r.poblacion,
|
|
8887
|
-
muni: r.muni,
|
|
8888
|
-
province: r.province,
|
|
8889
|
-
comunidadAutonoma: r.comunidadAutonoma,
|
|
8890
|
-
refCatastral: r.refCatastral
|
|
8891
|
-
})) if (value !== void 0 && value !== null && value !== "") parts[key] = String(value);
|
|
8892
|
-
return {
|
|
8893
|
-
displayName,
|
|
8894
|
-
parts
|
|
8895
|
-
};
|
|
8896
|
-
}
|
|
8897
|
-
}
|
|
8898
|
-
];
|
|
8899
|
-
const PROVIDERS_BY_ID = new Map(GEOCODING_PROVIDERS.map((provider) => [provider.id, provider]));
|
|
8900
|
-
/** Coerce an arbitrary string to a known provider id, defaulting to Nominatim. */
|
|
8901
|
-
function normalizeGeocodingProviderId(value) {
|
|
8902
|
-
const id = value?.trim();
|
|
8903
|
-
return id && PROVIDERS_BY_ID.has(id) ? id : DEFAULT_GEOCODING_PROVIDER_ID;
|
|
8904
|
-
}
|
|
8905
|
-
/** Look up a provider by id, falling back to Nominatim for unknown ids. */
|
|
8906
|
-
function getGeocodingProvider(id) {
|
|
8907
|
-
return PROVIDERS_BY_ID.get(normalizeGeocodingProviderId(id)) ?? nominatimProvider;
|
|
8908
|
-
}
|
|
8909
|
-
/**
|
|
8910
|
-
* Resolve the geocoder configuration from runtime env, falling back to the
|
|
8911
|
-
* selected provider's default endpoints. `VITE_GEOCODER_PROVIDER` selects the
|
|
8912
|
-
* backend; `VITE_GEOCODER_ENDPOINT`/`VITE_GEOCODER_REVERSE_ENDPOINT` override
|
|
8913
|
-
* the endpoints; `VITE_GEOCODER_EMAIL` supplies the contact email; and
|
|
8914
|
-
* `VITE_GEOCODER_API_KEY` supplies the API key for keyed providers.
|
|
8915
|
-
*/
|
|
8916
|
-
function getGeocoderConfig() {
|
|
8917
|
-
const env = getRuntimeEnvironment();
|
|
8918
|
-
const provider = getGeocodingProvider(env.VITE_GEOCODER_PROVIDER);
|
|
8919
|
-
return {
|
|
8920
|
-
providerId: provider.id,
|
|
8921
|
-
forwardEndpoint: env.VITE_GEOCODER_ENDPOINT?.trim() || provider.defaultForwardEndpoint,
|
|
8922
|
-
reverseEndpoint: env.VITE_GEOCODER_REVERSE_ENDPOINT?.trim() || provider.defaultReverseEndpoint,
|
|
8923
|
-
email: env.VITE_GEOCODER_EMAIL?.trim() || void 0,
|
|
8924
|
-
apiKey: env.VITE_GEOCODER_API_KEY?.trim() || void 0
|
|
8925
|
-
};
|
|
8926
|
-
}
|
|
8927
|
-
/**
|
|
8928
|
-
* Build a {@link GeocoderConfig} from structured project preferences. Used by
|
|
8929
|
-
* the geocode dialog so a per-run provider choice resolves the right endpoints
|
|
8930
|
-
* and API key without round-tripping through runtime env.
|
|
8931
|
-
*/
|
|
8932
|
-
function resolveGeocoderConfig(input) {
|
|
8933
|
-
const provider = getGeocodingProvider(input.providerId);
|
|
8934
|
-
return {
|
|
8935
|
-
providerId: provider.id,
|
|
8936
|
-
forwardEndpoint: input.forwardEndpoint?.trim() || provider.defaultForwardEndpoint,
|
|
8937
|
-
reverseEndpoint: input.reverseEndpoint?.trim() || provider.defaultReverseEndpoint,
|
|
8938
|
-
email: input.email?.trim() || void 0,
|
|
8939
|
-
apiKey: input.apiKeys?.[provider.id]?.trim() || void 0
|
|
8940
|
-
};
|
|
8941
|
-
}
|
|
8942
|
-
/** Hostname of `endpoint`, or null when it does not parse as a URL. */
|
|
8943
|
-
function geocoderHostname(endpoint) {
|
|
8944
|
-
try {
|
|
8945
|
-
return new URL(endpoint).hostname;
|
|
8946
|
-
} catch {
|
|
8947
|
-
return null;
|
|
8948
|
-
}
|
|
8949
|
-
}
|
|
8950
|
-
/** Whether `hostname` is the public CartoCiudad service or a subdomain of it. */
|
|
8951
|
-
function isCartociudadHost(hostname) {
|
|
8952
|
-
if (hostname === null) return false;
|
|
8953
|
-
return hostname === "cartociudad.es" || hostname.endsWith(`.cartociudad.es`);
|
|
8954
|
-
}
|
|
8955
|
-
/**
|
|
8956
|
-
* Whether requests to `endpoint` must be throttled AND row-capped. True for the
|
|
8957
|
-
* public Nominatim host (its usage policy applies) and, defensively, for any
|
|
8958
|
-
* endpoint that does not parse as a URL. Every other host (a self-hosted
|
|
8959
|
-
* Nominatim or a keyed provider) returns false.
|
|
8960
|
-
*
|
|
8961
|
-
* Note this is the *Nominatim policy* gate, not "is this host paced at all" —
|
|
8962
|
-
* see {@link geocoderMinIntervalMs}, which paces CartoCiudad more gently
|
|
8963
|
-
* without capping its row count.
|
|
8964
|
-
*/
|
|
8965
|
-
function shouldThrottle(endpoint) {
|
|
8966
|
-
const hostname = geocoderHostname(endpoint);
|
|
8967
|
-
return hostname === null || hostname === "nominatim.openstreetmap.org";
|
|
8968
|
-
}
|
|
8969
|
-
/**
|
|
8970
|
-
* The row cap to apply for `endpoint`: a finite cap for the public Nominatim
|
|
8971
|
-
* host, else Infinity. CartoCiudad is uncapped — IGN publishes no row limit and
|
|
8972
|
-
* its own bulk address geocoder processes up to 60,000 records per run, so a
|
|
8973
|
-
* cap here would be an invented constraint. It is still paced; see
|
|
8974
|
-
* {@link geocoderMinIntervalMs}.
|
|
8975
|
-
*/
|
|
8976
|
-
function rowCap(endpoint) {
|
|
8977
|
-
return shouldThrottle(endpoint) ? PUBLIC_GEOCODE_ROW_CAP : Number.POSITIVE_INFINITY;
|
|
8978
|
-
}
|
|
8979
|
-
/**
|
|
8980
|
-
* Minimum spacing (ms) between requests for `endpoint`. Gated on the hostname,
|
|
8981
|
-
* not the selected provider, so pointing any provider at the public Nominatim
|
|
8982
|
-
* host still honors its 1 req/sec policy.
|
|
8983
|
-
*
|
|
8984
|
-
* CartoCiudad gets a gentler pace of its own. IGN documents no rate limit for
|
|
8985
|
-
* the single-lookup `find`/`reverseGeocode` endpoints either way, so the honest
|
|
8986
|
-
* position is that unbounded bursting is unverified rather than sanctioned:
|
|
8987
|
-
* a large CSV run against a free public government service with zero spacing
|
|
8988
|
-
* risks getting the caller's IP throttled and degrading the service for
|
|
8989
|
-
* everyone. Nominatim's 1 req/sec is that provider's published policy and is
|
|
8990
|
-
* not borrowed here. Keyed providers and self-hosted endpoints are paced by
|
|
8991
|
-
* their own quotas, not by us.
|
|
8992
|
-
*/
|
|
8993
|
-
function geocoderMinIntervalMs(endpoint) {
|
|
8994
|
-
if (shouldThrottle(endpoint)) return NOMINATIM_MIN_INTERVAL_MS;
|
|
8995
|
-
return isCartociudadHost(geocoderHostname(endpoint)) ? 200 : 0;
|
|
8996
|
-
}
|
|
8997
|
-
/** Hosted Pelias service that rejects keyless requests. */
|
|
8998
|
-
const GEOCODE_EARTH_HOST_SUFFIX = "geocode.earth";
|
|
8999
|
-
/**
|
|
9000
|
-
* Whether `config` cannot geocode without an API key. True for the keyed
|
|
9001
|
-
* providers (ArcGIS, Mapbox, Google) and for Pelias only when it targets the
|
|
9002
|
-
* hosted geocode.earth endpoint (a self-hosted Pelias needs no key). Drives the
|
|
9003
|
-
* batch dialog's "missing key" warning and disabled run.
|
|
9004
|
-
*/
|
|
9005
|
-
function geocoderNeedsApiKey(config) {
|
|
9006
|
-
const provider = getGeocodingProvider(config.providerId);
|
|
9007
|
-
if (provider.requiresApiKey) return true;
|
|
9008
|
-
if (provider.id === "pelias") try {
|
|
9009
|
-
const host = new URL(config.forwardEndpoint).hostname;
|
|
9010
|
-
return host === GEOCODE_EARTH_HOST_SUFFIX || host.endsWith(`.${GEOCODE_EARTH_HOST_SUFFIX}`);
|
|
9011
|
-
} catch {
|
|
9012
|
-
return false;
|
|
9013
|
-
}
|
|
9014
|
-
return false;
|
|
9015
|
-
}
|
|
9016
|
-
/**
|
|
9017
|
-
* Milliseconds to wait before starting the next request so consecutive
|
|
9018
|
-
* requests are spaced at least `intervalMs` apart, measured from the previous
|
|
9019
|
-
* request's start time (not its completion) so a slow network does not double
|
|
9020
|
-
* the wait. Returns 0 for the first request or when enough time has elapsed.
|
|
9021
|
-
*/
|
|
9022
|
-
function nextDelayMs(lastStartedAt, now, intervalMs) {
|
|
9023
|
-
if (lastStartedAt === null) return 0;
|
|
9024
|
-
return Math.max(0, intervalMs - (now - lastStartedAt));
|
|
9025
|
-
}
|
|
9026
|
-
/**
|
|
9027
|
-
* Build geocoding requests from parsed CSV rows. The address for each row is
|
|
9028
|
-
* the selected columns trimmed and joined with ", " (so multi-part addresses
|
|
9029
|
-
* like street/city/country can be combined). Rows whose composed address is
|
|
9030
|
-
* empty are skipped.
|
|
9031
|
-
*/
|
|
9032
|
-
function csvRowsToGeocodeRequests(rows, addressColumns) {
|
|
9033
|
-
const requests = [];
|
|
9034
|
-
rows.forEach((row, index) => {
|
|
9035
|
-
const address = addressColumns.map((column) => (row[column] ?? "").trim()).filter(Boolean).join(", ").trim();
|
|
9036
|
-
if (!address) return;
|
|
9037
|
-
requests.push({
|
|
9038
|
-
index,
|
|
9039
|
-
address,
|
|
9040
|
-
row
|
|
9041
|
-
});
|
|
9042
|
-
});
|
|
9043
|
-
return requests;
|
|
9044
|
-
}
|
|
9045
|
-
/**
|
|
9046
|
-
* The fetch implementation used by {@link geocodeForward}/{@link geocodeReverse}.
|
|
9047
|
-
* Null means "use the global browser `fetch`" (the default for the web and
|
|
9048
|
-
* embedded builds).
|
|
9049
|
-
*/
|
|
9050
|
-
let geocodingFetch = null;
|
|
9051
|
-
/**
|
|
9052
|
-
* Override the fetch used for geocoding requests, or pass null to restore the
|
|
9053
|
-
* global browser `fetch`.
|
|
9054
|
-
*
|
|
9055
|
-
* The desktop shell sets this to Tauri's native HTTP fetch so geocoding requests
|
|
9056
|
-
* are made from the Rust side, which:
|
|
9057
|
-
* - bypasses the WebView's CORS enforcement. Public Nominatim's CDN
|
|
9058
|
-
* intermittently omits the `Access-Control-Allow-Origin` header on cached
|
|
9059
|
-
* responses, which the browser then rejects — surfacing to the user as
|
|
9060
|
-
* "Search failed. Try again." (the symptom that failed Microsoft Store
|
|
9061
|
-
* certification); and
|
|
9062
|
-
* - can send a `User-Agent` identifying the app, as Nominatim's usage policy
|
|
9063
|
-
* requires (browser fetch cannot set that header).
|
|
9064
|
-
*
|
|
9065
|
-
* Safe to call multiple times; only the most recent implementation is used.
|
|
9066
|
-
*/
|
|
9067
|
-
function setGeocodingFetch(fetchImpl) {
|
|
9068
|
-
geocodingFetch = fetchImpl;
|
|
9069
|
-
}
|
|
9070
|
-
/** The active geocoding fetch: the injected override, else the global fetch. */
|
|
9071
|
-
function geocodeFetch() {
|
|
9072
|
-
return geocodingFetch ?? fetch;
|
|
9073
|
-
}
|
|
9074
|
-
/**
|
|
9075
|
-
* Read a geocoder response body as JSON, treating an empty one as "no results".
|
|
9076
|
-
*
|
|
9077
|
-
* CartoCiudad answers an unmatched query with HTTP 204 and an empty body rather
|
|
9078
|
-
* than a JSON null (verified against the live `find` and `reverseGeocode`
|
|
9079
|
-
* endpoints). `response.ok` is true for 204, so parsing unconditionally would
|
|
9080
|
-
* throw a JSON syntax error and surface a nonsense address as "Search failed"
|
|
9081
|
-
* instead of "no match". Returning undefined lets each provider's parser report
|
|
9082
|
-
* no results the way it already does for a null body.
|
|
9083
|
-
*/
|
|
9084
|
-
async function readGeocodeJson(response) {
|
|
9085
|
-
if (response.status === 204) return void 0;
|
|
9086
|
-
const text = await response.text();
|
|
9087
|
-
if (!text.trim()) return void 0;
|
|
9088
|
-
return JSON.parse(text);
|
|
9089
|
-
}
|
|
9090
|
-
/**
|
|
9091
|
-
* Normalize a longitude into [-180, 180], or null when it is not finite.
|
|
9092
|
-
*
|
|
9093
|
-
* MapLibre reports `lngLat.lng` unwrapped once the map is zoomed out far enough
|
|
9094
|
-
* to show repeated world copies, so a click on a non-primary copy arrives as
|
|
9095
|
-
* e.g. 210 rather than -150. Rejecting those outright would silently drop a
|
|
9096
|
-
* legitimate reverse-geocode click for every provider, so wrap instead.
|
|
9097
|
-
*
|
|
9098
|
-
* An in-range longitude returns untouched: the modulo round-trip is not exact
|
|
9099
|
-
* in floating point (-3.7 comes back as -3.7000000000000455), and the common
|
|
9100
|
-
* case should not be perturbed to handle the rare one.
|
|
9101
|
-
*/
|
|
9102
|
-
function wrapLongitude(lon) {
|
|
9103
|
-
if (!Number.isFinite(lon)) return null;
|
|
9104
|
-
if (lon >= -180 && lon <= 180) return lon;
|
|
9105
|
-
return ((lon + 180) % 360 + 360) % 360 - 180;
|
|
9106
|
-
}
|
|
9107
|
-
/**
|
|
9108
|
-
* Forward-geocode a single query through the configured provider, returning
|
|
9109
|
-
* normalized matches.
|
|
9110
|
-
*/
|
|
9111
|
-
async function geocodeForward(query, options = {}) {
|
|
9112
|
-
const config = options.config ?? getGeocoderConfig();
|
|
9113
|
-
const provider = getGeocodingProvider(config.providerId);
|
|
9114
|
-
const url = provider.buildForwardUrl(config, query, {
|
|
9115
|
-
email: config.email,
|
|
9116
|
-
limit: options.limit
|
|
9117
|
-
});
|
|
9118
|
-
const response = await geocodeFetch()(url, {
|
|
9119
|
-
signal: options.signal,
|
|
9120
|
-
headers: { Accept: "application/json" }
|
|
9121
|
-
});
|
|
9122
|
-
if (!response.ok) throw new Error(`Geocoder returned HTTP ${response.status}`);
|
|
9123
|
-
const data = await readGeocodeJson(response);
|
|
9124
|
-
return provider.parseForward(data);
|
|
9125
|
-
}
|
|
9126
|
-
/**
|
|
9127
|
-
* Reverse-geocode a single point ([lon, lat]) through the configured provider,
|
|
9128
|
-
* returning a normalized display result or null when no address was found.
|
|
9129
|
-
*/
|
|
9130
|
-
async function geocodeReverse(lon, lat, options = {}) {
|
|
9131
|
-
const wrappedLon = wrapLongitude(lon);
|
|
9132
|
-
if (wrappedLon === null || !Number.isFinite(lat) || lat < -90 || lat > 90) return null;
|
|
9133
|
-
const config = options.config ?? getGeocoderConfig();
|
|
9134
|
-
const provider = getGeocodingProvider(config.providerId);
|
|
9135
|
-
const url = provider.buildReverseUrl(config, wrappedLon, lat, {
|
|
9136
|
-
email: config.email,
|
|
9137
|
-
zoom: options.zoom
|
|
9138
|
-
});
|
|
9139
|
-
const response = await geocodeFetch()(url, {
|
|
9140
|
-
signal: options.signal,
|
|
9141
|
-
headers: { Accept: "application/json" }
|
|
9142
|
-
});
|
|
9143
|
-
if (!response.ok) throw new Error(`Geocoder returned HTTP ${response.status}`);
|
|
9144
|
-
const data = await readGeocodeJson(response);
|
|
9145
|
-
return provider.parseReverse(data);
|
|
9146
|
-
}
|
|
9147
|
-
//#endregion
|
|
9148
|
-
//#region src/platform.ts
|
|
8185
|
+
// src/platform.ts
|
|
9149
8186
|
/**
|
|
9150
8187
|
* Platform detection shared across the workspace. Carries no React/MapLibre
|
|
9151
8188
|
* dependency so callers stay unit-testable.
|
|
@@ -9171,8 +8208,7 @@ async function geocodeReverse(lon, lat, options = {}) {
|
|
|
9171
8208
|
function isIpadDesktopUserAgent(userAgent, maxTouchPoints) {
|
|
9172
8209
|
return /Macintosh/.test(userAgent) && (maxTouchPoints ?? 0) > 1;
|
|
9173
8210
|
}
|
|
9174
|
-
|
|
9175
|
-
//#region src/three-d-tiles.ts
|
|
8211
|
+
// src/three-d-tiles.ts
|
|
9176
8212
|
/** Google Photorealistic 3D Tiles root host + path. */
|
|
9177
8213
|
const GOOGLE_PHOTOREALISTIC_TILES_HOST = "tile.googleapis.com";
|
|
9178
8214
|
const GOOGLE_PHOTOREALISTIC_TILES_PATH = "/v1/3dtiles/root.json";
|
|
@@ -9239,8 +8275,7 @@ function persistedThreeDTilesRequestHeaders(url, headers) {
|
|
|
9239
8275
|
if (!isGooglePhotorealisticTilesetUrl(url)) return headers;
|
|
9240
8276
|
return nonEmptyRecord(stripGoogleMapsApiKeyHeader(headers));
|
|
9241
8277
|
}
|
|
9242
|
-
|
|
9243
|
-
//#region src/project-credential-refs.ts
|
|
8278
|
+
// src/project-credential-refs.ts
|
|
9244
8279
|
/**
|
|
9245
8280
|
* Credentials a project refers to by name rather than carrying inline.
|
|
9246
8281
|
*
|
|
@@ -9417,8 +8452,7 @@ function resolveProjectHeaderReferences(headers) {
|
|
|
9417
8452
|
}
|
|
9418
8453
|
return resolveHeaderReferences(headers, values);
|
|
9419
8454
|
}
|
|
9420
|
-
|
|
9421
|
-
//#region src/visibility.ts
|
|
8455
|
+
// src/visibility.ts
|
|
9422
8456
|
/**
|
|
9423
8457
|
* Returns a new FeatureCollection with properties marked as "excluded" removed.
|
|
9424
8458
|
*/
|
|
@@ -9450,8 +8484,9 @@ function excludeHiddenFieldsFromProject(project) {
|
|
|
9450
8484
|
const strippedGeojson = excludeHiddenFieldsFromGeojson(layer.geojson, layer.fieldVisibility);
|
|
9451
8485
|
if (strippedGeojson !== layer.geojson) {
|
|
9452
8486
|
changed = true;
|
|
8487
|
+
const { geoarrow: _staleGeoarrow, ...rest } = updatedLayer;
|
|
9453
8488
|
updatedLayer = {
|
|
9454
|
-
...
|
|
8489
|
+
...rest,
|
|
9455
8490
|
geojson: strippedGeojson
|
|
9456
8491
|
};
|
|
9457
8492
|
}
|
|
@@ -9476,8 +8511,7 @@ function excludeHiddenFieldsFromProject(project) {
|
|
|
9476
8511
|
layers
|
|
9477
8512
|
} : project;
|
|
9478
8513
|
}
|
|
9479
|
-
|
|
9480
|
-
//#region src/editor-tracking.ts
|
|
8514
|
+
// src/editor-tracking.ts
|
|
9481
8515
|
/** Default field names for maintained editor tracking columns. */
|
|
9482
8516
|
const DEFAULT_EDITOR_TRACKING_CONFIG = {
|
|
9483
8517
|
enabled: false,
|
|
@@ -9647,8 +8681,7 @@ function stampFeatureCollectionEditorTracking(collection, action, options) {
|
|
|
9647
8681
|
features: collection.features.map((feat) => stampFeatureEditorTracking(feat, action, opts))
|
|
9648
8682
|
};
|
|
9649
8683
|
}
|
|
9650
|
-
|
|
9651
|
-
//#region src/editor-identity.ts
|
|
8684
|
+
// src/editor-identity.ts
|
|
9652
8685
|
/**
|
|
9653
8686
|
* Runtime resolution of "who is editing", for the editor tracking stamps.
|
|
9654
8687
|
*
|
|
@@ -9696,8 +8729,7 @@ function currentEditorIdentity() {
|
|
|
9696
8729
|
const { isActive, selfName } = useAppStore.getState().collaboration;
|
|
9697
8730
|
return pickEditorIdentity(isActive ? selfName : void 0, readStoredAuthorName());
|
|
9698
8731
|
}
|
|
9699
|
-
|
|
9700
|
-
//#region src/datum-shift.ts
|
|
8732
|
+
// src/datum-shift.ts
|
|
9701
8733
|
/** Inclusive ranges of codes, as a list. */
|
|
9702
8734
|
const range = (from, to) => Array.from({ length: to - from + 1 }, (_, i) => from + i);
|
|
9703
8735
|
const SHIFTS = [
|
|
@@ -9847,8 +8879,7 @@ function withGeoKeysDatumShift(definition, geoKeys) {
|
|
|
9847
8879
|
function installCogTilerDatumShift(module) {
|
|
9848
8880
|
module.setSourceCrsResolver?.((def, geoKeys) => def.trimStart().startsWith("+") ? withGeoKeysDatumShift(def, geoKeys) : def);
|
|
9849
8881
|
}
|
|
9850
|
-
|
|
9851
|
-
//#region src/cog-jpeg-tables.ts
|
|
8882
|
+
// src/cog-jpeg-tables.ts
|
|
9852
8883
|
const DEFAULT_COEFFICIENTS = [
|
|
9853
8884
|
.299,
|
|
9854
8885
|
.587,
|
|
@@ -9978,7 +9009,6 @@ function withJpegTablesPatch(module) {
|
|
|
9978
9009
|
openCog: (async (input) => patchJpegCogSource(await module.openCog(input)))
|
|
9979
9010
|
};
|
|
9980
9011
|
}
|
|
9981
|
-
//#endregion
|
|
9982
|
-
export { ALL_APP_PRIVILEGES, ALL_DEPLOYMENT_CAPABILITIES, ARCGIS_PROJECTION_PRESETS, BLANK_BASEMAP, BLEND_MODES, BUILT_IN_STYLE_PRESETS, CARTOCIUDAD_MIN_INTERVAL_MS, CARTOCIUDAD_PUBLIC_HOST, CESIUM_BASEMAPS, CESIUM_BING_AERIAL_ASSET_ID, CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, CESIUM_ION_QUICK_PICKS, CESIUM_ION_SOURCE_KIND, CESIUM_KML_SOURCE_KIND, CESIUM_OSM_BUILDINGS_ASSET_ID, CHINA_BASEMAPS, CZML_QUICK_PICKS, CZML_SOURCE_KIND, DEFAULT_BASEMAP, DEFAULT_BLEND_MODE, DEFAULT_COLLABORATION_STATE, DEFAULT_DASHBOARD_COLUMNS, DEFAULT_EDITOR_IDENTITY, DEFAULT_EDITOR_TRACKING_CONFIG, DEFAULT_ELLIPSOID_ID, DEFAULT_FORWARD_GEOCODE_ENDPOINT, DEFAULT_GEOCODING_PROVIDER_ID, DEFAULT_LAYER_GROUP_OPACITY, DEFAULT_LAYER_STYLE, DEFAULT_LEGEND_CONFIG, DEFAULT_MAP_GRID_LAYOUT, DEFAULT_PRIMARY_RENDERER, DEFAULT_PRINT_LAYOUT, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_PREFERENCES, DEFAULT_REVERSE_GEOCODE_ENDPOINT, DEFAULT_ROUTING_ENDPOINT, DEFAULT_STORY_MAP, DEPLOYMENT_CAPABILITIES, DUCKDB_VECTOR_FEATURE_WARN_COUNT, DUCKDB_VECTOR_ROUTE_BYTES, EARTH_MEAN_RADIUS_METERS, EDITOR_IDENTITY_STORAGE_KEY, ELEVATION_REQUEST_TIMEOUT_MS, ELLIPSOIDS, EXPRESSION_FUNCTION_CATEGORIES, ElevationFetchError, FEET_PER_METER, FEET_PER_MILE, GEOCODE_DISPLAY_NAME_KEY, GEOCODE_LAT_KEY, GEOCODE_LON_KEY, GEOCODE_PROVIDER_KEY, GEOCODE_SCORE_KEY, GEOCODE_STATUS_KEY, GEOCODING_PROVIDERS, GOOGLE_MAPS_API_KEY_HEADER, IDENTIFY_ALL_LAYERS_ID, LABEL_NUMBER_LOCALES, LABEL_NUMBER_SAMPLE, LARGE_VECTOR_FEATURE_THRESHOLD, LAYERS_FILE_TYPE, LAYERS_FILE_VERSION, LAYER_LIBRARY_BUNDLE_TYPE, LAYER_LIBRARY_BUNDLE_VERSION, LAYER_PALETTE, LAYER_STYLES_FILE_TYPE, LAYER_STYLES_FILE_VERSION, LAYER_TYPES, MAX_DASHBOARD_COLUMNS, MAX_DIAGRAM_FEATURES, MAX_DIAGRAM_SCAN_FEATURES, MAX_LAYERS_FILE_BYTES, MAX_LAYER_LIBRARY_ENTRIES, MAX_LAYER_LIBRARY_ENTRY_BYTES, MAX_MAP_GRID_DIM, MAX_POINTS_PER_REQUEST, MAX_PROCESSING_HISTORY, MAX_PROJECT_BOOKMARKS, MAX_REDACT_DEPTH, MERCATOR_METERS_PER_PIXEL_AT_ZOOM_0, METERS_PER_FOOT, METERS_PER_MILE, METERS_PER_NAUTICAL_MILE, MIN_DASHBOARD_COLUMNS, MIN_DIAGRAM_SIZE, NETCDF_IMAGE_SOURCE_KIND, NOMINATIM_MIN_INTERVAL_MS, NOMINATIM_PUBLIC_HOST, NO_DEPLOYMENT_CAPABILITIES, NO_LAYERS, OPENFREEMAP_BASEMAPS, PHOTO_FULL_PROPERTY, PHOTO_PROPERTY, PLANETARY_BASEMAPS, PLANETARY_BASEMAP_GROUPS, PLANETARY_BASEMAP_SENTINEL_PREFIX, PLANET_SWITCHER_OPTIONS, POINTER_ELEVATION_CACHE_LIMIT, POINTER_ELEVATION_DEBOUNCE_MS, POPUP_IMAGE_HEIGHT_RANGE, POPUP_MAX_WIDTH_RANGE, PROJECT_CREDENTIAL_FIELDS, PROJECT_VERSION, PROTOMAPS_BASEMAPS, PUBLIC_GEOCODE_ROW_CAP, PUBLISHABLE_PLUGIN_SETTINGS, RAMP_STYLE_KEYS, RASTER_APPEARANCE_STATE_KEYS, REGIONAL_BASEMAPS, REGIONAL_BASEMAP_GROUPS, REGIONAL_BASEMAP_SENTINEL_PREFIX, ROLE_PRIVILEGES, RoutingRequestError, S3CorsError, S3_MAX_PRESIGN_SECONDS, SELECTION_MODES, SQL_QUERY_SOURCE_KIND, STAC_PROCESSING_EXTENSION, STAC_VERSION, STYLE_LIBRARY_BUNDLE_TYPE, STYLE_LIBRARY_BUNDLE_VERSION, SYMBOL_STYLE_KEYS, VECTOR_COLOR_RAMPS, activeLayerFilterExpression, activeQuickFilters, addLayersToProject, allowsCredentialHeaders, appPrivilegeReason, applyCopiedLayerStyle, applyGroupEffects, applyJoinsToLayer, applyLayerJoins, applyLayerVirtualFields, applyMatchedSelection, applyProjectToStore, applySelectionMode, applyStoryLayerOpacity, attributeFormFieldLabel, attributeLinkUrl, availableCesiumBasemap, basemapToCesiumImagery, batchDecodePolylines, bodyLengthToEarth, buildForwardGeocodeUrl, buildIsochroneRequest, buildLayerPanelUnits, buildLayerStacItem, buildLayerTree, buildMatrixRequest, buildReverseGeocodeUrl, buildRouteRequest, canRedoProjectRestore, canSaveLayerToLibrary, canUndoProjectRestore, captureLayerLibraryEntry, cascadeLayerJoinRefresh, cesiumIonAssetId, cesiumIonAssetKind, cesiumKmlSource, changedPreferenceCredentials, circleRadiusValue, clampLabelDecimals, clampLatitude, clearExternalNativePaintBridge, clearHistory, clearQuickFilterValues, coerceAttributeFormValue, collectDiagramData, collectTransitiveJoinSourceIds, compareSequenceValues, compileFeatureExpression, compileLayerFilters, compileQuickFilter, compileQuickFilters, controlRendersLayer, convertTiffYCbCrToRgb, copyableLayerStyleKind, createCesiumIonLayer, createCesiumKmlLayer, createCzmlLayer, createDefaultAppCapabilities, createDefaultMapView, createDefaultPrintLayout, createEmptyProject, createEqualIntervalBreaks, createGraduatedClassBreaks, createLayerLibraryEntryId, createPointerElevationResolver, createProjectLayerSerializationCache, createProjectTemplate, createQuantileBreaks, createSampleStoryMap, createStyleLayerEvaluator, createStyleLibraryEntryId, csvRowsToGeocodeRequests, currentEditorIdentity, czmlSource, darkenHex, datumShiftFor, decodePolyline, decodePolylineDetailed, detachProjectCopy, detectNonGeographicCoordinates, diagramAnchor, diagramPixelSize, diagramsSuppressedByPointRenderer, diffFeatureCollections, diffProjects, documentLocale, dominantGeometry, drawMarkerPath, earthAreaToBody, earthLengthToBody, editorTrackingFieldNames, effectiveLayerRenderState, effectiveVectorRules, encodePolyline, encodeS3Key, ensureEditorTrackingFields, environmentVariableAccount, evaluateMapExpression, excludeHiddenFieldsFromGeojson, excludeHiddenFieldsFromProject, explainS3ReadError, extractCopiedLayerStyle, extractLayerStyleEntries, extractLayersFileContent, extractStyleLibraryStyle, extrusionColorValue, extrusionHeightValue, featureSelectionId, fetchElevations, findLayerStyleEntryIndex, formatCameraAltitude, formatExpressionPreviewValue, formatLabelNumber, formatLabelNumberSample, formatPixelValue, formatPopupValue, formatRoundNum, formatS3Uri, generatorCircleRadiusValue, generatorSizeRange, geoJSONToPolylineStr, geocodeForward, geocodeMatchToFeature, geocodeReverse, geocoderMinIntervalMs, geocoderNeedsApiKey, geocodingApiKeyAccount, geojsonHasZCoordinates, getActiveBodyRadiusRatio, getActiveEllipsoid, getActiveMeanRadiusMeters, getActiveSemiMajorAxisMeters, getArcgisApiKey, getAttributeFormField, getBuildEnvironment, getCesiumIonToken, getEllipsoid, getExternalNativePaintBridge, getGeocoderConfig, getGeocodingProvider, getGoogleMapsApiKey, getHistoryCoalesceMs, getMapboxAccessToken, getMaxHistoryFeatureCount, getPlanetaryBasemapById, getPlanetaryBasemapByStyleUrl, getProtomapsApiKey, getProtomapsStyleUrl, getRegionalBasemapById, getRegionalBasemapByStyleUrl, getRoundNum, getRoutingConfig, getRuntimeEnvironment, getS3UrlSigner, getSpatialExtensionPath, getVectorColorRamp, googleMapsApiKeyHeaderValue, groupMemberIndices, hasActiveLayerFilter, hasActiveQuickFilter, hasAppPrivilege, hasHeaderReferences, hasPathTraversal, hasRestorableLayerSource, hasSimpleStyleProperties, heatmapRampColors, horizontalBbox, hydrateProjectLayer, identifyAllIncludes, identifyStateWithoutLayers, inferFieldTypes, inferLayerCapabilities, initialLayerStyle, installCogTilerDatumShift, interpolateColors, interpolateHexColor, interpolateRampColors, intersectPrivileges, invertSelection, isAbbreviatedJpegCompression, isAbsoluteFilesystemPath, isAdoptedVectorAwaitingFeatures, isAllowedPluginManifestUrl, isAttributeFormFieldVisible, isCesiumIonLayer, isCesiumKmlLayer, isCesiumOnlyLayer, isCredentialFieldName, isCredentialUrlParam, isCredentialedS3Url, isCzmlLayer, isDefaultPrintLayout, isDeploymentCapability, isDiagramStyleEnabled, isDuckDBQueryLayer, isExternalNativeLayerRecord, isGooglePhotorealisticTilesetUrl, isHeaderReferenceOnly, isHexColor, isInitialLayerStyle, isInlineImageValue, isInternalPopupField, isIpadDesktopUserAgent, isMaintainedEditorTrackingField, isPopupClickEnabled, isPopupHoverEnabled, isRasterMarkerSource, isReferencedLayer, isRegionalBasemapSentinel, isS3Uri, isSafePopupUrl, isSecretEnvironmentVariable, isSessionOnlyLayer, isStoryHiddenLayer, isStyleLibraryTargetLayer, isStyleSpecColor, isSvgMarkerResponse, isValidMetadataDate, isValidMetadataEmail, isValidMetadataUrl, isVectorColorExpression, isochroneResponseToFeatures, jsonValuesEqual, labelFieldTextField, layerGroupDepth, layerGroupMoveability, layerGroupSortability, layerJoinKey, layerLibraryConfigPatch, layerLibraryEntryNeedsLocalFile, layerLocalPath, layerPanelGroupHeaders, lineWidthValue, localFileName, lookupProjectCredential, mapZoomStepOutputs, matchFeaturesByExpression, matchLayerStyleEntry, matrixResponseToFeatures, meanRadiusMeters, mercatorMetersPerPixelAtZoom0, mergeAttributeFormConfigs, metadataDateToRfc3339, metersWidthExpression, nextDelayMs, nextLayerPaletteColor, nominatimResultToFeature, nominatimReverseResultToDisplay, nonEmptyRecord, normalizeAppPrivileges, normalizeArcgisWkid, normalizeBlankBackgroundColor, normalizeBookmarkGroups, normalizeBookmarks, normalizeCesiumBasemap, normalizeDashboardColumns, normalizeGeocodingProviderId, normalizeGroupContiguity, normalizeHexColor, normalizeLayerCapabilities, normalizeLayerDescriptiveMetadata, normalizeLayerLibraryEntries, normalizeLayerStyleEntries, normalizeLayersFileContent, normalizeLegendConfig, normalizeLongitude, normalizeMapLayout, normalizeMapViewState, normalizeModelGraph, normalizeModels, normalizeObiaWorkbench, normalizePrimaryRenderer, normalizePrintLayoutConfig, normalizeProcessingHistory, normalizeProjectComments, normalizeProjectInteraction, normalizeSecondaryMapViews, normalizeStoryMap, normalizeStyleLibraryEntries, normalizeWidgets, overlayStoredEnvironmentVariables, overlayStoredGeocodingApiKeys, overlayStoredPreferenceCredentials, parseCesiumIonAssetId, parseContours, parseCzml, parseDeploymentCapabilities, parseHexColor, parseHexColorList, parseJsonExpression, parseLayerLibrary, parseLayerStylesFile, parseLayersFile, parseMetadataKeywords, parseProject, parseS3BucketList, parseS3Error, parseS3ListObjects, parseS3Url, parseStoryMapCsv, parseStoryMapJson, parseStyleLibrary, parseValueMapText, patchJpegCogSource, persistedThreeDTilesRequestHeaders, pickEditorIdentity, planLayerLibraryAdd, pluginOwnsPaint, polylineStrToGeoJSON, popupFieldLabel, portableWmsTileUrl, presignS3Url, previewValue, printLayoutConfigsEqual, projectFromStore, projectPathLabel, proportionalRadiusExpression, proportionalSizeRange, readStoredAuthorName, reapplyLayerJoins, redactConfigurationCredentials, redactCredentials, redactProjectCredentials, redactUrlCredentials, redo, registerProjectRestoreHistory, registerS3UrlSigner, removeTrailingJsonCommas, rendererAppliesOpacity, reorderLayerGroupInPanel, requestIsochrone, requestMatrix, requestNavigationRoute, requestRoute, resolveConfiguredPopupTitle, resolveEditorTrackingConfig, resolveGeocoderConfig, resolveHeaderReferences, resolveIdentifyTarget, resolveLabelNumberLocale, resolveLayerCapabilities, resolveMapGrid, resolvePopupBody, resolvePopupImageHeight, resolvePopupMaxWidth, resolvePopupRows, resolvePopupTitle, resolveProjectHeaderReferences, resolveReadableUrl, resolveRolePrivileges, resolveSvgSource, resolveThreeDTilesRequestHeaders, rgbToHex, routeResponseToFeatures, rowCap, ruleBasedColorExpression, ruleBasedVisibilityFilter, s3ObjectHttpsUrl, sameCesiumImagery, sampleMapTerrain, sampleMapTerrainPoint, sampleRemoteElevations, sanitizeLayerStylePatch, scaleAltitudeToActiveBody, scaleDenomination, scaleSpan, scrubCommentsForRemovedLayers, scrubLegendForRemovedLayers, scrubPrintLayoutForLayers, scrubPrintLayoutForRemovedLayers, scrubWidgetsForRemovedLayers, selectLayerById, selectLayerIds, selectLayerSummaries, selectLayersWhen, serializeLayerLibrary, serializeLayerStylesFile, serializeLayersFile, serializeProject, serializeProjectWithLayerCache, serializeProjectWithLayerCacheAsync, serializeStoryMapCsv, serializeStoryMapJson, serializeStyleLibrary, setActiveEllipsoidId, setExternalNativePaintBridge, setGeocodingFetch, setHistoryCoalesceMs, setMaxHistoryFeatureCount, setProjectCredentialLookup, setRegistryPublishableSettings, setStoredAuthorName, shouldThrottle, shouldUseTiledRendering, shouldZoomToNewLayers, simpleStyleNumberValue, sortLayerGroupInPanel, splitProjectCredentials, stacAssetMediaType, stampFeatureCollectionEditorTracking, stampFeatureEditorTracking, stampFeaturePropertiesEditorTracking, storyLayerOpacityFactor, storyLocationView, storyMapHasContent, storyVisibleLayers, stringifyPopupValue, stripGoogleMapsApiKeyHeader, stripJoinFields, stripVirtualFieldColumns, styleValue, subscribeProjectRestoreHistory, substituteExpressionVariables, supportsBridgedOpacity, transformGeojsonElevation, trimHistoryBySize, undo, unescapePolyline, uniqueImportedLayerName, unmatchedGeocodeFeature, unresolvedLayerLibraryJoins, unsignedSourceUrl, useAppCapability, useAppStore, useLayer, useLayerIds, useLayerSummaries, useLayersWhen, validateAttributeFormField, validateAttributeFormValues, validateLayerDescriptiveMetadata, validateMapExpression, valueMapLabelFor, valueMapToText, vectorCircleColorValue, vectorColorExpression, vectorFillColorValue, vectorFillOpacityValue, vectorLineColorValue, vectorOutlineColorValue, vectorStrokeWidthValue, visiblePopupFields, visiblePopupProperties, withDatumShift, withGeoKeysDatumShift, withJpegTablesPatch, withoutHistory };
|
|
9012
|
+
export { ALL_APP_PRIVILEGES, ALL_DEPLOYMENT_CAPABILITIES, ARCGIS_PROJECTION_PRESETS, BLANK_BASEMAP, BLEND_MODES, BUILT_IN_STYLE_PRESETS, CARTOCIUDAD_MIN_INTERVAL_MS, CARTOCIUDAD_PUBLIC_HOST, CESIUM_BASEMAPS, CESIUM_BING_AERIAL_ASSET_ID, CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, CESIUM_ION_QUICK_PICKS, CESIUM_ION_SOURCE_KIND, CESIUM_KML_SOURCE_KIND, CESIUM_OSM_BUILDINGS_ASSET_ID, CHINA_BASEMAPS, CZML_QUICK_PICKS, CZML_SOURCE_KIND, DEFAULT_BASEMAP, DEFAULT_BLEND_MODE, DEFAULT_COLLABORATION_STATE, DEFAULT_DASHBOARD_COLUMNS, DEFAULT_EDITOR_IDENTITY, DEFAULT_EDITOR_TRACKING_CONFIG, DEFAULT_ELLIPSOID_ID, DEFAULT_FORWARD_GEOCODE_ENDPOINT, DEFAULT_GEOCODING_PROVIDER_ID, DEFAULT_LAYER_GROUP_OPACITY, DEFAULT_LAYER_STYLE, DEFAULT_LEGEND_CONFIG, DEFAULT_MAP_GRID_LAYOUT, DEFAULT_PRIMARY_RENDERER, DEFAULT_PRINT_LAYOUT, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_PREFERENCES, DEFAULT_REVERSE_GEOCODE_ENDPOINT, DEFAULT_ROUTING_ENDPOINT, DEFAULT_STORY_CHAPTER_DURATION_SECONDS, DEFAULT_STORY_MAP, DEPLOYMENT_CAPABILITIES, DUCKDB_VECTOR_FEATURE_WARN_COUNT, DUCKDB_VECTOR_ROUTE_BYTES, EARTH_MEAN_RADIUS_METERS, EDITOR_IDENTITY_STORAGE_KEY, ELEVATION_REQUEST_TIMEOUT_MS, ELLIPSOIDS, EXPRESSION_FUNCTION_CATEGORIES, ElevationFetchError, FEET_PER_METER, FEET_PER_MILE, GEOCODE_ATTRIBUTE_PREFIX, GEOCODE_DISPLAY_NAME_KEY, GEOCODE_LAT_KEY, GEOCODE_LON_KEY, GEOCODE_PROVIDER_KEY, GEOCODE_SCORE_KEY, GEOCODE_STATUS_KEY, GEOCODING_PROVIDERS, GOOGLE_MAPS_API_KEY_HEADER, GeocoderServiceError, GeocoderUnsupportedError, IDENTIFY_ALL_LAYERS_ID, LABEL_NUMBER_LOCALES, LABEL_NUMBER_SAMPLE, LARGE_VECTOR_FEATURE_THRESHOLD, LAYERS_FILE_TYPE, LAYERS_FILE_VERSION, LAYER_LIBRARY_BUNDLE_TYPE, LAYER_LIBRARY_BUNDLE_VERSION, LAYER_PALETTE, LAYER_STYLES_FILE_TYPE, LAYER_STYLES_FILE_VERSION, LAYER_TYPES, MAP_CRS_CHANGE_EVENT, MAP_CRS_PRESETS, MAX_DASHBOARD_COLUMNS, MAX_DIAGRAM_FEATURES, MAX_DIAGRAM_SCAN_FEATURES, MAX_LAYERS_FILE_BYTES, MAX_LAYER_LIBRARY_ENTRIES, MAX_LAYER_LIBRARY_ENTRY_BYTES, MAX_MAP_GRID_DIM, MAX_POINTS_PER_REQUEST, MAX_PROCESSING_HISTORY, MAX_PROJECT_BOOKMARKS, MAX_REDACT_DEPTH, MAX_STORY_CHAPTER_DURATION_SECONDS, MERCATOR_METERS_PER_PIXEL_AT_ZOOM_0, METERS_PER_FOOT, METERS_PER_MILE, METERS_PER_NAUTICAL_MILE, MIN_DASHBOARD_COLUMNS, MIN_DIAGRAM_SIZE, MIN_STORY_CHAPTER_DURATION_SECONDS, NETCDF_IMAGE_SOURCE_KIND, NOMINATIM_MIN_INTERVAL_MS, NOMINATIM_PUBLIC_HOST, NO_DEPLOYMENT_CAPABILITIES, NO_LAYERS, OPENFREEMAP_BASEMAPS, PHOTO_FULL_PROPERTY, PHOTO_PROPERTY, PLANETARY_BASEMAPS, PLANETARY_BASEMAP_GROUPS, PLANETARY_BASEMAP_SENTINEL_PREFIX, PLANET_SWITCHER_OPTIONS, POINTER_ELEVATION_CACHE_LIMIT, POINTER_ELEVATION_DEBOUNCE_MS, POPUP_IMAGE_HEIGHT_RANGE, POPUP_MAX_WIDTH_RANGE, PROJECT_CREDENTIAL_FIELDS, PROJECT_VERSION, PROTOMAPS_BASEMAPS, PUBLIC_GEOCODE_ROW_CAP, PUBLISHABLE_PLUGIN_SETTINGS, RAMP_STYLE_KEYS, RASTER_APPEARANCE_STATE_KEYS, REGIONAL_BASEMAPS, REGIONAL_BASEMAP_GROUPS, REGIONAL_BASEMAP_SENTINEL_PREFIX, ROLE_PRIVILEGES, RoutingRequestError, S3CorsError, S3_MAX_PRESIGN_SECONDS, SELECTION_MODES, SQL_QUERY_SOURCE_KIND, STAC_PROCESSING_EXTENSION, STAC_VERSION, STYLE_LIBRARY_BUNDLE_TYPE, STYLE_LIBRARY_BUNDLE_VERSION, SYMBOL_STYLE_KEYS, VECTOR_COLOR_RAMPS, activeLayerFilterExpression, activeQuickFilters, adaptBboxTemplateToCrs, addLayersToProject, allowsCredentialHeaders, appPrivilegeReason, applyCopiedLayerStyle, applyGroupEffects, applyJoinsToLayer, applyLayerJoins, applyLayerVirtualFields, applyMatchedSelection, applyProjectToStore, applySelectionMode, applyStoryLayerOpacity, arcgisLocatorInputField, attributeFormFieldLabel, attributeLinkUrl, availableCesiumBasemap, basemapToCesiumImagery, batchDecodePolylines, bodyLengthToEarth, buildForwardGeocodeUrl, buildIsochroneRequest, buildLayerPanelUnits, buildLayerStacItem, buildLayerTree, buildMatrixRequest, buildReverseGeocodeUrl, buildRouteRequest, canRedoProjectRestore, canSaveLayerToLibrary, canUndoProjectRestore, captureLayerLibraryEntry, cascadeLayerJoinRefresh, cesiumIonAssetId, cesiumIonAssetKind, cesiumKmlSource, changedPreferenceCredentials, circleRadiusValue, clampLabelDecimals, clampLatitude, clearExternalNativePaintBridge, clearHistory, clearQuickFilterValues, coerceAttributeFormValue, collectDiagramData, collectTransitiveJoinSourceIds, compareSequenceValues, compileFeatureExpression, compileLayerFilters, compileQuickFilter, compileQuickFilters, computeGeoArrowBBox, controlRendersLayer, convertTiffYCbCrToRgb, copyableLayerStyleKind, createCesiumIonLayer, createCesiumKmlLayer, createCzmlLayer, createDefaultAppCapabilities, createDefaultMapView, createDefaultPrintLayout, createEmptyProject, createEqualIntervalBreaks, createGraduatedClassBreaks, createLayerLibraryEntryId, createPointerElevationResolver, createProjectLayerSerializationCache, createProjectTemplate, createQuantileBreaks, createSampleStoryMap, createStyleLayerEvaluator, createStyleLibraryEntryId, csvRowsToGeocodeRequests, currentEditorIdentity, czmlSource, darkenHex, datumShiftFor, decodePolyline, decodePolylineDetailed, deriveTileMatrixSet, detachProjectCopy, detectNonGeographicCoordinates, diagramAnchor, diagramPixelSize, diagramsSuppressedByPointRenderer, diffFeatureCollections, diffProjects, documentLocale, dominantGeometry, drawMarkerPath, earthAreaToBody, earthLengthToBody, editorTrackingFieldNames, effectiveLayerRenderState, effectiveVectorRules, encodePolyline, encodeS3Key, ensureEditorTrackingFields, environmentVariableAccount, evaluateMapExpression, excludeHiddenFieldsFromGeojson, excludeHiddenFieldsFromProject, explainS3ReadError, extractCopiedLayerStyle, extractLayerStyleEntries, extractLayersFileContent, extractStyleLibraryStyle, extrusionColorValue, extrusionHeightValue, featureCollectionToGeoArrow, featureSelectionId, fetchArcGISLocatorInfo, fetchElevations, findLayerStyleEntryIndex, formatCameraAltitude, formatExpressionPreviewValue, formatLabelNumber, formatLabelNumberSample, formatPixelValue, formatPopupValue, formatRoundNum, formatS3Uri, generatorCircleRadiusValue, generatorSizeRange, geoArrowToFeatureCollection, geoJSONToPolylineStr, geocodeForward, geocodeMatchToFeature, geocodeReverse, geocodeSuggest, geocoderMinIntervalMs, geocoderNeedsApiKey, geocoderSupportsReverse, geocoderSupportsSuggest, geocodingApiKeyAccount, geojsonHasZCoordinates, getActiveBodyRadiusRatio, getActiveEllipsoid, getActiveMeanRadiusMeters, getActiveSemiMajorAxisMeters, getArcgisApiKey, getAttributeFormField, getBuildEnvironment, getCesiumIonToken, getEllipsoid, getExternalNativePaintBridge, getGeocoderConfig, getGeocodingProvider, getGoogleMapsApiKey, getHistoryCoalesceMs, getMapCrsPreset, getMapboxAccessToken, getMaxHistoryFeatureCount, getPlanetaryBasemapById, getPlanetaryBasemapByStyleUrl, getProtomapsApiKey, getProtomapsStyleUrl, getRegionalBasemapById, getRegionalBasemapByStyleUrl, getRoundNum, getRoutingConfig, getRuntimeEnvironment, getS3UrlSigner, getSpatialExtensionPath, getVectorColorRamp, googleMapsApiKeyHeaderValue, groupMemberIndices, hasActiveLayerFilter, hasActiveQuickFilter, hasAppPrivilege, hasHeaderReferences, hasPathTraversal, hasRestorableLayerSource, hasSimpleStyleProperties, heatmapRampColors, horizontalBbox, hydrateProjectLayer, identifyAllIncludes, identifyStateWithoutLayers, inferFieldTypes, inferLayerCapabilities, initialLayerStyle, installCogTilerDatumShift, interpolateColors, interpolateHexColor, interpolateRampColors, intersectPrivileges, invertSelection, isAbbreviatedJpegCompression, isAbsoluteFilesystemPath, isAdoptedVectorAwaitingFeatures, isAllowedPluginManifestUrl, isAttributeFormFieldVisible, isCesiumIonLayer, isCesiumKmlLayer, isCesiumOnlyLayer, isCredentialFieldName, isCredentialUrlParam, isCredentialedS3Url, isCzmlLayer, isDefaultPrintLayout, isDeploymentCapability, isDiagramStyleEnabled, isDuckDBQueryLayer, isExternalNativeLayerRecord, isGeoArrowBatch, isGooglePhotorealisticTilesetUrl, isHeaderReferenceOnly, isHexColor, isInitialLayerStyle, isInlineImageValue, isInternalPopupField, isIpadDesktopUserAgent, isMaintainedEditorTrackingField, isMapClickClaimed, isPopupClickEnabled, isPopupHoverEnabled, isRasterMarkerSource, isReferencedLayer, isRegionalBasemapSentinel, isS3Uri, isSafePopupUrl, isSecretEnvironmentVariable, isSessionOnlyLayer, isStoryHiddenLayer, isStyleLibraryTargetLayer, isStyleSpecColor, isSvgMarkerResponse, isValidMetadataDate, isValidMetadataEmail, isValidMetadataUrl, isVectorColorExpression, isochroneResponseToFeatures, jsonValuesEqual, labelFieldTextField, layerGroupDepth, layerGroupMoveability, layerGroupSortability, layerJoinKey, layerLibraryConfigPatch, layerLibraryEntryNeedsLocalFile, layerLocalPath, layerPanelGroupHeaders, lineWidthValue, localFileName, lookupProjectCredential, mapZoomStepOutputs, matchFeaturesByExpression, matchLayerStyleEntry, matrixResponseToFeatures, meanRadiusMeters, mercatorMetersPerPixelAtZoom0, mergeAttributeFormConfigs, metadataDateToRfc3339, metersWidthExpression, nextDelayMs, nextLayerPaletteColor, nominatimResultToFeature, nominatimReverseResultToDisplay, nonEmptyRecord, normalizeAppPrivileges, normalizeArcGISLocatorUrl, normalizeArcgisWkid, normalizeBlankBackgroundColor, normalizeBookmarkGroups, normalizeBookmarks, normalizeCesiumBasemap, normalizeDashboardColumns, normalizeGeocodingLocator, normalizeGeocodingProviderId, normalizeGroupContiguity, normalizeHexColor, normalizeLayerCapabilities, normalizeLayerDescriptiveMetadata, normalizeLayerLibraryEntries, normalizeLayerStyleEntries, normalizeLayersFileContent, normalizeLegendConfig, normalizeLongitude, normalizeMapCrs, normalizeMapLayout, normalizeMapViewState, normalizeModelGraph, normalizeModels, normalizeObiaWorkbench, normalizePrimaryRenderer, normalizePrintLayoutConfig, normalizeProcessingHistory, normalizeProjectComments, normalizeProjectInteraction, normalizeSecondaryMapViews, normalizeStoryChapterDurationSeconds, normalizeStoryMap, normalizeStyleLibraryEntries, normalizeWidgets, overlayStoredEnvironmentVariables, overlayStoredGeocodingApiKeys, overlayStoredPreferenceCredentials, parseArcGISLocatorInfo, parseArcGISSuggestions, parseCesiumIonAssetId, parseContours, parseCzml, parseDeploymentCapabilities, parseHexColor, parseHexColorList, parseJsonExpression, parseLayerLibrary, parseLayerStylesFile, parseLayersFile, parseMapCrsEpsgCode, parseMetadataKeywords, parseProject, parseS3BucketList, parseS3Error, parseS3ListObjects, parseS3Url, parseStoryMapCsv, parseStoryMapJson, parseStyleLibrary, parseValueMapText, patchJpegCogSource, persistedThreeDTilesRequestHeaders, pickEditorIdentity, planLayerLibraryAdd, pluginOwnsPaint, polylineStrToGeoJSON, popupFieldLabel, portableWmsTileUrl, presignS3Url, previewValue, printLayoutConfigsEqual, projectFromStore, projectPathLabel, proportionalRadiusExpression, proportionalSizeRange, readStoredAuthorName, reapplyLayerJoins, redactConfigurationCredentials, redactCredentials, redactProjectCredentials, redactUrlCredentials, redo, registerMapClickClaim, registerProjectRestoreHistory, registerS3UrlSigner, removeTrailingJsonCommas, rendererAppliesOpacity, reorderLayerGroupInPanel, requestIsochrone, requestMatrix, requestNavigationRoute, requestRoute, resolveConfiguredPopupTitle, resolveEditorTrackingConfig, resolveGeocoderConfig, resolveHeaderReferences, resolveIdentifyTarget, resolveLabelNumberLocale, resolveLayerCapabilities, resolveMapGrid, resolvePopupBody, resolvePopupImageHeight, resolvePopupMaxWidth, resolvePopupRows, resolvePopupTitle, resolveProjectHeaderReferences, resolveReadableUrl, resolveRolePrivileges, resolveSvgSource, resolveThreeDTilesRequestHeaders, rgbToHex, routeResponseToFeatures, rowCap, ruleBasedColorExpression, ruleBasedVisibilityFilter, s3ObjectHttpsUrl, sameCesiumImagery, sampleMapTerrain, sampleMapTerrainPoint, sampleRemoteElevations, sanitizeLayerStylePatch, scaleAltitudeToActiveBody, scaleDenomination, scaleSpan, scrubCommentsForRemovedLayers, scrubLegendForRemovedLayers, scrubPrintLayoutForLayers, scrubPrintLayoutForRemovedLayers, scrubWidgetsForRemovedLayers, selectLayerById, selectLayerIds, selectLayerSummaries, selectLayersWhen, selectedGeocodingLocator, serializeLayerLibrary, serializeLayerStylesFile, serializeLayersFile, serializeProject, serializeProjectWithLayerCache, serializeProjectWithLayerCacheAsync, serializeStoryMapCsv, serializeStoryMapJson, serializeStyleLibrary, setActiveEllipsoidId, setExternalNativePaintBridge, setGeocodingFetch, setGeocodingTokenProvider, setHistoryCoalesceMs, setMaxHistoryFeatureCount, setProjectCredentialLookup, setRegistryPublishableSettings, setStoredAuthorName, shouldThrottle, shouldUseTiledRendering, shouldZoomToNewLayers, simpleStyleNumberValue, sortLayerGroupInPanel, splitProjectCredentials, stacAssetMediaType, stampFeatureCollectionEditorTracking, stampFeatureEditorTracking, stampFeaturePropertiesEditorTracking, storyLayerOpacityFactor, storyLocationView, storyMapHasContent, storyVisibleLayers, stringifyPopupValue, stripGoogleMapsApiKeyHeader, stripJoinFields, stripVirtualFieldColumns, styleValue, subscribeProjectRestoreHistory, substituteExpressionVariables, supportsBridgedOpacity, transformGeojsonElevation, trimHistoryBySize, undo, unescapePolyline, uniqueImportedLayerName, unmatchedGeocodeFeature, unresolvedLayerLibraryJoins, unsignedSourceUrl, useAppCapability, useAppStore, useLayer, useLayerIds, useLayerSummaries, useLayersWhen, validateAttributeFormField, validateAttributeFormValues, validateLayerDescriptiveMetadata, validateMapExpression, valueMapLabelFor, valueMapToText, vectorCircleColorValue, vectorColorExpression, vectorFillColorValue, vectorFillOpacityValue, vectorLineColorValue, vectorOutlineColorValue, vectorStrokeWidthValue, visiblePopupFields, visiblePopupProperties, withDatumShift, withGeoKeysDatumShift, withJpegTablesPatch, withoutHistory };
|
|
9983
9013
|
|
|
9984
9014
|
//# sourceMappingURL=index.mjs.map
|