Skip to content

Changelog

All notable changes to @geoleaf/core are documented here.

Format: Keep a ChangelogSemantic Versioning.


[Unreleased]

Added

  • @geoleaf-plugins/cog : nouveau plugin premium de rendu Cloud Optimized GeoTIFF (COG). Lecture native via geotiff@^3.0.5 avec sélection d'overview automatique selon le viewport, rendu multi-bandes (1/3/4 canaux, nodata transparent, LUT colorMap), injection comme source image MapLibre GL JS. API : GeoLeaf.COG.addLayer(url, map, opts?), GeoLeaf.COG.removeLayer(map, id), GeoLeaf.COG.getInfo(url, opts?). Bundle séparé du core, licence commerciale, distribué via GitHub Packages.
  • @geoleaf-plugins/flatgeobuf : nouveau plugin MIT de chargement FlatGeobuf. Streaming via async iterator (flatgeobuf v4.4.0), filtrage spatial bbox via R-tree index + HTTP Range requests, auto-refresh debounced sur viewport. API : GeoLeaf.FlatGeobuf.load(url), loadBbox(url, bbox), loadAsLayer(url, options?), loadBboxAsLayer(url, bbox, options?). Bundle séparé du core (~91 KB raw / 20 KB gzip).
  • @geoleaf-plugins/file-import : nouveau plugin MIT d'import de fichiers géospatiaux. Formats supportés : GPX, KML, KMZ, CSV (lat/lng ou WKT), TopoJSON. API : GeoLeaf.FileImport.convert(file), importAsLayer(file, options?), getSupportedFormats(), registerConverter(ext, converter). Bundle séparé du core (~276 KB raw).
  • Geocoding : 31ème export nommé ESM. Module de recherche d'adresse lazy-loadé (_loadModule("geocoding")), API GeoLeaf.Geocoding. Quatre fournisseurs intégrés : addok, nominatim, photon, URL personnalisée.
  • geoleaf:geocoding:result : nouvel événement émis lors de la sélection d'un résultat de géocodage — payload { label, lat, lng, bounds? }.
  • GeocodingConfig dans ui.json ou geoleaf.config.json : paramètres enabled, provider, position, placeholder, minChars, resultLimit, debounceMs, flyToZoom.
  • Terrain 3D : support du relief 3D sur basemaps raster (type: "tile") et vectoriels (type: "maplibre"). Configuration via basemaps.{id}.terrain (enabled, demUrl, demEncoding, demMaxZoom, exaggeration, default3D, pitch, bearing). Activation automatique sans toggle UI — default3D: true active le terrain au switch vers le basemap, false le désactive. Source DEM validée en production : AWS Terrarium (~30m).
  • map.maxPitch dans profile.json : plafond d'inclinaison caméra configurable. GeoLeaf lève la limite MapLibre GL JS par défaut (60°) à 80°. Valeur par défaut : 80. Configurable via profile.json > map.maxPitch.
  • Fill-Extrusion : support des polygones 3D via le type de layer MapLibre GL JS fill-extrusion. Configurer geometry: "fill-extrusion" dans le fichier config de couche, puis définir fillExtrusionColor, fillExtrusionOpacity, fillExtrusionHeight et fillExtrusionBase dans le fichier style. fillExtrusionHeight accepte une valeur fixe (mètres) ou un nom de champ feature (ex. "hauteur"). La validation est assurée par style-validator-extrusion.ts : erreur si fillExtrusionHeight manquant, warning si le champ n'est pas trouvé dans les propriétés du premier feature.
  • GeoLeaf.Utils.wktToGeoJSON(wkt) : convertit une chaîne WKT en objet géométrie GeoJSON. Supporte les 7 types standardisés (Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection) en 2D et 3D/Z. Supporte le préfixe SRID (SRID=4326;…) et les qualificateurs Z/M/ZM. Retourne null sans exception si l'entrée est invalide.
  • OGC API Features : support natif du chargement de couches GeoJSON depuis un endpoint OGC API Features. Configurer data.ogcApi dans la définition de couche : url, collectionId, bbox, maxFeatures, limit, autoRefresh, autoRefreshDebounce, headers. Pagination automatique via liens next, garde-fou maxFeatures, annulation via AbortController, conversion automatique des géométries WKT. Mode autoRefresh: true : re-fetch sur moveend avec bbox viewport courant.
  • .topojson et .fgb ajoutés à la validation FileValidator (préparation plugins Sprint 3/4).
  • Basemap type: "image" : nouveau type de fond de carte pour images géoréférencées statiques (format natif MapLibre image). Configuration via basemaps.{id}.imageSource (url, coordinates, opacity). L'image est positionnée selon 4 coins [lng, lat] ; sans coordinates, les limites monde sont utilisées par défaut.
  • Basemap type: "hillshade" : ombrage du relief via couche MapLibre hillshade. Configuration via basemaps.{id}.hillshade (demUrl, demEncoding, demMaxZoom, shadowColor, highlightColor, accentColor, exaggeration, illuminationDirection, illuminationAnchor). Réutilise automatiquement la source DEM terrain-dem si elle est déjà présente avec la même URL (compatible avec type: "tile" terrain 3D).
  • Basemap type: "wmts" : support des serveurs WMTS OGC via résolution dynamique du GetCapabilities. Configuration via basemaps.{id}.wmts (getCapabilitiesUrl, layer, tileMatrixSet, format). Parsing XML namespace-safe, cache in-memory des URL résolues, annulation via AbortController.
  • Basemap type: "wms" : support des serveurs WMS OGC (flux raster). Configuration via basemaps.{id}.wms (url, layers, version, crs, format, tileSize, transparent, styles). Construit l'URL template avec placeholder {bbox-epsg-3857} compatible MapLibre GL JS.

Changed

  • Extraction GPX du core : la conversion GPX→GeoJSON (méthode DataConverter.convertGpxToGeoJSON() + helpers privés) a été retirée de @geoleaf/core et migrée vers @geoleaf-plugins/file-import. Le pipeline route (route-utils.ts::parseGPX()) et la normalisation (normalizer.ts::normalizeFromGPX()) ne sont pas affectés. Interface DataConverterLike mise à jour (retrait de convertGpxToGeoJSON()). Le loader single-layer.ts n'a plus de branche isGpx — simplification du flux de chargement.

Fixed

  • Fill-extrusion plates au chargement : les couches fill-extrusion s'affichaient à plat (hauteur 0) au chargement initial et après changement de style. Cause : l'objet style complet { id, label, style: {…} } était passé directement aux fonctions de rendu au lieu du paint plat — toFillExtrusionPaint() ne trouvait pas les clés fillExtrusionHeight etc. à la racine. Corrigé dans theme-applier/visibility.ts et vector-tiles.ts.
  • Style actif perdu après changement de basemap : les couches GeoJSON (dont fill-extrusion) revenaient systématiquement au style par défaut après chaque switch de basemap. Cause : _rebuildGeoJSONLayers() lisait .defaultStyle sur un paint plat, toujours undefined. Corrigé par la lecture currentStyle.style ?? currentStyle.
  • Sous-couche line parasite sur les couches fill-extrusion : une sous-couche line était générée par-dessus les volumes 3D, produisant un rendu parasite. Corrigé par un guard geometry !== "fill-extrusion" dans maplibre-helpers.ts.
  • Couches vector tiles invisibles après switch de basemap : les couches VT n'étaient pas rechargées après un changement de basemap (elles étaient ignorées dans _rebuildGeoJSONLayers car features: []). Corrigé par une branche dédiée isVectorTile === true déclenchant loadVectorTileLayer().

[2.0.0] - 2026-03-22

First public release on npm. See the full release notes for complete details.

⚠️ Breaking Changes

  • Leaflet → MapLibre GL JS v5 : moteur de rendu remplacé. Supprimer leaflet / leaflet.markercluster, ajouter maplibre-gl@^5.0.0 en peer dependency.
  • Convention coordonnées : [lat, lng] (Leaflet) → [lng, lat] (GeoJSON/MapLibre standard).
  • Scope npm renommé : geoleaf@geoleaf/core.
  • UMD supprimé : distribution ESM-only. Remplacer <script src="geoleaf.umd.js"> par <script type="module">.
  • container:mapId: : clé d'initialisation du conteneur carte renommée.
  • applyTheme(theme)applyTheme(layerId, themeId) : signature changée.
  • CSS : classes .leaflet-*.maplibregl-* (MapLibre) + .gl-* (GeoLeaf interne).

Added

  • MaplibreAdapter : implémentation complète de IMapAdapter (33 méthodes) — rendu WebGL, clustering GPU natif, MVT/PBF vector tiles.
  • @geoleaf/connector v1.0.0 (MIT, npm public) : intercepteur fetch universel pour sources géospatiales authentifiées (GeoJSON, WFS, vector tiles, PMTiles).
  • Basemaps : CARTO Positron / Dark Matter / Voyager, ESRI Street, support pmtiles://.
  • Performance marks : window.__GEOLEAF_PERF__ = true active 8 paires de marks (TTI, boot, modules...).
  • Architecture TypeScript : lazy-module-loader.ts, loader-types.ts (13 interfaces service locator), contracts enrichis (api.contract.ts, ui-controls.contract.ts, map-adapter.contract.ts).
  • Sécurité : module CSRF complet (csrf-token.ts), DOMSecurity.setSafeHTML() systématique, CSS.escape() sur POI IDs.
  • Accessibilité : prefers-reduced-motion, :focus-visible, aria-label + role="img" sur markers MapLibre.
  • Documentation : site VitePress geoleaf.dev/docs/, TypeDoc dual entries, 273 fichiers déployés.

Changed

  • Build : UMD supprimé — 3 sorties ESM (bundle full chunked, preserveModules, lite sans table/labels/route/search).
  • Tests : migration complète Jest → Vitest 3 + Istanbul — 323 suites, 8 317 tests, couverture branches 77,97 %.
  • TypeScript strict : 30 @ts-nocheck supprimés, 0 erreur tsc --noEmit --strict.
  • Dead code : 7 fichiers orphelins et 172 exports morts supprimés (Knip).
  • Filtres GeoJSON : nouveau chemin MapLibre via updateLayerData() sans corruption du dataset source.

Fixed

  • Basemap raster s'affichait au-dessus de toutes les couches GeoJSON/POI/route.
  • Style selector niveau racine — wrapper non déroulé avant normalizeToFlat().
  • Clustering natif MapLibre — options cluster/clusterRadius/clusterMaxZoom non propagées à la source.
  • Side panel vide — objets imbriqués sérialisés en JSON string par MapLibre lors des clics.
  • Échelle graphique invisible — classes CSS .gl-scale-graphic absentes.
  • Labels glyphs 404 — _resolveMapFontStack() avec fallback dynamique.
  • Visibilité zoom ignorée après changement de thème.
  • StyleRules data-driven inopérantes — préfixe "properties." incorrect dans les expressions MapLibre.

Performance

Métriquev1.x (Leaflet)v2.0.0 (MapLibre)
10 000 markers4 FPS (DOM)60 FPS (GPU)
10 000 GeoJSON572 ms< 100 ms WebGL
ESM bundle gzip35 KB~35 KB
UMD bundle196 KB gzip❌ supprimé

Migration

Released under the MIT License.