Files
Qiusheng Wu 1c3bec9869 fix(map): load Mapbox GL from its CDN instead of bundling it (#3294)
* fix(map): load Mapbox GL from its CDN instead of bundling it

Mapbox GL JS v2+ is proprietary, but the web, desktop and store builds
and the Python wheel have shipped it as a chunk since v3.1.0. Load the
script and stylesheet from Mapbox's CDN when a Mapbox pane mounts, pinned
by version and SRI hash to the installed package. The build now fails if
mapbox-gl reaches a chunk.

Also ship the gdal3.js LGPL license and a source link with every build,
and link third-party licenses from the About dialog.

* fix(deps): upgrade node-forge to 1.4.2 for new advisories

Five high node-forge advisories published on 2026-10-30 fail the audit
gate on every PR. All are patched in 1.4.1, which also clears the only
allowlist entry, so drop it.

* Address review feedback

- Inline the Mapbox stylesheet through fetch. A <link> was blocked by
  style-src in both CSPs, so every Mapbox pane failed outside vite preview.
- Refuse the CDN load in GEOLIBRE_NO_EXTERNAL_CDN builds and document it.
- Make the test's fake remove() idempotent, as a real element's is.
- Use new Map() for the empty audit allowlist.

* Fix stylesheet URL assertion in the Mapbox loader test

SVG data URIs contain url(#clip) references of their own, so strip whole
data URIs before asserting that no other url() remains.

* fix(map): stop MapLibre's class registry breaking Mapbox tiles

MapLibre 6 permanently sets _classRegistryKey on the global Set and Error.
Mapbox's serializer reads the same property, fails looking the key up in
its own registry, and no tile loads ("reading 'omit'"). Rename MapLibre's
private copy at build time, including in the dev dependency optimizer.

Also theme Mapbox's native and shared map controls in dark mode, and
retry only the failed half of the CDN load.

* fix(map): keep Mapbox control hover readable in dark mode

mapbox-gl paints #eee behind any hovered button in a control, so the
layer control's unclassed toggle lost its light icon against the
background. Use the theme's accent color in dark mode.

* Address review feedback

- Keep Mapbox's active geolocate icon colored in dark mode, as on MapLibre.
- Reload a script that ran without defining mapboxgl, since it still fires
  load.
- Cover a stylesheet-only retry, and reset the loader between tests.
- Wait for the style in the retry test instead of relying on microtask
  order.
- Fail the registry contract test if the plugin stops matching MapLibre.

* Address review feedback

- Reject any Mapbox GL module at load time, so its stylesheet is caught as
  well as its script.
- Keep the MapLibre registry rename the same length, so source maps stay
  correct.
- Leave the inverted attribution button out of the dark hover color, which
  the invert would turn light behind its icon.

* Address review feedback

- Describe the dark hover rule's specificity correctly in its comment.
2026-10-31 01:13:02 -04:00

172 lines
6.4 KiB
YAML

site_name: GeoLibre
site_description: A lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data across desktop and web environments, with a responsive layout for mobile screens.
site_url: https://geolibre.app
repo_name: opengeos/GeoLibre
repo_url: https://github.com/opengeos/GeoLibre
edit_uri: edit/main/docs/
# Output directory, set explicitly so the build target stays pinned to `site/`
# (matching the Pages upload paths) rather than relying on the tool's
# default, which a Zensical 0.0.x patch could shift.
site_dir: site
theme:
name: material
logo: assets/geolibre-icon.png
favicon: assets/geolibre-icon.png
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: indigo
toggle:
icon: material/weather-night
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: indigo
toggle:
icon: material/weather-sunny
name: Switch to light mode
features:
- navigation.instant
- navigation.sections
- navigation.top
- search.highlight
- search.share
- search.suggest
- toc.follow
nav:
- Home: index.md
- Getting Started: getting-started.md
- Features: features.md
- Comparison: comparison.md
- Demos: demos.md
- Gallery: gallery.md
- Downloads: downloads.md
- Sponsor: sponsor.md
# Keep this deployment-relative: production serves at /, while PR previews
# are nested under /pages-preview/GeoLibre/pr-<number>/.
- Launch GeoLibre Web: https://web.geolibre.app
- User Guide:
- Interface Overview: user-guide/interface.md
- Rendering Engines: user-guide/rendering-engines.md
- Projects: user-guide/projects.md
- Adding Data: user-guide/adding-data.md
- Supported Data Formats: data-formats.md
- Chrome Extension: user-guide/chrome-extension.md
- Managing Layers: user-guide/layers.md
- Styling Layers: user-guide/styling.md
- Attribute Table: user-guide/attribute-table.md
- Map Controls & Tools: user-guide/map-controls.md
- GPS Tracking & Field Collection: user-guide/field-collection.md
- Print Layout: user-guide/print-layout.md
- Processing Tools: user-guide/processing.md
- Model Builder: user-guide/model-builder.md
- Object-Based Analysis: user-guide/obia.md
- Coming from eCognition: user-guide/obia-ecognition.md
- AI Segmentation: user-guide/segmentation.md
- Point Cloud Annotation: user-guide/point-cloud-annotation.md
- SQL Workspace: user-guide/sql-workspace.md
- Python Console: user-guide/python-console.md
- AI Assistant: user-guide/ai-assistant.md
- Data Integrations: user-guide/data-integrations.md
- Cloud Storage (S3): user-guide/cloud-storage.md
- Plugins & Marketplace: user-guide/plugins.md
- Web Services: user-guide/web-services.md
- Settings & Preferences: user-guide/settings.md
- Story Maps: user-guide/storymaps.md
- Embedding & Sharing: user-guide/embedding.md
- Troubleshooting: user-guide/troubleshooting.md
- Tutorials:
- Overview: tutorials/index.md
- Video Tutorials: tutorials/videos.md
- Your First Map: tutorials/first-map.md
- Cloud-Native Data: tutorials/cloud-native-data.md
- Vector Analysis: tutorials/vector-analysis.md
- Terrain Analysis: tutorials/terrain-analysis.md
- Spatial SQL: tutorials/spatial-sql.md
- Sharing & Embedding: tutorials/sharing-embedding.md
- Format Reference: tutorials/supported-formats-en.md
- Format Reference (中文): tutorials/supported-formats-zh.md
- Source Code Deep Dive: tutorials/source-code-deep-dive-en.md
- Source Code Deep Dive (中文): tutorials/source-code-deep-dive-zh.md
- Reference:
- Architecture: architecture.md
- MapLibre Renderer: maplibre-renderer.md
- Mapbox Renderer: mapbox-renderer.md
- Cesium Renderer: cesium-renderer.md
- ArcGIS Renderer: arcgis-renderer.md
- Self-Hosting: self-hosting.md
- Server API: server-api.md
- Android: android.md
- iOS: ios.md
- Mac App Store: mac-app-store.md
- Project Format: project-format.md
- Plugin API: plugin-api.md
- Collaboration: collaboration.md
- UI Profiles: ui-profiles.md
- Deployment Capabilities: deployment-capabilities.md
- Deployment Policy: deployment-policy.md
- Internationalization: i18n.md
- Python Package: python.md
- R Package: r.md
- MCP Server: mcp.md
- Agent Skill: agent-skill.md
- Notebook Panel: notebook.md
- Roadmap: roadmap.md
- Contributing: contributing.md
- Maintenance Notes: maintenance.md
- Third-Party Licenses: third-party-licenses.md
- How to Cite: citation.md
- Acknowledgements: acknowledgements.md
- Privacy Policy: privacy.md
- Terms of Service: terms.md
plugins:
- search
markdown_extensions:
- admonition
- attr_list
- md_in_html
- toc:
permalink: true
- pymdownx.details
- pymdownx.highlight
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
extra_css:
- stylesheets/extra.css
extra:
# Google Analytics for geolibre.app, configured entirely from the environment
# so the tracker only loads where a measurement ID is set: the production
# Pages deploy. A local `zensical build`, a fork, and a PR preview leave these
# unset and ship no tracker, which is also why the ID is not hard-coded here.
#
# `provider` is a second variable because the theme keys the whole integration
# off it: with a provider and a blank property it would still load gtag.js,
# pointed at nothing. .github/workflows/pages.yml derives it from
# GEOLIBRE_GA_MEASUREMENT_ID, so an operator only ever sets that one value.
analytics:
provider: !ENV [GEOLIBRE_ANALYTICS_PROVIDER, ""]
property: !ENV [GEOLIBRE_GA_MEASUREMENT_ID, ""]
social:
- icon: fontawesome/brands/github
link: https://github.com/opengeos/GeoLibre
name: GeoLibre on GitHub
- icon: fontawesome/solid/heart
link: https://github.com/sponsors/giswqs
name: Sponsor GeoLibre on GitHub
- icon: fontawesome/solid/mug-hot
link: https://buymeacoffee.com/giswqs
name: Buy the maintainer a coffee