@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
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# @massif-maps/style-tools
|
|
2
|
+
|
|
3
|
+
Style conversion for [Massif Maps](https://github.com/massif-maps/MassifMaps). One command,
|
|
4
|
+
`massif-style`, with no toolchain to install.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npx @massif-maps/style-tools css2xml style/project.json style.xml
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Subcommands
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `css2xml <project.json> <out.xml>` | compile a CartoCSS style project to the mapnik XML the decoder reads |
|
|
15
|
+
| `mapbox2css <style.json> <outdir>` | translate a MapBox/MapLibre style to a CartoCSS project |
|
|
16
|
+
| `legend <project.json> [--spec legend.json] [--params k=v]... [--svg out.svg]` | resolve a [legend spec](../../docs/features/legends.md) against the style, as JSON, and optionally draw it |
|
|
17
|
+
|
|
18
|
+
`css2xml` runs the SDK's own C++ compiled to WebAssembly — the same compiler the map uses at
|
|
19
|
+
runtime, so what compiles here renders there. `mapbox2css` is TypeScript.
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
massif-style css2xml --roundtrip project.json out.xml # also parse the XML back and diff
|
|
23
|
+
massif-style legend project.json --params variant=eink --svg legend.svg # the legend as a parameter paints it
|
|
24
|
+
massif-style mapbox2css style.json out/ --validate # compile the result before writing it
|
|
25
|
+
massif-style mapbox2css topo.json out/ --contour-schema div # nth_line -> div contour attributes
|
|
26
|
+
massif-style mapbox2css standard.json out/ --schema openmaptiles # read OpenMapTiles tiles instead
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`--schema openmaptiles` retargets the style at an OpenMapTiles tileset. Both **MapBox Streets v8**
|
|
30
|
+
and **MapTiler `planet_v4`** are understood as the source, detected from the style's own source-layer
|
|
31
|
+
names (`--source-schema mapbox|maptiler` says it outright). Layer names, field names and field values
|
|
32
|
+
are all rewritten, one source layer can feed several target ones, and anything without an equivalent
|
|
33
|
+
is dropped and named in the coverage report rather than guessed at. See
|
|
34
|
+
[the docs](https://massif-maps.github.io/MassifMaps/docs/contributing/style-tools#retargeting-at-another-tile-schema---schema).
|
|
35
|
+
|
|
36
|
+
`--contour-schema div` rewrites contour-layer `nth_line` tests onto a `div` (interval in metres)
|
|
37
|
+
attribute, for tiles built with the gdal ladder rather than MapTiler's schema. Only the major/minor
|
|
38
|
+
split survives — the base interval is not in the style — and `--contour-major-div` (default 100)
|
|
39
|
+
sets the threshold. Colours and widths are untouched.
|
|
40
|
+
|
|
41
|
+
`mapbox2css` skips MapBox properties CartoCSS has no equivalent for and prints a coverage report
|
|
42
|
+
naming each one and how often it appeared. `--strict` turns any skipped property into a non-zero
|
|
43
|
+
exit.
|
|
44
|
+
|
|
45
|
+
## Requirements
|
|
46
|
+
|
|
47
|
+
Node 20 or newer. The wasm build uses `NODERAWFS`, so it runs under Node only — not in a browser.
|
|
48
|
+
|
|
49
|
+
## Development
|
|
50
|
+
|
|
51
|
+
The wasm is built from `libs-massif/cartocss` and is **not** in the repository. Either build it
|
|
52
|
+
(see [the docs](https://massif-maps.github.io/MassifMaps/docs/contributing/style-tools)) or download
|
|
53
|
+
`massif-style.wasm` and `massif-style.mjs` from an SDK
|
|
54
|
+
[release](https://github.com/massif-maps/MassifMaps/releases) into `wasm/`.
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
npm ci && npm run build && npm test
|
|
58
|
+
```
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, extname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { VARIABLES_FILE, convert } from './mapbox2css/index.js';
|
|
7
|
+
import { nodeSpriteHost } from './mapbox2css/node-host.js';
|
|
8
|
+
import { loadSprites, setSpriteHost } from './mapbox2css/sprite.js';
|
|
9
|
+
import { renderLegendSvg } from './legend-svg.js';
|
|
10
|
+
import { WasmMissing, runWasm, wasmAvailable } from './wasm.js';
|
|
11
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
/**
|
|
13
|
+
* Sides a POI name may take when --shield-anchors is passed with no list of its own. MapBox's own
|
|
14
|
+
* styles that DO use text-variable-anchor state exactly this order, and the horizontal sides come
|
|
15
|
+
* first because a name beside an icon reads better than one under it.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_SHIELD_ANCHORS = 'right,left,top,bottom';
|
|
18
|
+
/** What ShieldSymbolizer::parseAnchors accepts - the corners spelled without the hyphen. */
|
|
19
|
+
const SHIELD_ANCHORS = new Set([
|
|
20
|
+
'center', 'top', 'bottom', 'left', 'right', 'topleft', 'topright', 'bottomleft', 'bottomright',
|
|
21
|
+
]);
|
|
22
|
+
const USAGE = `Usage: massif-style <command> [options] [args]
|
|
23
|
+
|
|
24
|
+
mapbox2css <style.json> <out-dir> [--validate] [--strict] [--no-sprite]
|
|
25
|
+
[--sprite-key '?key=...']
|
|
26
|
+
[--contour-schema div] [--contour-major-div N]
|
|
27
|
+
[--label-spacing N] [--schema openmaptiles]
|
|
28
|
+
[--source-schema mapbox|maptiler]
|
|
29
|
+
translate a MapBox/MapLibre style to a CartoCSS project
|
|
30
|
+
|
|
31
|
+
--sprite-key query string appended to the style's sprite URLs, for a
|
|
32
|
+
provider that needs a key
|
|
33
|
+
--label-spacing N multiply the collision gap between labels; 1 is what the
|
|
34
|
+
style asks for, higher thins the map out
|
|
35
|
+
--shield-anchors [sides]
|
|
36
|
+
let a POI name take the first FREE side of its icon instead of
|
|
37
|
+
the one fixed place the style states, and draw the icon alone
|
|
38
|
+
when no side fits (shield-anchors + shield-text-optional).
|
|
39
|
+
Sides in preference order, comma separated; the default is
|
|
40
|
+
'${DEFAULT_SHIELD_ANCHORS}'. A layer that already states
|
|
41
|
+
text-variable-anchor keeps its own list
|
|
42
|
+
--icon-font FACE draw every SHIELD icon as a glyph of the FACE icon font instead of a
|
|
43
|
+
sprite (shield-icon-name + shield-icon-face-name), so the style ships
|
|
44
|
+
one font rather than a sheet of PNGs. Needs --icon-font-map. A marker
|
|
45
|
+
(a oneway arrow, a crossing) keeps its sprite - it has no glyph run
|
|
46
|
+
--icon-font-map FILE JSON mapping the style's icon-image names onto that face's characters:
|
|
47
|
+
{"mountain": "\\ue90a"} or {"mountain": "U+E90A"} or {"mountain": 59658}.
|
|
48
|
+
A name absent from it draws no icon, so country artwork (an RER
|
|
49
|
+
roundel, a national motorway plate) is lost - that is the trade
|
|
50
|
+
--icon-font-size PX the height in sprite pixels a glyph fills at icon-size 1, so icon-size
|
|
51
|
+
scales a glyph as it scales the sprite; unset, a multiple of text-size
|
|
52
|
+
--schema NAME retarget the style's source layers at another tile schema.
|
|
53
|
+
'openmaptiles' is the only target. A MapTiler planet_v4 style
|
|
54
|
+
becomes the OpenMapTiles layer plus the class filter that
|
|
55
|
+
stands in for its per-feature-type split (forest, grass,
|
|
56
|
+
city_label, peak, ...); a MapBox Streets v8 style is further
|
|
57
|
+
away and also gets its field names (height ->
|
|
58
|
+
render_height), its field values (class 'street' -> 'minor')
|
|
59
|
+
and its one-layer-two-targets splits (road is both
|
|
60
|
+
transportation and transportation_name) rewritten. A layer
|
|
61
|
+
with no equivalent is dropped and named in the coverage report
|
|
62
|
+
--source-schema NAME which vocabulary the style itself is written in, 'mapbox' or
|
|
63
|
+
'maptiler'. Detected from the source layer names when unset,
|
|
64
|
+
and conversion stops rather than guess when they are ambiguous
|
|
65
|
+
--no-sprite skip the sprite; every icon-image is then dropped
|
|
66
|
+
--no-variables keep the colours, fonts and sizes inline in style.mss instead of
|
|
67
|
+
hoisting them into a variables.mss a variant can override
|
|
68
|
+
--no-presets do not emit the extra lightPreset palettes (Mapbox Standard)
|
|
69
|
+
--config k=v set one of the style's own config values, for a style that declares a
|
|
70
|
+
schema (Mapbox Standard). Repeatable, and k=v,k2=v2 also works. Every
|
|
71
|
+
config read is resolved to a constant, so this is a build-time choice:
|
|
72
|
+
--config lightPreset=night is how the dark version is produced
|
|
73
|
+
--live-light leave the 2D colours as the style authored them and carry its
|
|
74
|
+
emissive strengths instead, for an SDK that lights them at draw
|
|
75
|
+
time. One palette then covers every light preset and the hour can
|
|
76
|
+
be changed at runtime. Off, the light is folded into the colours
|
|
77
|
+
and a palette is emitted per preset
|
|
78
|
+
--label-emissive N a CAP on every text and icon emissive, and the default where the
|
|
79
|
+
style states none. MapBox's own default is 1 - a label drawn as
|
|
80
|
+
authored at any hour - and Standard states 1 on its shields
|
|
81
|
+
deliberately, so a cap is what makes them follow the light too.
|
|
82
|
+
Needs --live-light
|
|
83
|
+
--halo-emissive N the same for a label's HALO, which the SDK grades separately: the
|
|
84
|
+
ink keeps its emissive and stays bright while the outline takes
|
|
85
|
+
this one and goes dark with the scene, so a name stays readable
|
|
86
|
+
over a map that darkens. Needs --live-light
|
|
87
|
+
--geometry-emissive N a FLOOR on what a fill, line or background emissive defaults to
|
|
88
|
+
where the style states none. MapBox's own default is 0 -
|
|
89
|
+
entirely at the mercy of the light - which collapses a style
|
|
90
|
+
with no light model of its own as soon as the sun is down.
|
|
91
|
+
Needs --live-light
|
|
92
|
+
--building-height-ramp grow the extrusions in over a third of a zoom level where the
|
|
93
|
+
style states no fill-extrusion-vertical-scale of its own
|
|
94
|
+
--ao-follows-height fade the ground AO on the same ramp that lays the buildings down as
|
|
95
|
+
the camera tilts over, so a flattened city does not keep a dark ring
|
|
96
|
+
around every footprint. Off by default: whether the contact shadow
|
|
97
|
+
outlives the walls is the style's call, not the renderer's
|
|
98
|
+
--sdf-flatten resolve SDF icons to plain bitmaps, for an SDK without
|
|
99
|
+
marker-sdf; loses the zoom-driven size and the halo
|
|
100
|
+
--fold-casings fold a casing layer into the fill it runs under, as one
|
|
101
|
+
line-border-* rule. Halves those rules and their geometry,
|
|
102
|
+
and MOVES the casing: it then draws per class instead of
|
|
103
|
+
under every fill
|
|
104
|
+
--fonts DIR copy the .ttf/.otf faces in DIR into the project's fonts/ and list
|
|
105
|
+
them in project.json. The decoder registers a style's own fonts ahead
|
|
106
|
+
of the system ones, which is how a face reaches a build that has none
|
|
107
|
+
--tile-draw-size N the Options::TileDrawSize the style will be drawn at, in dp.
|
|
108
|
+
Shifts every zoom stop by log2(512 / N); the default 256 is
|
|
109
|
+
the SDK's own, 512 an app on maplibre's convention
|
|
110
|
+
--contour-schema div rewrite contour-layer nth_line tests onto a div (interval in
|
|
111
|
+
metres) attribute; --contour-major-div is the major threshold,
|
|
112
|
+
and --contour-elevation is what the target tiles call the
|
|
113
|
+
elevation (default ele; MapTiler's own say height),
|
|
114
|
+
default 100
|
|
115
|
+
|
|
116
|
+
css2xml [--roundtrip] <project.json> <out.xml>
|
|
117
|
+
compile a CartoCSS style project to mapnik XML
|
|
118
|
+
|
|
119
|
+
legend <project.json> [--spec legend.json] [--params k=v]... [--out out.json]
|
|
120
|
+
[--svg out.svg] [--lang en]
|
|
121
|
+
resolve a legend spec against the style: every item is a synthetic feature, and comes
|
|
122
|
+
back as the swatch the style draws it with - lines, fill, icon, road plate, text - as
|
|
123
|
+
the SDK's MBVectorTileDecoder.getLegend returns it
|
|
124
|
+
|
|
125
|
+
--spec FILE the spec; legend.json beside the project by default
|
|
126
|
+
--params k=v a style parameter value, as setStyleParameter takes it. Repeatable
|
|
127
|
+
--out FILE write the JSON there instead of stdout
|
|
128
|
+
--svg FILE also draw the legend as an SVG sheet, images inlined
|
|
129
|
+
--lang CODE which label to draw when a label is a {lang: text} object
|
|
130
|
+
`;
|
|
131
|
+
function loadPropertyTable() {
|
|
132
|
+
// dist/cli.js -> dist/generated; src/cli.ts -> src/generated.
|
|
133
|
+
return JSON.parse(readFileSync(join(HERE, 'generated', 'properties.json'), 'utf8'));
|
|
134
|
+
}
|
|
135
|
+
/** `--flag`, `--key value` and `--key=value`, which is as much as this CLI needs. */
|
|
136
|
+
function parseFlags(args) {
|
|
137
|
+
const flags = new Map();
|
|
138
|
+
const positional = [];
|
|
139
|
+
for (let i = 0; i < args.length; i++) {
|
|
140
|
+
const arg = args[i];
|
|
141
|
+
if (!arg.startsWith('--')) {
|
|
142
|
+
positional.push(arg);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const eq = arg.indexOf('=');
|
|
146
|
+
if (eq !== -1) {
|
|
147
|
+
flags.set(arg.slice(2, eq), arg.slice(eq + 1));
|
|
148
|
+
}
|
|
149
|
+
else if (i + 1 < args.length && !args[i + 1].startsWith('--') && VALUE_FLAGS.has(arg.slice(2))) {
|
|
150
|
+
flags.set(arg.slice(2), args[++i]);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
flags.set(arg.slice(2), '');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { flags, positional };
|
|
157
|
+
}
|
|
158
|
+
const VALUE_FLAGS = new Set(['shield-anchors', 'icon-font', 'icon-font-map', 'icon-font-size', 'contour-schema', 'contour-major-div', 'sprite-key', 'label-spacing', 'tile-draw-size', 'fonts', 'label-emissive', 'halo-emissive', 'geometry-emissive', 'contour-elevation', 'schema', 'source-schema', 'config', 'spec', 'params', 'out', 'svg', 'lang']);
|
|
159
|
+
/**
|
|
160
|
+
* `--config key=value`, repeatable, for a style with a `schema` (Mapbox Standard). Values are read
|
|
161
|
+
* as JSON when they parse - so `show3dObjects=false` and `densityPointOfInterestLabels=2` arrive as
|
|
162
|
+
* a boolean and a number - and as a plain string otherwise, which is what a colour or a preset is.
|
|
163
|
+
*/
|
|
164
|
+
function parseConfig(args) {
|
|
165
|
+
const config = {};
|
|
166
|
+
for (let i = 0; i < args.length; i++) {
|
|
167
|
+
const arg = args[i];
|
|
168
|
+
const pair = arg === '--config' ? args[++i] : arg.startsWith('--config=') ? arg.slice('--config='.length) : null;
|
|
169
|
+
if (!pair)
|
|
170
|
+
continue;
|
|
171
|
+
for (const entry of pair.split(',')) {
|
|
172
|
+
const eq = entry.indexOf('=');
|
|
173
|
+
if (eq === -1)
|
|
174
|
+
continue;
|
|
175
|
+
const [key, raw] = [entry.slice(0, eq).trim(), entry.slice(eq + 1).trim()];
|
|
176
|
+
try {
|
|
177
|
+
config[key] = JSON.parse(raw);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
config[key] = raw;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return config;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The icon face's own character per icon name. An icon-font builder emits the codepoint in any of
|
|
188
|
+
* three ways - the character itself, a `U+E90A`/`0xE90A`/`e90a` codepoint, or a number - and all
|
|
189
|
+
* three are the same thing, so all three are read rather than making the caller convert.
|
|
190
|
+
*/
|
|
191
|
+
function readGlyphMap(file) {
|
|
192
|
+
let raw;
|
|
193
|
+
try {
|
|
194
|
+
raw = JSON.parse(readFileSync(file, 'utf8'));
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
process.stderr.write(`--icon-font-map ${file}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
201
|
+
process.stderr.write(`--icon-font-map ${file}: expected an object of name -> character.\n`);
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const glyphs = new Map();
|
|
205
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
206
|
+
if (typeof value === 'number') {
|
|
207
|
+
glyphs.set(name, String.fromCodePoint(value));
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
211
|
+
process.stderr.write(`--icon-font-map ${file}: "${name}" is not a character or a codepoint.\n`);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const codepoint = /^(?:U\+|0x|\\u)?([0-9a-f]{4,6})$/i.exec(value);
|
|
215
|
+
// A bare 4-6 hex-digit string is a codepoint, never a name: no icon face carries a glyph
|
|
216
|
+
// whose CHARACTER is "e90a".
|
|
217
|
+
glyphs.set(name, codepoint ? String.fromCodePoint(parseInt(codepoint[1], 16)) : value);
|
|
218
|
+
}
|
|
219
|
+
if (glyphs.size === 0) {
|
|
220
|
+
process.stderr.write(`--icon-font-map ${file}: no glyphs in it.\n`);
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
return glyphs;
|
|
224
|
+
}
|
|
225
|
+
async function mapbox2css(args) {
|
|
226
|
+
const { flags, positional } = parseFlags(args);
|
|
227
|
+
const [input, outDir] = positional;
|
|
228
|
+
if (!input || !outDir) {
|
|
229
|
+
process.stderr.write(USAGE);
|
|
230
|
+
return 2;
|
|
231
|
+
}
|
|
232
|
+
const contourSchema = flags.get('contour-schema');
|
|
233
|
+
if (contourSchema !== undefined && contourSchema !== 'div') {
|
|
234
|
+
process.stderr.write(`Unknown --contour-schema "${contourSchema}"; only "div" is supported.\n`);
|
|
235
|
+
return 2;
|
|
236
|
+
}
|
|
237
|
+
const schema = flags.get('schema');
|
|
238
|
+
if (schema !== undefined && schema !== 'openmaptiles') {
|
|
239
|
+
process.stderr.write(`Unknown --schema "${schema}"; only "openmaptiles" is supported.\n`);
|
|
240
|
+
return 2;
|
|
241
|
+
}
|
|
242
|
+
const sourceSchema = flags.get('source-schema');
|
|
243
|
+
if (sourceSchema !== undefined && sourceSchema !== 'mapbox' && sourceSchema !== 'maptiler') {
|
|
244
|
+
process.stderr.write(`Unknown --source-schema "${sourceSchema}"; "mapbox" or "maptiler".\n`);
|
|
245
|
+
return 2;
|
|
246
|
+
}
|
|
247
|
+
let shieldAnchors;
|
|
248
|
+
if (flags.has('shield-anchors')) {
|
|
249
|
+
shieldAnchors = (flags.get('shield-anchors') || DEFAULT_SHIELD_ANCHORS)
|
|
250
|
+
.split(',').map((a) => a.trim().replace('-', '')).filter(Boolean);
|
|
251
|
+
const unknown = shieldAnchors.filter((a) => !SHIELD_ANCHORS.has(a));
|
|
252
|
+
if (unknown.length > 0) {
|
|
253
|
+
process.stderr.write(`Unknown --shield-anchors side(s): ${unknown.join(', ')}; `
|
|
254
|
+
+ `one of ${[...SHIELD_ANCHORS].join(', ')}.\n`);
|
|
255
|
+
return 2;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const face = flags.get('icon-font');
|
|
259
|
+
const mapFile = flags.get('icon-font-map');
|
|
260
|
+
if ((face === undefined) !== (mapFile === undefined)) {
|
|
261
|
+
process.stderr.write('--icon-font and --icon-font-map go together: the face names the font, '
|
|
262
|
+
+ "the map says which character it carries each of the style's icons at.\n");
|
|
263
|
+
return 2;
|
|
264
|
+
}
|
|
265
|
+
let iconFont;
|
|
266
|
+
if (face && mapFile) {
|
|
267
|
+
const glyphs = readGlyphMap(mapFile);
|
|
268
|
+
if (glyphs === null)
|
|
269
|
+
return 2;
|
|
270
|
+
const size = flags.get('icon-font-size');
|
|
271
|
+
iconFont = { face, glyphs, ...(size !== undefined ? { size: Number(size) } : {}) };
|
|
272
|
+
process.stdout.write(`Icon font "${face}": ${glyphs.size} glyph(s).\n`);
|
|
273
|
+
}
|
|
274
|
+
const style = JSON.parse(readFileSync(input, 'utf8'));
|
|
275
|
+
// Icons need the sprite sheet, which the style only points at - so this is opt-in and says
|
|
276
|
+
// what it fetches rather than reaching out silently.
|
|
277
|
+
let sprites;
|
|
278
|
+
if (!flags.has('no-sprite')) {
|
|
279
|
+
try {
|
|
280
|
+
const sheets = await loadSprites(style, flags.get('sprite-key') ?? '');
|
|
281
|
+
if (sheets.size > 0) {
|
|
282
|
+
process.stdout.write(`Loaded ${sheets.size} sprite sheet(s).\n`);
|
|
283
|
+
sprites = { sheets, outDir };
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
process.stderr.write(`Sprite not loaded (${error instanceof Error ? error.message : String(error)}); icons will be dropped.\n`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// A style CARRIES its fonts: the decoder registers everything under <style>/fonts/ ahead of the
|
|
291
|
+
// system ones, which is the only way a face reaches a build with no system fonts at all - the
|
|
292
|
+
// web one. Only the faces a style actually names are worth carrying; they are preloaded nowhere.
|
|
293
|
+
const fontDir = flags.get('fonts');
|
|
294
|
+
const fontFiles = fontDir
|
|
295
|
+
? readdirSync(fontDir).filter((name) => /\.(?:ttf|otf|ttc)$/i.test(name)).sort()
|
|
296
|
+
: [];
|
|
297
|
+
const { mss, project, coverage, variables, presets, defaultPreset, presetOverrides } = convert(style, loadPropertyTable(), {
|
|
298
|
+
sprites,
|
|
299
|
+
variables: !flags.has('no-variables'),
|
|
300
|
+
liveLight: flags.has('live-light'),
|
|
301
|
+
labelEmissive: flags.has('label-emissive') ? Number(flags.get('label-emissive')) : undefined,
|
|
302
|
+
haloEmissive: flags.has('halo-emissive') ? Number(flags.get('halo-emissive')) : undefined,
|
|
303
|
+
geometryEmissive: flags.has('geometry-emissive') ? Number(flags.get('geometry-emissive')) : undefined,
|
|
304
|
+
buildingHeightRamp: flags.has('building-height-ramp'),
|
|
305
|
+
aoFollowsHeight: flags.has('ao-follows-height'),
|
|
306
|
+
config: parseConfig(args),
|
|
307
|
+
presets: flags.has('no-presets') ? [] : undefined,
|
|
308
|
+
flattenSdf: flags.has('sdf-flatten'),
|
|
309
|
+
foldCasings: flags.has('fold-casings'),
|
|
310
|
+
labelSpacing: Number(flags.get('label-spacing') ?? 1),
|
|
311
|
+
tileDrawSize: Number(flags.get('tile-draw-size') ?? 256),
|
|
312
|
+
fonts: fontFiles,
|
|
313
|
+
shieldAnchors: shieldAnchors?.join(','),
|
|
314
|
+
iconFont,
|
|
315
|
+
schema: schema === 'openmaptiles' ? 'openmaptiles' : undefined,
|
|
316
|
+
sourceSchema,
|
|
317
|
+
contour: contourSchema === 'div'
|
|
318
|
+
? {
|
|
319
|
+
schema: 'div',
|
|
320
|
+
majorDiv: Number(flags.get('contour-major-div') ?? 100),
|
|
321
|
+
elevationField: flags.get('contour-elevation') ?? undefined,
|
|
322
|
+
}
|
|
323
|
+
: undefined,
|
|
324
|
+
});
|
|
325
|
+
mkdirSync(outDir, { recursive: true });
|
|
326
|
+
writeFileSync(join(outDir, 'style.mss'), mss);
|
|
327
|
+
writeFileSync(join(outDir, 'project.json'), project);
|
|
328
|
+
if (fontDir && fontFiles.length > 0) {
|
|
329
|
+
mkdirSync(join(outDir, 'fonts'), { recursive: true });
|
|
330
|
+
for (const name of fontFiles)
|
|
331
|
+
copyFileSync(join(fontDir, name), join(outDir, 'fonts', name));
|
|
332
|
+
}
|
|
333
|
+
if (variables)
|
|
334
|
+
writeFileSync(join(outDir, VARIABLES_FILE), variables);
|
|
335
|
+
// One palette per other light preset, plus the project that picks it. Same style.mss.
|
|
336
|
+
const overrides = presetOverrides ?? new Map();
|
|
337
|
+
for (const [preset, palette] of presets) {
|
|
338
|
+
writeFileSync(join(outDir, `${preset}.mss`), palette);
|
|
339
|
+
const params = overrides.get(preset);
|
|
340
|
+
writeFileSync(join(outDir, `${preset}.json`), `${JSON.stringify({
|
|
341
|
+
extends: './project.json', styles: [`${preset}.mss`, 'style.mss'],
|
|
342
|
+
...(params ? { styleparameters: params } : {}),
|
|
343
|
+
}, null, 2)}\n`);
|
|
344
|
+
}
|
|
345
|
+
if (defaultPreset) {
|
|
346
|
+
writeFileSync(join(outDir, `${defaultPreset}.json`), `${JSON.stringify({
|
|
347
|
+
extends: './project.json', styles: [VARIABLES_FILE, 'style.mss'],
|
|
348
|
+
}, null, 2)}\n`);
|
|
349
|
+
}
|
|
350
|
+
if (presets.size > 0) {
|
|
351
|
+
process.stdout.write(`Light presets: ${[defaultPreset, ...presets.keys()].filter(Boolean).join(', ')}`
|
|
352
|
+
+ ' (one palette each, over the same style.mss).\n');
|
|
353
|
+
}
|
|
354
|
+
process.stdout.write(`${coverage.report()}\n`);
|
|
355
|
+
if (flags.has('validate')) {
|
|
356
|
+
if (!wasmAvailable()) {
|
|
357
|
+
process.stderr.write('--validate needs massif-style.mjs; skipping validation.\n');
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
const status = await runWasm(['css2xml', join(outDir, 'project.json'), join(outDir, 'style.xml')]);
|
|
361
|
+
if (status !== 0) {
|
|
362
|
+
process.stderr.write('Validation failed: the generated CartoCSS did not compile.\n');
|
|
363
|
+
return status;
|
|
364
|
+
}
|
|
365
|
+
process.stdout.write('Validated: the generated CartoCSS compiles.\n');
|
|
366
|
+
}
|
|
367
|
+
if (flags.has('strict') && coverage.droppedCount > 0) {
|
|
368
|
+
process.stderr.write(`--strict: ${coverage.droppedCount} properties dropped.\n`);
|
|
369
|
+
return 1;
|
|
370
|
+
}
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
const IMAGE_TYPES = { '.png': 'image/png', '.svg': 'image/svg+xml', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg' };
|
|
374
|
+
async function legend(args) {
|
|
375
|
+
const { flags, positional } = parseFlags(args);
|
|
376
|
+
const [project] = positional;
|
|
377
|
+
if (!project) {
|
|
378
|
+
process.stderr.write(USAGE);
|
|
379
|
+
return 2;
|
|
380
|
+
}
|
|
381
|
+
const svg = flags.get('svg');
|
|
382
|
+
// --svg and --lang are drawn here; every other option is the C++ command's own.
|
|
383
|
+
const local = ['--svg', '--lang'];
|
|
384
|
+
const wasmArgs = args.filter((arg, i) => !local.includes(arg) && !local.includes(args[i - 1]));
|
|
385
|
+
const out = flags.get('out') || (svg ? join(mkdtempSync(join(tmpdir(), 'massif-legend-')), 'legend.json') : undefined);
|
|
386
|
+
if (svg && !flags.get('out')) {
|
|
387
|
+
wasmArgs.push('--out', out);
|
|
388
|
+
}
|
|
389
|
+
const status = await runWasm(['legend', ...wasmArgs]);
|
|
390
|
+
if (status !== 0 || !svg || !out) {
|
|
391
|
+
return status;
|
|
392
|
+
}
|
|
393
|
+
if (!flags.get('out')) {
|
|
394
|
+
process.stdout.write(`${readFileSync(out, 'utf8')}\n`);
|
|
395
|
+
}
|
|
396
|
+
// Inlined, so the sheet still shows its icons once it is moved away from the project.
|
|
397
|
+
const folder = dirname(project);
|
|
398
|
+
const imageHref = (file) => {
|
|
399
|
+
const path = join(folder, file);
|
|
400
|
+
const type = IMAGE_TYPES[extname(file).toLowerCase()];
|
|
401
|
+
return type && existsSync(path) ? `data:${type};base64,${readFileSync(path).toString('base64')}` : file;
|
|
402
|
+
};
|
|
403
|
+
writeFileSync(svg, renderLegendSvg(JSON.parse(readFileSync(out, 'utf8')), { lang: flags.get('lang'), imageHref }));
|
|
404
|
+
return 0;
|
|
405
|
+
}
|
|
406
|
+
async function main(argv) {
|
|
407
|
+
// The slicer reads and writes through a host so it can also run in a browser; here it is node.
|
|
408
|
+
setSpriteHost(nodeSpriteHost);
|
|
409
|
+
const [command, ...args] = argv;
|
|
410
|
+
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
|
411
|
+
process.stdout.write(USAGE);
|
|
412
|
+
return command ? 0 : 2;
|
|
413
|
+
}
|
|
414
|
+
try {
|
|
415
|
+
if (command === 'mapbox2css')
|
|
416
|
+
return await mapbox2css(args);
|
|
417
|
+
if (command === 'css2xml')
|
|
418
|
+
return await runWasm([command, ...args]);
|
|
419
|
+
if (command === 'legend')
|
|
420
|
+
return await legend(args);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
if (error instanceof WasmMissing) {
|
|
424
|
+
process.stderr.write(`${error.message}\n`);
|
|
425
|
+
return 1;
|
|
426
|
+
}
|
|
427
|
+
throw error;
|
|
428
|
+
}
|
|
429
|
+
process.stderr.write(`Unknown command: ${command}\n\n${USAGE}`);
|
|
430
|
+
return 2;
|
|
431
|
+
}
|
|
432
|
+
main(process.argv.slice(2)).then((code) => { process.exitCode = code; }, (error) => {
|
|
433
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
434
|
+
process.exitCode = 1;
|
|
435
|
+
});
|
|
436
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|