[general]
name=MapSplat
qgisMinimumVersion=4.0
qgisMaximumVersion=4.99
description=Export QGIS projects to static web maps using PMTiles and MapLibre GL JS
version=0.43.1
author=John Zastrow
email=mapsplat@example.com

about=MapSplat exports your QGIS project layers to self-contained web map packages that can be hosted on any static web server. It converts vector and raster layers to PMTiles format and generates a ready-to-deploy HTML viewer using MapLibre GL JS.

    Features:
    - Export vector layers to PMTiles format
    - Export raster layers as basemap tiles
    - Automatic symbology conversion to MapLibre styles
    - Self-contained offline viewer (no CDN required)
    - Style roundtripping with Maputnik editor
    - Auto-reprojection to Web Mercator (EPSG:3857)

tracker=https://github.com/johnzastrow/mapsplat4/issues
repository=https://github.com/johnzastrow/mapsplat4

hasProcessingProvider=no

changelog=
    0.43.1 - Republish for the QGIS plugin repository
    - Version bump to publish the validated build (Qt6 scoped enums and the lint/security gates
      cleared). The generated viewer's version stamp now reflects the real plugin version. No
      behavioural change.
    0.43.0 - Layer order follows the QGIS layer tree
    - The exported map now stacks layers in your QGIS layer-tree order: the top layer in the QGIS
      panel renders on top in the web map (and appears at the top of the layer list). Rearrange your
      layers in QGIS and the export follows — you control the order directly, including where imagery
      and tile basemaps sit. (The added Protomaps basemap stays at the very bottom.)
    0.42.0 - Group on/off toggles + restore the 'My Layers' QGIS group
    - Each collapsible section in the viewer's layer list (My Layers, Carto, Basemap, ...) now has a
      checkbox in its header that shows/hides ALL layers in the group at once; it reflects the child
      state (all / none / mixed).
    - Fixed a regression where QGIS layer-tree groups (e.g. 'My Layers') stopped appearing after the
      source-aware TOC grouping change.
    0.41.1 - Fix render order: basemaps below your data
    - Tile/raster layers (XYZ imagery like Google Satellite, vector-tile bases like Carto) now always
      render BELOW your vector data instead of being interleaved or stacked on top. Previously a full
      vector-tile basemap could sit on top and cover everything, and an opaque XYZ raster could hide
      the data layers beneath it.
    0.41.0 - Basemap layers under a collapsible 'Basemap' section; base layers at the bottom
    - The basemap's many sub-layers (roads, water, landuse, ...) now collapse under a 'Basemap' section
      in the viewer's layer list instead of sitting at the top level. The base sections (styled vector
      tiles like Carto, and the Basemap) now appear at the BOTTOM of the list, below your own data
      layers — matching the map's base-at-bottom rendering order.
    0.40.0 - Group a vector tile layer's sub-layers under their own TOC section
    - A styled vector tile layer (e.g. Carto) adds many sub-layers (water, roads, labels, ...). They
      now appear under their own collapsible section in the viewer's layer list, named after the
      layer, instead of cluttering the top level. The TOC also groups source-aware now, so a provider's
      'water'/'landcover'/... no longer merge with the basemap's identically-named layers.
    0.39.6 - Fix missing base64 import (0.39.5 regression)
    - 0.39.5 added the favicon using base64 but the module import was missing, so HTML generation
      raised NameError and no viewer could be written. Added the import; full test suite green again.
    0.39.5 - Resilient viewer: one bad layer no longer blanks the whole map
    - The viewer now adds data layers one at a time and skips (logs) any layer MapLibre rejects, so a
      single invalid layer can't reject the entire style and leave a blank map.
    - Duplicate layer ids (which MapLibre rejects outright) are renamed at export; a fetched provider
      GL style's layer ids are namespaced so generic names (water, landcover, ...) don't collide with
      the basemap. Fixes a blank map when a Carto vector basemap was added.
    - The exported page now uses the MapSplat icon as its favicon (also stops the favicon.ico 404).
    0.39.4 - Use a vector tile layer's own GL style (fetch styleUrl)
    - A vector tile (MVT) layer added in QGIS with a Style URL now renders: MapSplat reads the styleUrl
      from the layer source, fetches that Mapbox-GL style at export time, and uses its layers (so e.g.
      Carto basemaps 'just work' instead of being skipped). Provider fonts/icons aren't bundled, so
      labels/icons may be partial when a separate basemap is also used.
    0.39.3 - Fix false PMTiles verify failures (benign zoom-header mismatch)
    - 'Verify PMTiles after export' no longer fails normal exports. GDAL's PMTiles writer stamps
      MinZoom=0 in the header even when small features only tile at a higher zoom, so `pmtiles verify`
      reported a header/tile zoom mismatch — a benign metadata quirk, not corruption. That case is now
      logged as a note and passes; real corruption (bad magic, structure) still fails.
    0.39.2 - Pre-upload hygiene: remove duplicate method, fix stale unit tests, gate clean
    - Removed a duplicate _plugin_version() in the dock (flake8 F811). Fixed style_converter unit-test
      mocks that had gone stale since the fill-paint refactor (missing layerType/opacity/orderByEnabled)
      — the full suite (173) now passes. flake8 clean; Bandit no High/Medium; metadata + packaging valid.
    0.39.1 - Layer ordering + unstyled MVT handling
    - Tile/raster layers (e.g. an XYZ raster) now appear in the map + TOC at their selected-layer
      position instead of always at the bottom of the stack.
    - A vector tile (MVT) layer with no usable style is now skipped cleanly (no dead source in the
      output) with actionable guidance, instead of leaving an empty, non-rendering source.
    0.39.0 - TOC entries for every layer (raster, XYZ, online, basemap)
    - The viewer's layer list previously only showed vector layers (those with a source-layer). Raster
      layers, the XYZ raster basemap, online XYZ raster layers, and local raster PMTiles had no toggle.
      They now all get a TOC entry (checkbox + raster swatch + friendly label) so users can switch any
      visible layer off.
    0.38.1 - Clearer self-hosting scope: label streaming (internet-only) sources
    - MapSplat bundles everything it can as PMTiles (Caddy/static-servable, offline). Sources that
      stream live from a remote server (XYZ basemap, online XYZ/MVT layers, streamed Protomaps) now
      carry a 🌐 marker in the UI and a tooltip explaining they need internet and aren't served by
      your own host. The export log flags any live-streaming source. New README 'Hosting & self-hosting
      scope' section spells out what's bundled vs streamed.
    0.38.0 - Local MBTiles vector tiles -> bundled PMTiles (Story 18 Stage 2)
    - A vector tile layer backed by a local .mbtiles file is now converted to PMTiles and bundled into
      the export (offline-capable; no terms-of-service concern since it's a local file). Its Mapbox-GL
      style is taken from the layer's custom property or the MBTiles metadata table.
    - Stage 3 (downloading ONLINE tile sources for offline use) remains deferred — it is ToS-gated and
      needs dedicated acknowledgment/progress UI; online tile layers still stream live (Stage 1).
    0.37.0 - XYZ raster basemap support (Story 16)
    - New basemap mode: "XYZ raster" — use an online XYZ tile provider (OpenStreetMap, Carto,
      OpenTopoMap, Esri World Imagery, or a custom {z}/{x}/{y} URL) as the basemap. It streams live in
      the viewer, needs no pmtiles CLI, and adds the provider's attribution automatically.
    0.36.1 - Docs: Quick Start refresh, Troubleshooting, tutorial storyboard
    - README: crisp 5-step Quick Start (install -> first export) plus a Troubleshooting table for the
      common gotchas (pmtiles CLI, blank map/serve.py, missing layers, rasters, online layers, tools).
    - New docs/TUTORIAL_SCRIPT.md: shot-by-shot storyboard for a ~6-minute demo video.
    0.36.0 - Raster layer support (Story 15)
    - Selected raster layers can now be tiled into the map: gdalwarp -> EPSG:3857 (clipped to the
      export extent) -> gdal_translate -of MBTiles (with overviews) -> pmtiles convert, added as a
      raster source below the vector layers with the layer's opacity. RGB/RGBA and paletted rasters
      are supported (paletted via an -expand rgba retry). Enable with the new "Include raster layers"
      checkbox (off by default; needs GDAL's MBTiles driver). Styled single-band rasters (e.g. DEMs)
      may not tile yet. Intermediate files are cleaned up; failures fold into the export summary.
    0.35.0 - Basemap extract caching (Story 17)
    - Basemap extracts are now cached by source + extent + max zoom, so repeat exports of the same
      area reuse the previous download instead of re-extracting. Transient network failures retry 3×,
      and `pmtiles extract` runs with parallel download threads.
    - New Advanced Options: "Refresh basemap cache (re-download)" checkbox and a "Clear basemap cache"
      button. Cache lives under the active QGIS profile.
    0.34.0 - MVT / XYZ tile layers: pass-through export (Story 18 Stage 1)
    - Vector tile layers (QgsVectorTileLayer, XYZ/MVT) and online XYZ raster layers (OSM, imagery,
      any {z}/{x}/{y}) are now exportable: their source URLs are referenced directly in style.json so
      the web map streams them live (no data copied — no provider terms-of-service concern).
    - Vector tile layers are now selectable (were disabled [Other]); online layers are tagged 🌐 in the
      layer list so you know the exported map needs internet for them.
    - XYZ raster layers were previously selectable but silently dropped — now they render.
    0.33.0 - Export robustness: partial-failure summary + optional PMTiles verify
    - Per-layer export failures no longer pass silently: the run tracks which layers had problems and
      shows a summary dialog ("N of M layers exported") listing each failure with its reason.
    - New "Verify PMTiles after export" checkbox (Advanced Options, off by default) runs `pmtiles
      verify` on each written tile file; failures are logged and surfaced in the summary.
    0.32.0 - Graduated marker icons + dual-sprite fallback + embed-note accuracy
    - Graduated (range-based) SVG-marker point layers now render as per-range sprite icons (a `step`
      icon-image over the class attribute), matching the categorized behaviour; they no longer fall
      back to plain circles. Per-range icons also appear in the legend.
    - Dual-sprite resilience: if a combined basemap+business sprite array fails to load (e.g. the
      remote basemap sprite is offline), the viewer now falls back to the local business sprite so
      your markers still render, instead of the whole array failing.
    - Copy-embed accuracy: the <body> block's NOTE now says the whole MAPSPLAT <head> block (assets
      AND styles, inline when bundled) is required — not just the CDN tags.
    0.31.0 - Toolbar polish + drawing interaction fixes
    - Map tool buttons (reset, north, measure, draw, export) are now 29x29 with black line-art SVG
      icons, matching MapLibre's native control buttons (e.g. the geolocate button) instead of the
      old mixed-size emoji buttons.
    - Right-click now completes a drawing or measurement (was double-click), avoiding stray points.
    - Identify popups are suppressed while the measure or draw tool is active, so they no longer get
      in the way while sketching.
    0.30.1 - Export tool now captures drawings + scale bar
    - JPG/PDF export composites the map onto a 2D canvas and captures it synchronously within a render
      frame, so drawn/measured features reliably appear (previously the async capture could miss them).
    - The exported image now also includes a scale bar (when the on-screen scale bar is enabled). The
      legend/controls panel is still excluded (it is a separate HTML overlay).
    0.30.0 - Plugin tool framework + export tool + adjustable units/colours
    - Interactive viewer tools (measure, draw, export) are now self-registering plugin objects that
      talk to the map through a small stable interface (MapSplatTools host). They use only long-stable
      MapLibre APIs, so upgrading the MapLibre library no longer touches the tools.
    - New optional Export tool: save the current map image as JPG or PDF (self-contained, no external
      library; single-image PDF built in-page). Enable via the Viewer tab "Export tool" checkbox.
    - Viewers can now adjust units and colours at runtime: the measure readout has a units toggle
      (metric + imperial / metric / imperial) and the draw tool has a per-feature colour picker.
      Authors can set defaults via measure_units / draw_color in a config.
    0.29.0 - Draw/sketch tool with GeoJSON/KML export (optional)
    - New optional viewer tool: a pencil button to draw points, lines, and polygons on the map and
      export them as GeoJSON or KML (client-side download; nothing is uploaded). Point/Line/Polygon
      modes, Finish/Undo/Clear. Enable via the Viewer tab "Draw/sketch tool" checkbox (off by
      default). Measure and Draw are mutually exclusive (activating one deactivates the other).
    0.28.0 - Measure tool (optional)
    - New optional viewer tool: a ruler button to measure distance and area on the map. Click to add
      points (live geodesic length), double-click to close a polygon (area). Shows metric + imperial
      units. Enable via the Viewer tab "Measure tool" checkbox (off by default). Pure offline JS.
    0.27.6 - Record MapSplat version in the export log
    - The export log now records the plugin version in the run header and as the first INFO line,
      so a saved export.log is self-identifying (matches mapsplat:version in style.json).
    0.27.5 - Don't inject a solid line for marker/hash decorative lines
    - Marker lines (symbols placed along a line, e.g. paw prints) and hash/tick lines can't render as
      symbols-on-a-line here. Previously they fell back to a plain solid line, which muddied the real
      line underneath (e.g. a solid underlay beneath the dashed wandering_cat line). These sublayers
      are now omitted so the intended (e.g. dashed) line renders cleanly. Other unsupported line types
      still get a solid colour stand-in.
    0.27.4 - Dashed lines for categorized/graduated layers
    - Categorized and graduated LINE layers now carry a dash pattern (were always solid). MapLibre's
      line-dasharray is not data-driven, so the layer carries one representative dash (most common
      across the classes); per-class color/width stay fully data-driven. Uses the same width-correct
      normalization as single-symbol lines (0.27.3).
    0.27.3 - Dashed line rendering fix
    - Dashed lines (e.g. wandering_cat) now render at the correct scale. MapLibre's line-dasharray is
      in units of LINE WIDTH, but the converter emitted absolute pixels, so dashes came out ~3-4x too
      large. Dash lengths are now divided by the line width. Qt preset pen styles (dash/dot/dash-dot)
      are also converted (were previously ignored -> rendered solid).
    0.27.2 - Vertical legend layout
    - Per-class legend entries now stack vertically BELOW their layer row instead of floating to the
      right (which stretched the legend wide). The legend panel is width-capped and scrolls vertically.
    0.27.1 - Marker legend classes always show
    - Per-class marker icons now appear in the legend even when the 'advanced legend' option is off
      (a marker layer's classes are essential to reading it). The advanced-legend toggle still gates
      the colour-inferred per-class breakdowns for fills/lines.
    0.27.0 - Legend: per-class icons, QGIS groups, collapsing
    - The legend now shows the real per-class SVG marker icon + label for categorized marker
      layers (was: no icon / a plain circle).
    - QGIS layer-tree groups (e.g. 'My Layers') render as collapsible sections, collapsed by default.
    - Layers with more than 6 classes collapse their class list behind an 'N classes' toggle.
    0.26.0 - Dual basemap+business sprites, serve.py startup banner
    - Basemap + business icons now coexist: when the basemap ships its own sprite, MapSplat
      combines both via a MapLibre sprite ARRAY (business icons namespaced 'mapsplat:'), so
      basemap shields/POIs AND your SVG markers render (was: business sprite replaced the basemap's).
    - serve.py prints a startup banner: the folder it's serving, project name, MapSplat version,
      layer/data-source summary, and a big warning if the folder is in the Trash (stale export).
    - The export style now records mapsplat:version / mapsplat:project in metadata.
    0.25.0 - Categorized SVG markers + MapLibre 5 sprite fix
    - Categorized point layers with SVG markers now render each class's real marker (via a
      per-class sprite icon + data-driven icon-image), instead of falling back to plain circles.
    - Fixed: MapLibre GL JS 5 rejects a relative sprite URL, so ALL sprite icons (including
      single-symbol SVG markers) silently failed to load. The viewer now resolves the sprite URL
      to absolute at runtime. Class symbols are rendered crash-safely (no symbolPreviewPixmap).
    0.24.2 - serve.py no-cache (fixes stale re-exports)
    - serve.py now sends no-store/no-cache headers so re-exporting a map always shows the fresh
      result. Browsers were caching style.json/index.html/tiles, making a re-exported layer look
      "missing" until a hard refresh. (Verified via headless render: the data/style were always
      correct.)
    0.24.1 - Log the style build in the dock
    - The Log tab now reports each layer as it's converted (renderer type → number of style
      layers + label, and the source name), warns when a renderer converts to 0 layers, and
      prints a final "Style built / Final style" summary. Makes "missing layer" issues visible.
    0.24.0 - Sprite icon render fix
    - Point layers using an SVG-marker sprite no longer render blank. The viewer's
      styleimagemissing handler was adding an empty placeholder for our own sprite icons
      when MapLibre requested them before the sprite finished loading, permanently blanking
      the marker. It now skips our sprite icons (recorded in style metadata) so the sprite wins.
    0.23.0 - Labels, background override & export robustness
    - Label placement now reads the real QGIS 4 settings: the quadrant is read from
      pointSettings() (the old attribute silently defaulted), so labels pin to QGIS's real
      quadrant; 'exact' mode is fixed (no drift), 'auto' avoids overlaps. Y offset sign fixed.
    - New optional Background colour override (Viewer tab + config file); blank = no change.
    - serve.py auto-advances to a free port instead of crashing; layers with an invalid/unset
      CRS are skipped with a clear message instead of exporting to the wrong place.
    0.22.0 - Draw order, hatch angles & robustness
    - Categorized polygons now honour QGIS feature draw order (order-by), so overlapping
      polygons stack the same as in QGIS (e.g. a big "bounds" polygon stays in the back).
    - Hatch line angle now matches QGIS (was mirrored); stacked line patterns render as a
      real crosshatch. Background colour is an optional override (default: no change).
    - Robustness: layers that fail to tile no longer leave a dangling source reference, and
      any orphan layer is pruned, so one bad reference can't blank the whole map.
    0.21.0 - Real hatch/pattern fills
    - QGIS hatch fills (LinePatternFill) now render as actual MapLibre fill-pattern hatching,
      not just a flat alpha. Tileable hatch PNGs are generated at export time (angle/spacing/
      width/colour from the QGIS symbol) and loaded in the viewer via styleimagemissing.
    - Each hatched category gets its own filtered fill-pattern layer over a semi-transparent
      solid fallback, so a failed image load degrades gracefully instead of blanking.
    0.20.0 - Symbology fidelity fixes
    - Categorized polygons/lines/points now render EVERY class (classes whose bottom symbol layer
      was a hatch/gradient were being dropped to invisible). Solid colours are sampled from the
      top-most visible fill layer, not just layer 0 (fixes wrong colours on stacked symbols).
    - Graduated renderers hardened the same way (no more dropped interpolate stops).
    - QGIS "Hairline" strokes now render as a 1px outline instead of nothing.
    - Full history: https://github.com/johnzastrow/mapsplat4/blob/main/docs/CHANGELOG.md
    0.13.1 - Security, packaging & licensing
    - Passes Bandit (0 high/medium), detect-secrets, and flake8 (plugins.qgis.org gates)
    - Removed the bundled go-pmtiles binary from the repo/zip; QGIS forbids binaries. Core export
      uses GDAL's PMTiles driver. The pmtiles CLI (offline-basemap mode only) is installed by the user.
    - Correct LICENSE (GPL-2.0-or-later; the old file was go-pmtiles' BSD); no longer experimental
    - Reliable self-verifying build (scripts/build_plugin.sh); dropped dead compiled resources
    - Full history: https://github.com/johnzastrow/mapsplat4/blob/main/docs/CHANGELOG.md
tags=export,web,pmtiles,maplibre,tiles,vector tiles,static map

homepage=https://github.com/johnzastrow/mapsplat4
category=Web
icon=icon.png

experimental=False
deprecated=False

server=False
