Export classes: what every construct does on emit
mlym emit compiles a document to spec-valid style.json. Not everything in
the format can compile — popups are runtime behavior, a legend is DOM chrome —
so every construct declares an export class: what emit does with it. There
is no fourth class and no undeclared construct; a runtime construct reaching
the emitter without a registration is a thrown error, not a silent drop.
The three classes
Section titled “The three classes”| Class | Meaning |
|---|---|
exports | Has an honest style.json representation and compiles to it. |
exports-with-fallback | Exports with a fallback: compiles to a documented approximation (a marker becomes a symbol layer + sprite; an animated effect becomes its static preset). Reported as lossy when the visual result differs. |
no-export | Doesn’t export: interactive-only; no honest style form exists. Reported by emit as a contract warning naming the construct — never silently omitted. |
Every construct, classified
Section titled “Every construct, classified”This table mirrors the registry in core
(packages/core/src/export/registrations.ts); a drift test fails if they
disagree.
| Construct | Class | On emit |
|---|---|---|
center / zoom / pitch / bearing | exports | Style-spec root camera properties; compile through. |
state | exports | A style-spec root property; compiles through on supporting runtimes, and below the global-state floor the defaults are inlined into expressions (the inlineState gate). |
layer.before | exports | Placement compiles honestly: the emitted layers array is ordered accordingly, and EmitResult.placements carries the intent. |
images | exports | Named images are fetched at compile time and merged into the document sprite; layer references are rewritten to mlym:<name> so they resolve in the emitted style. |
terrain | exports | A style-spec root property; compiles through verbatim, and the document’s terrain wins over a basemap’s. A source that resolves to no raster-dem source is dropped and reported as lossy rather than shipped invalid. |
sky | exports | A style-spec root property; compiles through verbatim, and the document’s sky wins over a basemap’s. Not drawn below maplibre-gl 4.5.0 — lossy against a declared --target below that. |
projection | exports | A style-spec root property; compiles through verbatim, and the document’s projection wins over a basemap’s. Globe needs maplibre-gl 5.0.0; older runtimes render mercator — lossy against a declared --target below that. |
color-relief | exports | The layer type compiles through verbatim (it is a style-spec layer); it needs maplibre-gl 5.6+ to render, so mlym emit --target below 5.6 reports it as lossy. Live, a runtime below 5.6 skips the layer with one warning. |
fitTo | exports-with-fallback | The fit-to-data camera lowers to a concrete center/zoom when the named source’s GeoJSON is inline (computed for a 1024×768 reference viewport — lossy, since a live map fits its own container); for fetched or tiled sources the authored center/zoom stand in, reported as lossy. |
light | exports | The style-spec root light; compiles through verbatim to the emitted style’s light, replacing any basemap light. |
markers | exports-with-fallback | Markers lower to a symbol layer with generated pin sprites — the pins render in the emitted style; DOM-marker behavior (dragging, built-in popups) does not compile, reported as lossy. |
layer.effect | exports-with-fallback | Experimental. A shader effect has no style.json form; the emitted style carries the layer’s own static style — the effect’s fallback — with one lossy warning per effect, so --strict refuses. A registered effect may adjust that layer or return null (the layer doesn’t export) from its fallback(). See Effects. |
layer.interactive | no-export | Popups, hover, and highlight are runtime behavior; attachInteractions() restores them over an exported style. |
layer.legend | no-export | Legend entries are chrome, not cartography. |
layer.label | no-export | Display labels are chrome metadata. |
layer.toggleable | no-export | The emitted style carries the layer’s authored visibility and no toggle. |
source.refresh / source.stream / source.cache / source.loading / source.prefetchedData / source.fetchStrategy / source.refreshInterval / source.updateStrategy / source.updateKey | no-export | Live-data machinery; the emitted source carries the data present at compile time (lossy when there is none). |
map.options | no-export | MapLibre constructor options are host decisions; the emitted style uses MapLibre’s defaults. |
controls | no-export | DOM chrome; the emitted map gets MapLibre’s default control set only. |
legend | no-export | DOM chrome; no legend surface exists in a style. |
container | no-export | className / inline style belong to the host page. |
popups | no-export | Standalone popups are DOM chrome; the emitted style renders the map without them. |
parameters | no-export | Presentation metadata for state keys; the values themselves export via state. |
x-* | no-export | Extension blocks are host-side data; never part of the emitted style. |
markers was the first construct that exports with a fallback (marker icon:
URLs are fetched into the sprite at emit time, like images: entries).
fitTo is the second, and its lowering rewrites the root camera rather than
adding layers. The experimental effects obey the same law — every effect
registers a mandatory fallback(), and the layer an effect sits on is that
fallback, so an exported effect is never a silent hole in the map.
<ml-map> slots
are not in the table because they are not in the document: slot children
are page markup the host places around the map, so mlym emit never sees
them and there is nothing to export. A page that exports to vanilla
maplibre-gl keeps its own markup and positions it itself.
Reading the emit report
Section titled “Reading the emit report”mlym emit map.yaml --out dist/Constructs that don’t export arrive as contract warnings — expected, documented drops
that don’t fail --strict:
contract layers.quakes.interactive: `interactive` — Interactions (popups, hover, highlight) are runtime behavior with no style.json form; …contract controls: `controls` — Controls are DOM chrome; …lossy warnings are different — something the map shows changed (a live
source with no compile-time data, a fallback that approximates). Those fail
--strict, because they are the cases where the exported map is not the map
you authored.