@massif-maps/style-tools 6.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/cli.js +436 -0
- package/dist/cli.js.map +1 -0
- package/dist/generated/properties.json +2488 -0
- package/dist/legend-svg.js +142 -0
- package/dist/legend-svg.js.map +1 -0
- package/dist/mapbox2css/browser-host.js +27 -0
- package/dist/mapbox2css/browser-host.js.map +1 -0
- package/dist/mapbox2css/casing.js +84 -0
- package/dist/mapbox2css/casing.js.map +1 -0
- package/dist/mapbox2css/config.js +212 -0
- package/dist/mapbox2css/config.js.map +1 -0
- package/dist/mapbox2css/contour.js +61 -0
- package/dist/mapbox2css/contour.js.map +1 -0
- package/dist/mapbox2css/coverage.js +56 -0
- package/dist/mapbox2css/coverage.js.map +1 -0
- package/dist/mapbox2css/emissive.js +192 -0
- package/dist/mapbox2css/emissive.js.map +1 -0
- package/dist/mapbox2css/expression.js +606 -0
- package/dist/mapbox2css/expression.js.map +1 -0
- package/dist/mapbox2css/filter.js +285 -0
- package/dist/mapbox2css/filter.js.map +1 -0
- package/dist/mapbox2css/fold.js +588 -0
- package/dist/mapbox2css/fold.js.map +1 -0
- package/dist/mapbox2css/host.js +13 -0
- package/dist/mapbox2css/host.js.map +1 -0
- package/dist/mapbox2css/index.js +3599 -0
- package/dist/mapbox2css/index.js.map +1 -0
- package/dist/mapbox2css/narrow.js +284 -0
- package/dist/mapbox2css/narrow.js.map +1 -0
- package/dist/mapbox2css/node-host.js +36 -0
- package/dist/mapbox2css/node-host.js.map +1 -0
- package/dist/mapbox2css/placement.js +62 -0
- package/dist/mapbox2css/placement.js.map +1 -0
- package/dist/mapbox2css/png.js +264 -0
- package/dist/mapbox2css/png.js.map +1 -0
- package/dist/mapbox2css/properties.js +155 -0
- package/dist/mapbox2css/properties.js.map +1 -0
- package/dist/mapbox2css/schema.js +865 -0
- package/dist/mapbox2css/schema.js.map +1 -0
- package/dist/mapbox2css/shield.js +118 -0
- package/dist/mapbox2css/shield.js.map +1 -0
- package/dist/mapbox2css/split.js +380 -0
- package/dist/mapbox2css/split.js.map +1 -0
- package/dist/mapbox2css/sprite.js +882 -0
- package/dist/mapbox2css/sprite.js.map +1 -0
- package/dist/mapbox2css/types.js +2 -0
- package/dist/mapbox2css/types.js.map +1 -0
- package/dist/mapbox2css/variables.js +273 -0
- package/dist/mapbox2css/variables.js.map +1 -0
- package/dist/wasm.js +43 -0
- package/dist/wasm.js.map +1 -0
- package/package.json +48 -0
- package/wasm/massif-style.mjs +2 -0
- package/wasm/massif-style.wasm +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draws a resolved legend (MBVectorTileDecoder::getLegend, `massif-style legend`) as an SVG sheet.
|
|
3
|
+
* No filesystem access, so a browser can reuse it: images go through `imageHref`.
|
|
4
|
+
*/
|
|
5
|
+
const WIDTH = 340;
|
|
6
|
+
const ROW = 28;
|
|
7
|
+
const SWATCH_W = 52;
|
|
8
|
+
const SWATCH_H = 22;
|
|
9
|
+
const HEADER = 30;
|
|
10
|
+
const PAD = 12;
|
|
11
|
+
const FONT = 'font-family="sans-serif"';
|
|
12
|
+
function esc(text) {
|
|
13
|
+
return String(text).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
14
|
+
}
|
|
15
|
+
export function labelText(label, lang) {
|
|
16
|
+
if (label === undefined || label === null)
|
|
17
|
+
return '';
|
|
18
|
+
if (typeof label === 'object' && !Array.isArray(label)) {
|
|
19
|
+
const text = (lang !== undefined ? label[lang] : undefined) ?? Object.values(label)[0];
|
|
20
|
+
return text === undefined ? '' : String(text);
|
|
21
|
+
}
|
|
22
|
+
return String(label);
|
|
23
|
+
}
|
|
24
|
+
/** Widths to scale, up to what the swatch holds, so a motorway still reads wider than a track. */
|
|
25
|
+
function clampWidth(width) {
|
|
26
|
+
return Math.max(0.5, Math.min(width, SWATCH_H - 2));
|
|
27
|
+
}
|
|
28
|
+
class Sheet {
|
|
29
|
+
href;
|
|
30
|
+
defs = '';
|
|
31
|
+
patterns = new Map();
|
|
32
|
+
constructor(href) {
|
|
33
|
+
this.href = href;
|
|
34
|
+
}
|
|
35
|
+
pattern(file) {
|
|
36
|
+
let id = this.patterns.get(file);
|
|
37
|
+
if (!id) {
|
|
38
|
+
id = `pattern${this.patterns.size}`;
|
|
39
|
+
this.patterns.set(file, id);
|
|
40
|
+
this.defs += `<pattern id="${id}" patternUnits="userSpaceOnUse" width="12" height="12">`
|
|
41
|
+
+ `<image href="${esc(this.href(file))}" width="12" height="12"/></pattern>`;
|
|
42
|
+
}
|
|
43
|
+
return `url(#${id})`;
|
|
44
|
+
}
|
|
45
|
+
image(file, x, y, size) {
|
|
46
|
+
return `<image href="${esc(this.href(file))}" x="${x}" y="${y}" width="${size}" height="${size}"/>`;
|
|
47
|
+
}
|
|
48
|
+
wrap(body) {
|
|
49
|
+
return this.defs ? `<defs>${this.defs}</defs>${body}` : body;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function text(t, x, y, size, weight = 'bold') {
|
|
53
|
+
const halo = t.halo && t.haloWidth ? ` stroke="${esc(t.halo)}" stroke-width="${2 * t.haloWidth}" paint-order="stroke"` : '';
|
|
54
|
+
return `<text x="${x}" y="${y}" text-anchor="middle" dominant-baseline="central" ${FONT} font-size="${size}"`
|
|
55
|
+
+ ` font-weight="${weight}" fill="${esc(t.color)}"${halo}>${esc(t.value)}</text>`;
|
|
56
|
+
}
|
|
57
|
+
function drawSwatch(item, x, y, sheet) {
|
|
58
|
+
const cx = x + SWATCH_W / 2;
|
|
59
|
+
const cy = y + SWATCH_H / 2;
|
|
60
|
+
switch (item.kind) {
|
|
61
|
+
case 'line':
|
|
62
|
+
return (item.lines ?? []).map((line) => {
|
|
63
|
+
if (line.pattern) {
|
|
64
|
+
return `<rect x="${x}" y="${cy - 3}" width="${SWATCH_W}" height="6" fill="${sheet.pattern(line.pattern)}" opacity="${line.opacity ?? 1}"/>`;
|
|
65
|
+
}
|
|
66
|
+
const ly = cy + (line.offset ?? 0);
|
|
67
|
+
const dash = line.dasharray ? ` stroke-dasharray="${line.dasharray.join(',')}"` : '';
|
|
68
|
+
return `<line x1="${x}" y1="${ly}" x2="${x + SWATCH_W}" y2="${ly}" stroke="${esc(line.color ?? '#000')}"`
|
|
69
|
+
+ ` stroke-width="${clampWidth(line.width ?? 1)}" stroke-opacity="${line.opacity ?? 1}"${dash}/>`;
|
|
70
|
+
}).join('');
|
|
71
|
+
case 'fill': {
|
|
72
|
+
let out = '';
|
|
73
|
+
if (item.color)
|
|
74
|
+
out += `<rect x="${x}" y="${y}" width="${SWATCH_W}" height="${SWATCH_H}" fill="${esc(item.color)}" fill-opacity="${item.opacity ?? 1}"/>`;
|
|
75
|
+
if (item.pattern)
|
|
76
|
+
out += `<rect x="${x}" y="${y}" width="${SWATCH_W}" height="${SWATCH_H}" fill="${sheet.pattern(item.pattern)}"/>`;
|
|
77
|
+
if (item.outline) {
|
|
78
|
+
const o = item.outline;
|
|
79
|
+
out += `<rect x="${x}" y="${y}" width="${SWATCH_W}" height="${SWATCH_H}" fill="none" stroke="${esc(o.color ?? '#000')}"`
|
|
80
|
+
+ ` stroke-width="${o.width ?? 1}"${o.dasharray ? ` stroke-dasharray="${o.dasharray.join(',')}"` : ''}/>`;
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
case 'shield': {
|
|
85
|
+
let out = '';
|
|
86
|
+
const value = item.text?.value ?? '';
|
|
87
|
+
if (item.plate) {
|
|
88
|
+
const w = Math.min(SWATCH_W, 10 + value.length * 6.5);
|
|
89
|
+
const p = item.plate;
|
|
90
|
+
out += `<rect x="${cx - w / 2}" y="${y + 3}" width="${w}" height="${SWATCH_H - 6}" rx="${p.radius}" fill="${esc(p.color)}"`
|
|
91
|
+
+ (p.border && p.borderWidth ? ` stroke="${esc(p.border)}" stroke-width="${p.borderWidth}"` : '') + '/>';
|
|
92
|
+
}
|
|
93
|
+
else if (item.icon) {
|
|
94
|
+
out += sheet.image(item.icon, cx - SWATCH_H / 2, y, SWATCH_H);
|
|
95
|
+
}
|
|
96
|
+
if (item.text)
|
|
97
|
+
out += text({ ...item.text, halo: undefined }, cx, cy, 10);
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
case 'poi':
|
|
101
|
+
if (item.icon)
|
|
102
|
+
return sheet.image(item.icon, cx - 9, cy - 9, 18);
|
|
103
|
+
if (item.marker) {
|
|
104
|
+
const m = item.marker;
|
|
105
|
+
return `<circle cx="${cx}" cy="${cy}" r="${Math.min(m.size, SWATCH_H) / 2}" fill="${esc(m.color)}"`
|
|
106
|
+
+ (m.border && m.borderWidth ? ` stroke="${esc(m.border)}" stroke-width="${m.borderWidth}"` : '') + '/>';
|
|
107
|
+
}
|
|
108
|
+
if (item.glyph) {
|
|
109
|
+
return `<text x="${cx}" y="${cy}" text-anchor="middle" dominant-baseline="central" font-family="${esc(item.glyph.font)}"`
|
|
110
|
+
+ ` font-size="16" fill="${esc(item.glyph.color)}">${esc(item.glyph.char)}</text>`;
|
|
111
|
+
}
|
|
112
|
+
return '';
|
|
113
|
+
case 'label':
|
|
114
|
+
return item.text ? text(item.text, cx, cy, 12) : '';
|
|
115
|
+
default:
|
|
116
|
+
return '';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function renderLegendSvg(legend, options = {}) {
|
|
120
|
+
const sheet = new Sheet(options.imageHref ?? ((file) => file));
|
|
121
|
+
let y = PAD;
|
|
122
|
+
let body = '';
|
|
123
|
+
const title = labelText(legend.title, options.lang);
|
|
124
|
+
if (title) {
|
|
125
|
+
body += `<text x="${PAD}" y="${y + 16}" ${FONT} font-size="17" font-weight="bold">${esc(title)}</text>`;
|
|
126
|
+
y += HEADER + 4;
|
|
127
|
+
}
|
|
128
|
+
for (const section of legend.sections) {
|
|
129
|
+
body += `<text x="${PAD}" y="${y + 18}" ${FONT} font-size="13" font-weight="bold">${esc(labelText(section.label, options.lang))}</text>`;
|
|
130
|
+
y += HEADER;
|
|
131
|
+
for (const item of section.items) {
|
|
132
|
+
body += drawSwatch(item, PAD, y, sheet)
|
|
133
|
+
+ `<text x="${PAD + SWATCH_W + PAD}" y="${y + SWATCH_H / 2}" dominant-baseline="central" ${FONT} font-size="12">`
|
|
134
|
+
+ `${esc(labelText(item.label, options.lang))}</text>`;
|
|
135
|
+
y += ROW;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const height = y + PAD;
|
|
139
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" height="${height}" viewBox="0 0 ${WIDTH} ${height}">`
|
|
140
|
+
+ `<rect width="100%" height="100%" fill="#ffffff"/>${sheet.wrap(body)}</svg>\n`;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=legend-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legend-svg.js","sourceRoot":"","sources":["../src/legend-svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sprite host for a browser: `fetch` for the sheets, the codec in png.ts, and a caller-supplied
|
|
3
|
+
* sink for the icons.
|
|
4
|
+
*
|
|
5
|
+
* The sink is what makes this useful rather than academic. The website's style preview writes into
|
|
6
|
+
* the wasm module's in-memory filesystem, so a converted style becomes a directory the SDK opens as
|
|
7
|
+
* an asset package - the same shape the CLI writes on disk, without a disk.
|
|
8
|
+
*/
|
|
9
|
+
import { decodePng, encodePng } from './png.js';
|
|
10
|
+
export function browserSpriteHost(writeIcon) {
|
|
11
|
+
return {
|
|
12
|
+
async fetchBytes(url) {
|
|
13
|
+
const response = await fetch(url);
|
|
14
|
+
if (!response.ok)
|
|
15
|
+
throw new Error(`${response.status} ${response.statusText} for ${url}`);
|
|
16
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
17
|
+
},
|
|
18
|
+
decodePng(bytes) {
|
|
19
|
+
return decodePng(bytes);
|
|
20
|
+
},
|
|
21
|
+
encodePng(image, encoding) {
|
|
22
|
+
return encodePng(image, encoding);
|
|
23
|
+
},
|
|
24
|
+
writeIcon,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=browser-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-host.js","sourceRoot":"","sources":["../../src/mapbox2css/browser-host.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKhD,MAAM,UAAU,iBAAiB,CAAC,SAAmB;IACjD,OAAO;QACH,KAAK,CAAC,UAAU,CAAC,GAAW;YACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,QAAQ,GAAG,EAAE,CAAC,CAAC;YAC1F,OAAO,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,SAAS,CAAC,KAAiB;YACvB,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,SAAS,CAAC,KAAgB,EAAE,QAAqB;YAC7C,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,SAAS;KACZ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fold a casing layer into the fill layer it runs under, as one `line-border-*` rule.
|
|
3
|
+
*
|
|
4
|
+
* A MapBox style draws a road casing as its OWN layer, wider and earlier, and the SDK can now draw
|
|
5
|
+
* that border from the line's own vertex buffer (vt, `line-border-width`). Folding the pair halves
|
|
6
|
+
* the rules, the tesselation and the tile geometry.
|
|
7
|
+
*
|
|
8
|
+
* It is opt-in because it MOVES the casing in the draw order: a style writes every casing layer
|
|
9
|
+
* before every fill layer, so a wide road's fill covers a narrow road's casing at a junction;
|
|
10
|
+
* folded, each class carries its own casing and a later class's casing draws over an earlier
|
|
11
|
+
* class's fill. That is what most styles look like anyway, but it is not what the source said.
|
|
12
|
+
*/
|
|
13
|
+
/** Paint keys a foldable pair may carry. Anything else (dashes, patterns, gaps) is left alone. */
|
|
14
|
+
const FOLDABLE = new Set(['line-color', 'line-width', 'line-opacity', 'line-emissive-strength']);
|
|
15
|
+
function same(a, b) {
|
|
16
|
+
return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
17
|
+
}
|
|
18
|
+
/** Same features, same shape: only then do the two layers describe one road. */
|
|
19
|
+
function pairs(casing, fill) {
|
|
20
|
+
if (casing.type !== 'line' || fill.type !== 'line')
|
|
21
|
+
return false;
|
|
22
|
+
if (casing.source !== fill.source || casing['source-layer'] !== fill['source-layer'])
|
|
23
|
+
return false;
|
|
24
|
+
if (!same(casing.filter, fill.filter))
|
|
25
|
+
return false;
|
|
26
|
+
if (casing.minzoom !== fill.minzoom || casing.maxzoom !== fill.maxzoom)
|
|
27
|
+
return false;
|
|
28
|
+
// Joins and caps come from ONE geometry once folded, so they have to already agree.
|
|
29
|
+
const layout = (l) => {
|
|
30
|
+
const { visibility, ...rest } = (l.layout ?? {});
|
|
31
|
+
return rest;
|
|
32
|
+
};
|
|
33
|
+
if (!same(layout(casing), layout(fill)))
|
|
34
|
+
return false;
|
|
35
|
+
const paint = (l) => Object.keys((l.paint ?? {}));
|
|
36
|
+
if (![...paint(casing), ...paint(fill)].every((k) => FOLDABLE.has(k)))
|
|
37
|
+
return false;
|
|
38
|
+
// The border takes the line's own opacity - see LineSymbolizer. Unstated is 1, and a casing
|
|
39
|
+
// that states it while its fill does not is the common way to write the same thing.
|
|
40
|
+
const opacity = (l) => l.paint?.['line-opacity'] ?? 1;
|
|
41
|
+
return same(opacity(casing), opacity(fill));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Rewrites the fill of every foldable pair to carry `line-border-*`, and hides the casing. The
|
|
45
|
+
* array keeps its length and order: callers index the original `style.layers` by position.
|
|
46
|
+
*/
|
|
47
|
+
export function foldCasings(layers) {
|
|
48
|
+
const out = layers.slice();
|
|
49
|
+
const folded = [];
|
|
50
|
+
const skipped = [];
|
|
51
|
+
const taken = new Set();
|
|
52
|
+
for (let i = 0; i < out.length; i++) {
|
|
53
|
+
if (taken.has(i))
|
|
54
|
+
continue;
|
|
55
|
+
for (let j = i + 1; j < out.length; j++) {
|
|
56
|
+
if (taken.has(j) || !pairs(out[i], out[j]))
|
|
57
|
+
continue;
|
|
58
|
+
// A sort key turns the fill into one rule per key value, and a folded casing then draws
|
|
59
|
+
// per class - over the fill of the road beside it, which is the very thing the casing
|
|
60
|
+
// LAYER avoided. Left unfolded, so the casings stay one rule under all of them.
|
|
61
|
+
if (out[j].layout?.['line-sort-key'] !== undefined) {
|
|
62
|
+
skipped.push({ casing: out[i].id, fill: out[j].id });
|
|
63
|
+
taken.add(i);
|
|
64
|
+
taken.add(j);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
const casing = (out[i].paint ?? {});
|
|
68
|
+
const fill = (out[j].paint ?? {});
|
|
69
|
+
out[j] = { ...out[j], paint: { ...fill,
|
|
70
|
+
'line-border-color': casing['line-color'] ?? '#000000',
|
|
71
|
+
// Half the difference: the casing's width is the WHOLE road, the border is what
|
|
72
|
+
// sticks out on one side.
|
|
73
|
+
'line-border-width': ['/', ['-', casing['line-width'] ?? 1, fill['line-width'] ?? 1], 2],
|
|
74
|
+
} };
|
|
75
|
+
out[i] = { ...out[i], layout: { ...(out[i].layout ?? {}), visibility: 'none' } };
|
|
76
|
+
folded.push({ casing: out[i].id, fill: out[j].id });
|
|
77
|
+
taken.add(i);
|
|
78
|
+
taken.add(j);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { layers: out, folded, skipped };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=casing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"casing.js","sourceRoot":"","sources":["../../src/mapbox2css/casing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/** The preset names Standard's `lightPreset` takes, in the order its schema lists them. */
|
|
2
|
+
export const LIGHT_PRESETS = ['day', 'dawn', 'dusk', 'night'];
|
|
3
|
+
/** Standard's own name for the knob that recolours the whole basemap. */
|
|
4
|
+
export const LIGHT_PRESET = 'lightPreset';
|
|
5
|
+
/** Every `["config", name]` in the style, in first-seen order. */
|
|
6
|
+
export function configNames(style) {
|
|
7
|
+
const found = [];
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
const walk = (node) => {
|
|
10
|
+
if (Array.isArray(node)) {
|
|
11
|
+
if (node[0] === 'config' && typeof node[1] === 'string' && !seen.has(node[1])) {
|
|
12
|
+
seen.add(node[1]);
|
|
13
|
+
found.push(node[1]);
|
|
14
|
+
}
|
|
15
|
+
for (const child of node)
|
|
16
|
+
walk(child);
|
|
17
|
+
}
|
|
18
|
+
else if (node && typeof node === 'object') {
|
|
19
|
+
for (const child of Object.values(node))
|
|
20
|
+
walk(child);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
walk((style.layers ?? []));
|
|
24
|
+
return found;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What the style says each configurable value is: the fragment's `schema` for the default and the
|
|
28
|
+
* allowed set, then every `imports[].config` on top - that is the override the root document is
|
|
29
|
+
* for, and it is what a style URL's `?config=` ends up as.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveConfig(style) {
|
|
32
|
+
const parameters = new Map();
|
|
33
|
+
const schema = style.schema;
|
|
34
|
+
if (schema && typeof schema === 'object' && !Array.isArray(schema)) {
|
|
35
|
+
for (const [name, entry] of Object.entries(schema)) {
|
|
36
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry))
|
|
37
|
+
continue;
|
|
38
|
+
const spec = { default: entry.default ?? '' };
|
|
39
|
+
const values = entry.values;
|
|
40
|
+
// The SDK's enum is a map, so a value can be renamed without touching the rules; the
|
|
41
|
+
// spec's is a plain list and every entry stands for itself.
|
|
42
|
+
if (Array.isArray(values) && values.every((v) => typeof v === 'string')) {
|
|
43
|
+
spec.values = Object.fromEntries(values.map((v) => [v, v]));
|
|
44
|
+
}
|
|
45
|
+
parameters.set(name, spec);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const entry of imports(style)) {
|
|
49
|
+
const config = entry.config;
|
|
50
|
+
if (!config || typeof config !== 'object' || Array.isArray(config))
|
|
51
|
+
continue;
|
|
52
|
+
for (const [name, value] of Object.entries(config)) {
|
|
53
|
+
const existing = parameters.get(name);
|
|
54
|
+
parameters.set(name, { ...existing, default: value });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// A layer may read a value the schema never declared - a fragment converted on its own has no
|
|
58
|
+
// root document to carry one. Declaring it anyway is what keeps `[param::x]` resolvable.
|
|
59
|
+
const undeclared = [];
|
|
60
|
+
for (const name of configNames(style)) {
|
|
61
|
+
if (parameters.has(name))
|
|
62
|
+
continue;
|
|
63
|
+
undeclared.push(name);
|
|
64
|
+
parameters.set(name, name === LIGHT_PRESET
|
|
65
|
+
? { default: 'day', values: Object.fromEntries(LIGHT_PRESETS.map((p) => [p, p])) }
|
|
66
|
+
: { default: '' });
|
|
67
|
+
}
|
|
68
|
+
return { parameters, undeclared };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The configs the style asks to keep as RUNTIME parameters instead of folding to a constant:
|
|
72
|
+
*
|
|
73
|
+
* "metadata": { "massif:live-config": ["poiRanking"] }
|
|
74
|
+
*
|
|
75
|
+
* Opt-in, because folding is what makes a configurable style convert at all - see fold.ts - and a
|
|
76
|
+
* live one only works where CartoCSS can say the same thing, which is a filter or a plain property.
|
|
77
|
+
* Its `schema` entry carries straight over: the default and the enum are what project.json declares.
|
|
78
|
+
*/
|
|
79
|
+
export function liveConfig(style) {
|
|
80
|
+
const asked = style.metadata;
|
|
81
|
+
if (!asked || typeof asked !== 'object' || Array.isArray(asked))
|
|
82
|
+
return [];
|
|
83
|
+
const names = asked['massif:live-config'];
|
|
84
|
+
return Array.isArray(names) ? names.filter((n) => typeof n === 'string') : [];
|
|
85
|
+
}
|
|
86
|
+
/** The style's `imports` entries, whatever shape the document is in. */
|
|
87
|
+
export function imports(style) {
|
|
88
|
+
const raw = style.imports;
|
|
89
|
+
if (!Array.isArray(raw))
|
|
90
|
+
return [];
|
|
91
|
+
return raw.filter((e) => !!e && typeof e === 'object' && !Array.isArray(e));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Standard's root document has no layers of its own. Converting it silently produces an empty
|
|
95
|
+
* style, so say what is missing and where the layers actually are.
|
|
96
|
+
*/
|
|
97
|
+
export function importOnly(style) {
|
|
98
|
+
const entries = imports(style);
|
|
99
|
+
if (entries.length === 0 || (style.layers ?? []).length > 0)
|
|
100
|
+
return null;
|
|
101
|
+
const urls = entries.map((e) => e.url ?? e.id ?? '?').join(', ');
|
|
102
|
+
return `the style has no layers of its own - it imports ${urls}. ` +
|
|
103
|
+
'Fetch the imported fragment and convert THAT; a root document carries only the config.';
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* What `["measure-light", "brightness"]` resolves to for a given config.
|
|
107
|
+
*
|
|
108
|
+
* Standard reads the scene's brightness 113 times, always as a ramp that switches a colour between
|
|
109
|
+
* its lit and its unlit form (`[0.25, 0.3]` in 66 of them). It is how the style says "night"
|
|
110
|
+
* without naming the preset. Our renderer has its own lighting and nothing measures it back into a
|
|
111
|
+
* style value, so the number has to be resolved at conversion time.
|
|
112
|
+
*
|
|
113
|
+
* This is `Style.calculateLightsBrightness` (src/style/style.ts) ported, not approximated: the
|
|
114
|
+
* DIRECTIONAL light counts too, weighted by how high it stands, and the luminance is the W3C
|
|
115
|
+
* relative one - a 2.4 gamma with a linear toe - not the colour's HSL lightness. The ambient-only
|
|
116
|
+
* proxy this replaces read Standard's presets as 0.80 / 0.70 / 0.23 / 0.06 where mapbox computes
|
|
117
|
+
* 0.478 / 0.397 / 0.026 / 0.013, so every ramp whose stops are not the common `[0.25, 0.3]` pair
|
|
118
|
+
* was sampled at the wrong place.
|
|
119
|
+
*/
|
|
120
|
+
export function sceneBrightness(lights, fold) {
|
|
121
|
+
const scene = foldedLights(lights, fold);
|
|
122
|
+
if (!scene)
|
|
123
|
+
return null;
|
|
124
|
+
const { ambient, directional } = scene;
|
|
125
|
+
const ambientBrightness = relativeLuminance(ambient.colour) * ambient.intensity;
|
|
126
|
+
// The polar angle is measured from straight up, so a sun at the zenith counts fully and one on
|
|
127
|
+
// the horizon not at all.
|
|
128
|
+
const polarIntensity = 1 - directional.polar / 90;
|
|
129
|
+
const directionalBrightness = relativeLuminance(directional.colour) * directional.intensity * polarIntensity;
|
|
130
|
+
return Number(((directionalBrightness + ambientBrightness) / 2).toFixed(6));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The lights block folded for one config, as sRGB channels and plain numbers. An intensity may be
|
|
134
|
+
* a zoom ramp; `pick` takes its last stop, the value every zoom a building is drawn at gets.
|
|
135
|
+
*/
|
|
136
|
+
function foldedLights(lights, fold) {
|
|
137
|
+
const folded = fold(lights);
|
|
138
|
+
if (!Array.isArray(folded))
|
|
139
|
+
return null;
|
|
140
|
+
const propertiesOf = (type) => {
|
|
141
|
+
const light = folded.find((l) => !!l && typeof l === 'object'
|
|
142
|
+
&& l.type === type);
|
|
143
|
+
const properties = light?.properties;
|
|
144
|
+
return properties && typeof properties === 'object' && !Array.isArray(properties)
|
|
145
|
+
? properties : null;
|
|
146
|
+
};
|
|
147
|
+
const ambient = propertiesOf('ambient');
|
|
148
|
+
if (!ambient)
|
|
149
|
+
return null;
|
|
150
|
+
const directional = propertiesOf('directional') ?? {};
|
|
151
|
+
const rgb = (colour) => typeof colour === 'string' ? hslChannels(colour) : null;
|
|
152
|
+
const ambientRgb = rgb(ambient.color);
|
|
153
|
+
if (!ambientRgb)
|
|
154
|
+
return null;
|
|
155
|
+
const directionalRgb = rgb(directional.color);
|
|
156
|
+
const direction = (() => {
|
|
157
|
+
const value = directional.direction;
|
|
158
|
+
const list = Array.isArray(value) && value[0] === 'literal' ? value[1] : value;
|
|
159
|
+
return Array.isArray(list) && list.length === 2 && list.every((v) => typeof v === 'number')
|
|
160
|
+
? list : null;
|
|
161
|
+
})();
|
|
162
|
+
return {
|
|
163
|
+
ambient: { colour: ambientRgb, intensity: lastStop(ambient.intensity, 1), polar: 0 },
|
|
164
|
+
directional: directionalRgb && direction
|
|
165
|
+
? { colour: directionalRgb, intensity: lastStop(directional.intensity, 1), polar: direction[1] }
|
|
166
|
+
: { colour: [0, 0, 0], intensity: 0, polar: 90 },
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/** The last stop of a ramp, or the value itself when it is already one. */
|
|
170
|
+
function lastStop(value, fallback) {
|
|
171
|
+
if (typeof value === 'number')
|
|
172
|
+
return value;
|
|
173
|
+
if (!Array.isArray(value))
|
|
174
|
+
return fallback;
|
|
175
|
+
const head = value[0];
|
|
176
|
+
if (head === 'literal')
|
|
177
|
+
return lastStop((value[1] ?? null), fallback);
|
|
178
|
+
if ((head === 'step' || head === 'interpolate' || head === 'case' || head === 'match') && value.length >= 4) {
|
|
179
|
+
return lastStop(value[value.length - 1], fallback);
|
|
180
|
+
}
|
|
181
|
+
return fallback;
|
|
182
|
+
}
|
|
183
|
+
/** W3C relative luminance of sRGB channels - mapbox's own, gamma 2.4 with a linear toe. */
|
|
184
|
+
function relativeLuminance([r, g, b]) {
|
|
185
|
+
const channel = (c) => (c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
|
|
186
|
+
return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
|
|
187
|
+
}
|
|
188
|
+
/** sRGB channels 0-1 of an `hsl()`/`hsla()` colour. Standard writes every light colour that way. */
|
|
189
|
+
function hslChannels(colour) {
|
|
190
|
+
const match = /^hsla?\(([^()]*)\)$/i.exec(colour.trim());
|
|
191
|
+
if (!match)
|
|
192
|
+
return null;
|
|
193
|
+
const parts = match[1].split(/[,/\s]+/).filter(Boolean).map((p) => parseFloat(p));
|
|
194
|
+
if (parts.length < 3 || parts.some((p) => !Number.isFinite(p)))
|
|
195
|
+
return null;
|
|
196
|
+
const [h, s, l] = [parts[0], parts[1] / 100, parts[2] / 100];
|
|
197
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
198
|
+
const hp = (((h % 360) + 360) % 360) / 60;
|
|
199
|
+
const x = c * (1 - Math.abs((hp % 2) - 1));
|
|
200
|
+
const [r, g, b] = hp < 1 ? [c, x, 0] : hp < 2 ? [x, c, 0] : hp < 3 ? [0, c, x]
|
|
201
|
+
: hp < 4 ? [0, x, c] : hp < 5 ? [x, 0, c] : [c, 0, x];
|
|
202
|
+
const m = l - c / 2;
|
|
203
|
+
return [r + m, g + m, b + m];
|
|
204
|
+
}
|
|
205
|
+
/** The presets a converted Standard style can be built for, taken from what it actually declares. */
|
|
206
|
+
export function presetsOf(parameters) {
|
|
207
|
+
const spec = parameters.get(LIGHT_PRESET);
|
|
208
|
+
if (!spec)
|
|
209
|
+
return [];
|
|
210
|
+
return spec.values ? Object.keys(spec.values) : [String(spec.default)];
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/mapbox2css/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { renameField } from './schema.js';
|
|
2
|
+
/** MapBox source-layers that carry contour lines. */
|
|
3
|
+
const CONTOUR_SOURCE_LAYERS = new Set(['contour', 'contours']);
|
|
4
|
+
/** nth_line values MapTiler uses to mark an index (major) contour. */
|
|
5
|
+
const INDEX_NTH_LINE = new Set([5, 10]);
|
|
6
|
+
export function isContourLayer(layer) {
|
|
7
|
+
const sourceLayer = layer['source-layer'];
|
|
8
|
+
return sourceLayer !== undefined && CONTOUR_SOURCE_LAYERS.has(sourceLayer);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* MapTiler says "every 5th/10th line" (`nth_line`); tiles built with the gdal ladder say "this line
|
|
12
|
+
* is a multiple of N metres" (`div`). Neither states the other's unit - the base interval is not in
|
|
13
|
+
* the style at all - so only the major/minor SPLIT survives the trip, and `nth_line in (5, 10)`
|
|
14
|
+
* becomes `div >= majorDiv`.
|
|
15
|
+
*
|
|
16
|
+
* Everything else about the layer is left alone: colours, widths and zoom ranges stay whatever the
|
|
17
|
+
* source style asked for.
|
|
18
|
+
*/
|
|
19
|
+
export function rewriteContourFilter(filter, options, onRewrite) {
|
|
20
|
+
if (options.schema !== 'div' || !Array.isArray(filter) || filter.length === 0)
|
|
21
|
+
return filter;
|
|
22
|
+
const [head, ...args] = filter;
|
|
23
|
+
if (head === 'all' || head === 'any' || head === '!') {
|
|
24
|
+
return [head, ...args.map((a) => rewriteContourFilter(a, options, onRewrite))];
|
|
25
|
+
}
|
|
26
|
+
if (typeof head !== 'string' || !namesNthLine(args[0]))
|
|
27
|
+
return filter;
|
|
28
|
+
const values = args.slice(1).filter((v) => typeof v === 'number');
|
|
29
|
+
if (values.length === 0 || !values.every((v) => INDEX_NTH_LINE.has(v)))
|
|
30
|
+
return filter;
|
|
31
|
+
if (head === 'in' || head === '==') {
|
|
32
|
+
onRewrite();
|
|
33
|
+
return ['>=', 'div', options.majorDiv];
|
|
34
|
+
}
|
|
35
|
+
if (head === '!in' || head === '!=') {
|
|
36
|
+
onRewrite();
|
|
37
|
+
return ['<', 'div', options.majorDiv];
|
|
38
|
+
}
|
|
39
|
+
return filter;
|
|
40
|
+
}
|
|
41
|
+
/** The key of a filter test, in either the legacy or the expression spelling. */
|
|
42
|
+
function namesNthLine(key) {
|
|
43
|
+
if (key === 'nth_line')
|
|
44
|
+
return true;
|
|
45
|
+
return Array.isArray(key) && key[0] === 'get' && key[1] === 'nth_line';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The elevation carries a different name in each schema: MapTiler's contour tiles call it `height`,
|
|
49
|
+
* the gdal ladder and `ContourTileDataSource` call it `ele`. Unlike the nth_line/div pair this is
|
|
50
|
+
* the SAME quantity in the same unit, so it is a plain rename - and without it a converted contour
|
|
51
|
+
* label reads a field that is not there and draws nothing.
|
|
52
|
+
*/
|
|
53
|
+
const MAPBOX_ELEVATION_FIELD = 'height';
|
|
54
|
+
export const DEFAULT_ELEVATION_FIELD = 'ele';
|
|
55
|
+
export function rewriteContourFields(value, options) {
|
|
56
|
+
const to = options.elevationField ?? DEFAULT_ELEVATION_FIELD;
|
|
57
|
+
if (options.schema !== 'div' || to === MAPBOX_ELEVATION_FIELD)
|
|
58
|
+
return value;
|
|
59
|
+
return renameField(value, MAPBOX_ELEVATION_FIELD, to);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=contour.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contour.js","sourceRoot":"","sources":["../../src/mapbox2css/contour.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the translation could not carry. Every drop is counted and named: a converter that stays
|
|
3
|
+
* quiet about what it skipped reads as "fully converted" when it was not.
|
|
4
|
+
*/
|
|
5
|
+
export class Coverage {
|
|
6
|
+
emitted = new Map();
|
|
7
|
+
dropped = new Map();
|
|
8
|
+
notes = [];
|
|
9
|
+
/** Translations that carried the property but not exactly. Counted, never silent. */
|
|
10
|
+
approximations = new Map();
|
|
11
|
+
emit(property) {
|
|
12
|
+
this.emitted.set(property, (this.emitted.get(property) ?? 0) + 1);
|
|
13
|
+
}
|
|
14
|
+
drop(property, reason, layerId) {
|
|
15
|
+
const entry = this.dropped.get(property) ?? { count: 0, reason, layers: new Set() };
|
|
16
|
+
entry.count++;
|
|
17
|
+
entry.layers.add(layerId);
|
|
18
|
+
this.dropped.set(property, entry);
|
|
19
|
+
}
|
|
20
|
+
note(message) {
|
|
21
|
+
this.notes.push(message);
|
|
22
|
+
}
|
|
23
|
+
approximate(what) {
|
|
24
|
+
this.approximations.set(what, (this.approximations.get(what) ?? 0) + 1);
|
|
25
|
+
}
|
|
26
|
+
get emittedCount() {
|
|
27
|
+
return [...this.emitted.values()].reduce((a, b) => a + b, 0);
|
|
28
|
+
}
|
|
29
|
+
get droppedCount() {
|
|
30
|
+
return [...this.dropped.values()].reduce((a, b) => a + b.count, 0);
|
|
31
|
+
}
|
|
32
|
+
report() {
|
|
33
|
+
const total = this.emittedCount + this.droppedCount;
|
|
34
|
+
const pct = total === 0 ? 100 : Math.round((this.emittedCount / total) * 100);
|
|
35
|
+
const lines = [`Coverage: ${this.emittedCount}/${total} properties (${pct}%)`];
|
|
36
|
+
if (this.dropped.size > 0) {
|
|
37
|
+
lines.push('', 'Dropped:');
|
|
38
|
+
const ranked = [...this.dropped.entries()].sort((a, b) => b[1].count - a[1].count);
|
|
39
|
+
for (const [property, { count, reason, layers }] of ranked) {
|
|
40
|
+
const where = layers.size <= 3 ? [...layers].join(', ') : `${layers.size} layers`;
|
|
41
|
+
lines.push(` ${String(count).padStart(4)}x ${property.padEnd(34)} ${reason} (${where})`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (this.approximations.size > 0) {
|
|
45
|
+
lines.push('', 'Approximated:');
|
|
46
|
+
for (const [what, count] of [...this.approximations.entries()].sort((a, b) => b[1] - a[1])) {
|
|
47
|
+
lines.push(` ${String(count).padStart(4)}x ${what}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (this.notes.length > 0) {
|
|
51
|
+
lines.push('', 'Notes:', ...this.notes.map((n) => ` ${n}`));
|
|
52
|
+
}
|
|
53
|
+
return lines.join('\n');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=coverage.js.map
|