Use addProtocol to transform feature properties
Replicates the MapLibre example Use addProtocol to transform feature properties. The YAML declares a GeoJSON source whose URL starts reverse://, and the layers that label it. The protocol is page JS: registered with addProtocol from @maplibre-yaml/core/maplibre, it fetches the real URL, writes every NAME and ABBREV backwards, and hands the result back as the response. The document never knows.
The YAML half
Section titled “The YAML half”# yaml-language-server: $schema=https://docs.maplibre-yaml.org/schema/latest/map.schema.json# Gallery twin of https://maplibre.org/maplibre-gl-js/docs/examples/use-addprotocol-to-transform-feature-properties/# The YAML half: a GeoJSON source whose URL goes through a `reverse://`# protocol, and the layers that label it. The protocol — fetch the real# URL, rewrite every NAME and ABBREV backwards, hand the data back — is# page JS registered on <ml-map>'s maplibre module; see# use-addprotocol-to-transform-feature-properties.js. The YAML never knows.## NOTE for the live sweep: renders only with the page's protocol# registration; scripts/verify-docs-gallery.mjs drives it through the# hatch harness, which runs that JS.type: mapid: use-addprotocol-to-transform-feature-propertiesconfig: center: [8, 47] zoom: 5 mapStyle: "https://demotiles.maplibre.org/style.json"sources: countries: type: geojson data: "reverse:///gallery-assets/alpine-countries.geojson"layers: - id: country-points type: circle source: countries paint: circle-radius: 5 circle-color: "#e63946" - id: country-names type: symbol source: countries layout: text-field: ["format", ["get", "NAME"], {}, "\n", {}, ["get", "ABBREV"], { font-scale: 0.75 }] text-font: ["Noto Sans Regular"] text-offset: [0, 0.4] text-anchor: top paint: text-color: "#1d3557" text-halo-color: "#ffffff" text-halo-width: 1.5The JavaScript half
Section titled “The JavaScript half”// The JavaScript half: addProtocol, imported from @maplibre-yaml/core/maplibre// so it registers on the very module <ml-map> renders with. Any source URL// that starts `reverse://` now comes through this function: fetch the real// URL, rewrite the properties, return the result as the response.// (Upstream does the same to vector tiles, decoding them with// @mapbox/vector-tile and re-encoding with vt-pbf; GeoJSON needs neither.)import { addProtocol } from "@maplibre-yaml/core/maplibre";
const reverse = (text) => [...text].reverse().join("");
addProtocol("reverse", async (request) => { const url = request.url.slice("reverse://".length); const geojson = await (await fetch(url)).json(); for (const { properties } of geojson.features) { for (const key of ["NAME", "ABBREV"]) { if (typeof properties?.[key] === "string") properties[key] = reverse(properties[key]); } } return { data: geojson };});What to notice
Section titled “What to notice”- The import path matters:
@maplibre-yaml/core/maplibreis the exact module<ml-map>renders with, so the protocol lands where the document’s requests go. See PMTiles source and protocol. - Upstream transforms vector tiles, decoding them with
@mapbox/vector-tileand re-encoding withvt-pbf; the protocol code is identical, only the payload differs.