@versatiles/style 3.5.2 → 3.6.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 +110 -14
- package/dist/index.d.ts +9 -4
- package/dist/index.js +13 -3
- package/dist/index.test.js +55 -24
- package/dist/lib/decorator.js +4 -0
- package/dist/lib/random_color.d.ts +9 -0
- package/dist/lib/random_color.js +150 -0
- package/dist/lib/random_color.test.d.ts +1 -0
- package/dist/lib/random_color.test.js +68 -0
- package/dist/lib/recolor.d.ts +3 -2
- package/dist/lib/recolor.js +2 -1
- package/dist/lib/recolor.test.d.ts +13 -1
- package/dist/lib/recolor.test.js +23 -10
- package/dist/lib/shortbread/layers.js +4 -4
- package/dist/lib/style_builder.d.ts +8 -15
- package/dist/lib/style_builder.js +50 -39
- package/dist/lib/style_builder.test.js +9 -15
- package/dist/lib/style_guesser.d.ts +2 -0
- package/dist/lib/style_guesser.js +148 -0
- package/dist/lib/style_guesser.test.d.ts +1 -0
- package/dist/lib/style_guesser.test.js +57 -0
- package/dist/lib/types.d.ts +34 -12
- package/dist/lib/types.js +4 -4
- package/dist/style/colorful.d.ts +4 -4
- package/dist/style/colorful.js +3 -3
- package/dist/style/graybeard.js +2 -2
- package/dist/style/neutrino.d.ts +4 -4
- package/dist/style/neutrino.js +3 -3
- package/package.json +16 -15
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import Color from 'color';
|
|
2
|
-
import type {
|
|
3
|
-
export default abstract class StyleBuilder {
|
|
2
|
+
import type { MaplibreStyle, StyleRules, StyleRulesOptions, StylemakerColorStrings, StylemakerColors, StylemakerFontStrings, StylemakerOptions } from './types.js';
|
|
3
|
+
export default abstract class StyleBuilder<Subclass extends StyleBuilder<Subclass>> {
|
|
4
4
|
#private;
|
|
5
|
-
baseUrl: string;
|
|
6
|
-
glyphsUrl: string;
|
|
7
|
-
spriteUrl: string;
|
|
8
|
-
tilesUrls: string[];
|
|
9
|
-
hideLabels: boolean;
|
|
10
|
-
languageSuffix: LanguageSuffix;
|
|
11
|
-
recolor: RecolorOptions;
|
|
12
5
|
abstract readonly name: string;
|
|
13
|
-
abstract
|
|
14
|
-
abstract
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
protected
|
|
18
|
-
protected abstract getStyleRules(
|
|
6
|
+
abstract readonly defaultColors: StylemakerColorStrings<Subclass>;
|
|
7
|
+
abstract readonly defaultFonts: StylemakerFontStrings<Subclass>;
|
|
8
|
+
build(options?: StylemakerOptions<Subclass>): MaplibreStyle;
|
|
9
|
+
getColors(colors: StylemakerColorStrings<Subclass>): StylemakerColors<Subclass>;
|
|
10
|
+
protected transformDefaultColors(callback: (color: Color) => Color): void;
|
|
11
|
+
protected abstract getStyleRules(options: StyleRulesOptions<Subclass>): StyleRules;
|
|
19
12
|
}
|
|
@@ -3,42 +3,46 @@ import getShortbreadTemplate from './shortbread/template.js';
|
|
|
3
3
|
import getShortbreadLayers from './shortbread/layers.js';
|
|
4
4
|
import { decorate } from './decorator.js';
|
|
5
5
|
import { getDefaultRecolorFlags, recolor } from './recolor.js';
|
|
6
|
+
import { deepClone } from './utils.js';
|
|
6
7
|
// Stylemaker class definition
|
|
7
8
|
export default class StyleBuilder {
|
|
8
|
-
baseUrl;
|
|
9
|
-
glyphsUrl = '/assets/fonts/{fontstack}/{range}.pbf';
|
|
10
|
-
spriteUrl = '/assets/sprites/sprites';
|
|
11
|
-
tilesUrls = ['/tiles/osm/{z}/{x}/{y}'];
|
|
12
|
-
hideLabels = false;
|
|
13
|
-
languageSuffix = '';
|
|
14
|
-
recolor = getDefaultRecolorFlags();
|
|
15
9
|
#sourceName = 'versatiles-shortbread';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
build(options) {
|
|
11
|
+
options ??= {};
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
13
|
+
const baseUrl = options.baseUrl ?? globalThis?.document?.location?.href ?? 'https://tiles.versatiles.org';
|
|
14
|
+
const glyphsUrl = options.glyphsUrl ?? '/assets/fonts/{fontstack}/{range}.pbf';
|
|
15
|
+
const spriteUrl = options.spriteUrl ?? '/assets/sprites/sprites';
|
|
16
|
+
const tilesUrls = options.tilesUrls ?? ['/tiles/osm/{z}/{x}/{y}'];
|
|
17
|
+
const hideLabels = options.hideLabels ?? false;
|
|
18
|
+
const languageSuffix = options.languageSuffix ?? '';
|
|
19
|
+
const recolorOptions = options.recolor ?? getDefaultRecolorFlags();
|
|
20
|
+
const colors = this.getColors(this.defaultColors);
|
|
21
|
+
if (options.colors) {
|
|
22
|
+
for (const key in options.colors)
|
|
23
|
+
colors[key] = Color(options.colors[key]);
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
// transform colors
|
|
26
|
+
recolor(colors, recolorOptions);
|
|
27
|
+
const fonts = deepClone(this.defaultColors);
|
|
28
|
+
if (options.fonts) {
|
|
29
|
+
for (const key in options.fonts) {
|
|
30
|
+
const fontName = options.fonts[key];
|
|
31
|
+
if (fontName != null)
|
|
32
|
+
fonts[key] = fontName;
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
|
-
}
|
|
27
|
-
build() {
|
|
28
35
|
// get empty shortbread style
|
|
29
36
|
const style = getShortbreadTemplate();
|
|
30
|
-
const
|
|
31
|
-
.map(([name, colorString]) => [name, Color(colorString)]));
|
|
32
|
-
// transform colors
|
|
33
|
-
recolor(colors, this.recolor);
|
|
34
|
-
// get layer style rules from child class
|
|
35
|
-
const layerStyleRules = this.getStyleRules({
|
|
37
|
+
const styleRuleOptions = {
|
|
36
38
|
colors,
|
|
37
|
-
fonts: this.
|
|
38
|
-
languageSuffix
|
|
39
|
-
}
|
|
39
|
+
fonts: deepClone(this.defaultFonts),
|
|
40
|
+
languageSuffix,
|
|
41
|
+
};
|
|
42
|
+
// get layer style rules from child class
|
|
43
|
+
const layerStyleRules = this.getStyleRules(styleRuleOptions);
|
|
40
44
|
// get shortbread layers
|
|
41
|
-
const layerDefinitions = getShortbreadLayers({ languageSuffix
|
|
45
|
+
const layerDefinitions = getShortbreadLayers({ languageSuffix });
|
|
42
46
|
let layers = layerDefinitions.map(layer => {
|
|
43
47
|
switch (layer.type) {
|
|
44
48
|
case 'background':
|
|
@@ -56,28 +60,35 @@ export default class StyleBuilder {
|
|
|
56
60
|
// apply layer rules
|
|
57
61
|
layers = decorate(layers, layerStyleRules);
|
|
58
62
|
// hide labels, if wanted
|
|
59
|
-
if (
|
|
63
|
+
if (hideLabels)
|
|
60
64
|
layers = layers.filter(l => l.type !== 'symbol');
|
|
61
65
|
style.layers = layers;
|
|
62
|
-
style.name = 'versatiles-' + this.name;
|
|
63
|
-
style.glyphs = resolveUrl(
|
|
64
|
-
style.sprite = resolveUrl(
|
|
66
|
+
style.name = 'versatiles-' + this.name.toLowerCase();
|
|
67
|
+
style.glyphs = resolveUrl(baseUrl, glyphsUrl);
|
|
68
|
+
style.sprite = resolveUrl(baseUrl, spriteUrl);
|
|
65
69
|
const source = style.sources[this.#sourceName];
|
|
66
70
|
if ('tiles' in source)
|
|
67
|
-
source.tiles =
|
|
71
|
+
source.tiles = tilesUrls.map(url => resolveUrl(baseUrl, url));
|
|
68
72
|
return style;
|
|
69
|
-
function resolveUrl(
|
|
70
|
-
if (!Boolean(
|
|
73
|
+
function resolveUrl(base, url) {
|
|
74
|
+
if (!Boolean(base))
|
|
71
75
|
return url;
|
|
72
|
-
url = new URL(url,
|
|
76
|
+
url = new URL(url, base).href;
|
|
73
77
|
url = url.replace(/%7B/gi, '{');
|
|
74
78
|
url = url.replace(/%7D/gi, '}');
|
|
75
79
|
return url;
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
getColors(colors) {
|
|
83
|
+
const entriesString = Object.entries(colors);
|
|
84
|
+
const entriesColor = entriesString.map(([key, value]) => [key, Color(value)]);
|
|
85
|
+
const result = Object.fromEntries(entriesColor);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
transformDefaultColors(callback) {
|
|
89
|
+
const colors = this.getColors(this.defaultColors);
|
|
90
|
+
for (const key in colors) {
|
|
91
|
+
this.defaultColors[key] = callback(colors[key]).hexa();
|
|
92
|
+
}
|
|
82
93
|
}
|
|
83
94
|
}
|
|
@@ -4,10 +4,10 @@ import StyleBuilder from './style_builder.js';
|
|
|
4
4
|
// Mock class for abstract class StyleBuilder
|
|
5
5
|
class MockStyleBuilder extends StyleBuilder {
|
|
6
6
|
name = 'mock';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
defaultFonts = { regular: 'Arial' };
|
|
8
|
+
defaultColors = { primary: '#FF8800' };
|
|
9
9
|
negateColors() {
|
|
10
|
-
this.
|
|
10
|
+
this.transformDefaultColors(color => color.negate());
|
|
11
11
|
}
|
|
12
12
|
getStyleRules(opt) {
|
|
13
13
|
for (const color of Object.values(opt.colors))
|
|
@@ -20,7 +20,7 @@ class MockStyleBuilder extends StyleBuilder {
|
|
|
20
20
|
'water-area': {
|
|
21
21
|
textColor: opt.colors.primary,
|
|
22
22
|
textSize: 12,
|
|
23
|
-
textFont:
|
|
23
|
+
textFont: opt.fonts.regular,
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
@@ -41,11 +41,11 @@ describe('StyleBuilder', () => {
|
|
|
41
41
|
expect(style).toHaveProperty('glyphs');
|
|
42
42
|
expect(style).toHaveProperty('sprite');
|
|
43
43
|
});
|
|
44
|
-
it('should
|
|
45
|
-
const initialColor = builder.
|
|
44
|
+
it('should transform colors correctly', () => {
|
|
45
|
+
const initialColor = builder.defaultColors.primary;
|
|
46
46
|
builder.negateColors();
|
|
47
|
-
expect(builder.
|
|
48
|
-
expect(builder.
|
|
47
|
+
expect(builder.defaultColors.primary).not.toBe(initialColor);
|
|
48
|
+
expect(builder.defaultColors.primary).toBe(Color(initialColor).negate().hexa());
|
|
49
49
|
});
|
|
50
50
|
describe('build method', () => {
|
|
51
51
|
it('should create a style object', () => {
|
|
@@ -56,14 +56,8 @@ describe('StyleBuilder', () => {
|
|
|
56
56
|
expect(style).toHaveProperty('glyphs');
|
|
57
57
|
expect(style).toHaveProperty('sprite');
|
|
58
58
|
});
|
|
59
|
-
it('should convert color strings to Color instances', () => {
|
|
60
|
-
builder.build();
|
|
61
|
-
const colors = Object.values(builder.colors);
|
|
62
|
-
expect(colors.every((color) => typeof color === 'string')).toBe(true);
|
|
63
|
-
});
|
|
64
59
|
it('should resolve urls correctly', () => {
|
|
65
|
-
builder.baseUrl
|
|
66
|
-
const style = builder.build();
|
|
60
|
+
const style = builder.build({ baseUrl: 'https://my.base.url/' });
|
|
67
61
|
expect(style.glyphs).toBe('https://my.base.url/assets/fonts/{fontstack}/{range}.pbf');
|
|
68
62
|
expect(style.sprite).toBe('https://my.base.url/assets/sprites/sprites');
|
|
69
63
|
const source = style.sources['versatiles-shortbread'];
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/prefer-includes */
|
|
2
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
3
|
+
import { isTileJSONSpecification } from './types.js';
|
|
4
|
+
import randomColorGenerator from './random_color.js';
|
|
5
|
+
import Colorful from '../style/colorful.js';
|
|
6
|
+
export default function guess(spec) {
|
|
7
|
+
let tilejson;
|
|
8
|
+
const { format } = spec;
|
|
9
|
+
switch (format) {
|
|
10
|
+
case 'avif':
|
|
11
|
+
case 'jpg':
|
|
12
|
+
case 'png':
|
|
13
|
+
case 'webp':
|
|
14
|
+
tilejson = {
|
|
15
|
+
tilejson: '3.0.0',
|
|
16
|
+
type: 'raster',
|
|
17
|
+
...spec,
|
|
18
|
+
format,
|
|
19
|
+
};
|
|
20
|
+
break;
|
|
21
|
+
case 'pbf':
|
|
22
|
+
const { vector_layers } = spec;
|
|
23
|
+
if (vector_layers == null) {
|
|
24
|
+
throw Error('property vector_layers is required for vector tiles');
|
|
25
|
+
}
|
|
26
|
+
tilejson = {
|
|
27
|
+
tilejson: '3.0.0',
|
|
28
|
+
type: 'vector',
|
|
29
|
+
...spec,
|
|
30
|
+
format,
|
|
31
|
+
vector_layers,
|
|
32
|
+
};
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
if (!isTileJSONSpecification(tilejson))
|
|
36
|
+
throw Error();
|
|
37
|
+
switch (tilejson.type) {
|
|
38
|
+
case 'raster':
|
|
39
|
+
return getImageStyle(tilejson);
|
|
40
|
+
case 'vector':
|
|
41
|
+
if (isShortbread(tilejson)) {
|
|
42
|
+
return getShortbreadStyle(tilejson);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return getInspectorStyle(tilejson);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function isShortbread(spec) {
|
|
50
|
+
if (typeof spec !== 'object')
|
|
51
|
+
return false;
|
|
52
|
+
if (!('vector_layers' in spec))
|
|
53
|
+
return false;
|
|
54
|
+
if (!Array.isArray(spec.vector_layers))
|
|
55
|
+
return false;
|
|
56
|
+
const layerIds = new Set(spec.vector_layers.map(l => String(l.id)));
|
|
57
|
+
const shortbreadIds = ['place_labels', 'boundaries', 'boundary_labels', 'addresses', 'water_lines', 'water_lines_labels', 'dam_lines', 'dam_polygons', 'pier_lines', 'pier_polygons', 'bridges', 'street_polygons', 'streets_polygons_labels', 'ferries', 'streets', 'street_labels', 'street_labels_points', 'aerialways', 'public_transport', 'buildings', 'water_polygons', 'ocean', 'water_polygons_labels', 'land', 'sites', 'pois'];
|
|
58
|
+
return shortbreadIds.every(id => layerIds.has(id));
|
|
59
|
+
}
|
|
60
|
+
function getShortbreadStyle(spec) {
|
|
61
|
+
return new Colorful().build({
|
|
62
|
+
hideLabels: true,
|
|
63
|
+
tilesUrls: spec.tiles,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function getInspectorStyle(spec) {
|
|
67
|
+
const sourceName = 'vectorSource';
|
|
68
|
+
const layers = { background: [], circle: [], line: [], fill: [] };
|
|
69
|
+
layers.background.push({ 'id': 'background', 'type': 'background', 'paint': { 'background-color': '#fff' } });
|
|
70
|
+
const randomColor = randomColorGenerator();
|
|
71
|
+
spec.vector_layers.forEach((vector_layer) => {
|
|
72
|
+
let luminosity = 'bright', saturation, hue;
|
|
73
|
+
if (/water|ocean|lake|sea|river/.test(vector_layer.id))
|
|
74
|
+
hue = 'blue';
|
|
75
|
+
if (/state|country|place/.test(vector_layer.id))
|
|
76
|
+
hue = 'pink';
|
|
77
|
+
if (/road|highway|transport|streets/.test(vector_layer.id))
|
|
78
|
+
hue = 'orange';
|
|
79
|
+
if (/contour|building/.test(vector_layer.id))
|
|
80
|
+
hue = 'monochrome';
|
|
81
|
+
if (/building/.test(vector_layer.id))
|
|
82
|
+
luminosity = 'dark';
|
|
83
|
+
if (/contour|landuse/.test(vector_layer.id))
|
|
84
|
+
hue = 'yellow';
|
|
85
|
+
if (/wood|forest|park|landcover|land/.test(vector_layer.id))
|
|
86
|
+
hue = 'green';
|
|
87
|
+
if (/point/.test(vector_layer.id)) {
|
|
88
|
+
saturation = 'strong';
|
|
89
|
+
luminosity = 'light';
|
|
90
|
+
}
|
|
91
|
+
const color = randomColor({
|
|
92
|
+
hue,
|
|
93
|
+
luminosity,
|
|
94
|
+
saturation,
|
|
95
|
+
seed: vector_layer.id,
|
|
96
|
+
opacity: 0.6,
|
|
97
|
+
});
|
|
98
|
+
layers.circle.push({
|
|
99
|
+
id: `${sourceName}-${vector_layer.id}-circle`,
|
|
100
|
+
'source-layer': vector_layer.id,
|
|
101
|
+
source: sourceName,
|
|
102
|
+
type: 'circle',
|
|
103
|
+
filter: ['==', '$type', 'Point'],
|
|
104
|
+
paint: { 'circle-color': color, 'circle-radius': 2 },
|
|
105
|
+
});
|
|
106
|
+
layers.line.push({
|
|
107
|
+
id: `${sourceName}-${vector_layer.id}-line`,
|
|
108
|
+
'source-layer': vector_layer.id,
|
|
109
|
+
source: sourceName,
|
|
110
|
+
type: 'line',
|
|
111
|
+
filter: ['==', '$type', 'LineString'],
|
|
112
|
+
layout: { 'line-join': 'round', 'line-cap': 'round' },
|
|
113
|
+
paint: { 'line-color': color },
|
|
114
|
+
});
|
|
115
|
+
layers.fill.push({
|
|
116
|
+
id: `${sourceName}-${vector_layer.id}-fill`,
|
|
117
|
+
'source-layer': vector_layer.id,
|
|
118
|
+
source: sourceName,
|
|
119
|
+
type: 'fill',
|
|
120
|
+
filter: ['==', '$type', 'Polygon'],
|
|
121
|
+
paint: { 'fill-color': color, 'fill-opacity': 0.3, 'fill-antialias': true, 'fill-outline-color': color },
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
version: 8,
|
|
126
|
+
sources: {
|
|
127
|
+
[sourceName]: spec,
|
|
128
|
+
},
|
|
129
|
+
layers: [
|
|
130
|
+
...layers.background,
|
|
131
|
+
...layers.fill,
|
|
132
|
+
...layers.line,
|
|
133
|
+
...layers.circle,
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function getImageStyle(spec) {
|
|
138
|
+
const sourceName = 'rasterSource';
|
|
139
|
+
return {
|
|
140
|
+
version: 8,
|
|
141
|
+
sources: { [sourceName]: spec },
|
|
142
|
+
layers: [{
|
|
143
|
+
id: 'raster',
|
|
144
|
+
type: 'raster',
|
|
145
|
+
source: sourceName,
|
|
146
|
+
}],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import guessStyle from './style_guesser.js';
|
|
3
|
+
describe('guessStyle', () => {
|
|
4
|
+
const tiles = ['https://example.com/tiles/{z}/{x}/{y}'];
|
|
5
|
+
it('should build raster styles', () => {
|
|
6
|
+
const type = 'raster';
|
|
7
|
+
const format = 'avif';
|
|
8
|
+
expect(guessStyle({ tiles, format }))
|
|
9
|
+
.toStrictEqual({
|
|
10
|
+
version: 8,
|
|
11
|
+
sources: { rasterSource: { format, tilejson: '3.0.0', tiles, type } },
|
|
12
|
+
layers: [{ id: 'raster', source: 'rasterSource', type }],
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
it('should build vector styles', () => {
|
|
16
|
+
const type = 'vector';
|
|
17
|
+
const format = 'pbf';
|
|
18
|
+
const vector_layers = [{ id: 'geometry', fields: { label: 'String', height: 'Number' } }];
|
|
19
|
+
expect(guessStyle({ tiles, format, vector_layers }))
|
|
20
|
+
.toStrictEqual({
|
|
21
|
+
version: 8,
|
|
22
|
+
sources: { vectorSource: { format, tilejson: '3.0.0', tiles, type, vector_layers } },
|
|
23
|
+
layers: [
|
|
24
|
+
{
|
|
25
|
+
id: 'background',
|
|
26
|
+
type: 'background',
|
|
27
|
+
paint: { 'background-color': '#fff' },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'vectorSource-geometry-fill',
|
|
31
|
+
type: 'fill',
|
|
32
|
+
source: 'vectorSource',
|
|
33
|
+
'source-layer': 'geometry',
|
|
34
|
+
filter: ['==', '$type', 'Polygon'],
|
|
35
|
+
paint: { 'fill-antialias': true, 'fill-color': 'hsla(7,57%,56%,0.6)', 'fill-opacity': 0.3, 'fill-outline-color': 'hsla(7,57%,56%,0.6)' },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'vectorSource-geometry-line',
|
|
39
|
+
type: 'line',
|
|
40
|
+
source: 'vectorSource',
|
|
41
|
+
'source-layer': 'geometry',
|
|
42
|
+
filter: ['==', '$type', 'LineString'],
|
|
43
|
+
layout: { 'line-cap': 'round', 'line-join': 'round' },
|
|
44
|
+
paint: { 'line-color': 'hsla(7,57%,56%,0.6)' },
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'vectorSource-geometry-circle',
|
|
48
|
+
type: 'circle',
|
|
49
|
+
source: 'vectorSource',
|
|
50
|
+
'source-layer': 'geometry',
|
|
51
|
+
filter: ['==', '$type', 'Point'],
|
|
52
|
+
paint: { 'circle-color': 'hsla(7,57%,56%,0.6)', 'circle-radius': 2 },
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BackgroundLayerSpecification, FillLayerSpecification, FilterSpecification, LineLayerSpecification, StyleSpecification, SymbolLayerSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
2
2
|
import type Color from 'color';
|
|
3
|
+
import type StyleBuilder from './style_builder.ts';
|
|
3
4
|
export type TileFormat = 'avif' | 'bin' | 'geojson' | 'jpg' | 'json' | 'pbf' | 'png' | 'svg' | 'topojson' | 'webp';
|
|
4
5
|
export type MaplibreLayer = BackgroundLayerSpecification | FillLayerSpecification | LineLayerSpecification | SymbolLayerSpecification;
|
|
5
6
|
export type MaplibreLayerDefinition = BackgroundLayerSpecification | Omit<FillLayerSpecification, 'source'> | Omit<LineLayerSpecification, 'source'> | Omit<SymbolLayerSpecification, 'source'>;
|
|
@@ -11,9 +12,8 @@ export interface VectorLayer {
|
|
|
11
12
|
minzoom?: number;
|
|
12
13
|
maxzoom?: number;
|
|
13
14
|
}
|
|
14
|
-
export interface
|
|
15
|
+
export interface TileJSONSpecificationBasic {
|
|
15
16
|
tilejson?: '3.0.0';
|
|
16
|
-
type: 'raster';
|
|
17
17
|
attribution?: string;
|
|
18
18
|
tiles: string[];
|
|
19
19
|
scheme?: 'tms' | 'xyz';
|
|
@@ -27,14 +27,21 @@ export interface TileJSONSpecificationRaster {
|
|
|
27
27
|
maxzoom?: number;
|
|
28
28
|
name?: string;
|
|
29
29
|
template?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface TileJSONSpecificationRaster extends TileJSONSpecificationBasic {
|
|
32
|
+
type: 'raster';
|
|
30
33
|
format: 'avif' | 'jpg' | 'png' | 'webp';
|
|
31
34
|
}
|
|
32
|
-
export interface TileJSONSpecificationVector extends
|
|
33
|
-
vector_layers: VectorLayer[];
|
|
34
|
-
format: 'pbf';
|
|
35
|
+
export interface TileJSONSpecificationVector extends TileJSONSpecificationBasic {
|
|
35
36
|
type: 'vector';
|
|
37
|
+
format: 'pbf';
|
|
38
|
+
vector_layers: VectorLayer[];
|
|
36
39
|
}
|
|
37
40
|
export type TileJSONSpecification = TileJSONSpecificationRaster | TileJSONSpecificationVector;
|
|
41
|
+
export interface TileJSONOption extends TileJSONSpecificationBasic {
|
|
42
|
+
format: 'avif' | 'jpg' | 'pbf' | 'png' | 'webp';
|
|
43
|
+
vector_layers?: VectorLayer[];
|
|
44
|
+
}
|
|
38
45
|
export type MaplibreStyleRaster = Omit<StyleSpecification, 'sources'> & {
|
|
39
46
|
'sources': {
|
|
40
47
|
[_: string]: TileJSONSpecificationRaster;
|
|
@@ -47,14 +54,18 @@ export type MaplibreStyleVector = Omit<StyleSpecification, 'sources'> & {
|
|
|
47
54
|
};
|
|
48
55
|
export type MaplibreStyle = MaplibreStyleRaster | MaplibreStyleVector;
|
|
49
56
|
export type StyleRuleValue = boolean | number | object | string;
|
|
50
|
-
export type StyleRule = Record<string, StyleRuleValue>;
|
|
51
|
-
export type StyleRules = Record<string, StyleRule>;
|
|
52
|
-
export type StylemakerColorLookup = Record<string, Color>;
|
|
53
|
-
export type StylemakerStringLookup = Record<string, string>;
|
|
57
|
+
export type StyleRule = Record<string, StyleRuleValue | undefined>;
|
|
58
|
+
export type StyleRules = Record<string, StyleRule | undefined>;
|
|
54
59
|
export type LanguageSuffix = '_de' | '_en' | '';
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
export type StylemakerColorKeys<T extends StyleBuilder<T>> = keyof T['defaultColors'];
|
|
61
|
+
export type StylemakerFontKeys<T extends StyleBuilder<T>> = keyof T['defaultFonts'];
|
|
62
|
+
export type StylemakerColorStrings<T extends StyleBuilder<T>> = Record<StylemakerColorKeys<T>, string>;
|
|
63
|
+
export type StylemakerFontStrings<T extends StyleBuilder<T>> = Record<StylemakerFontKeys<T>, string>;
|
|
64
|
+
export type StylemakerColors<T extends StyleBuilder<T>> = Record<StylemakerColorKeys<T>, Color>;
|
|
65
|
+
export type StylemakerFonts<T extends StyleBuilder<T>> = Record<StylemakerFontKeys<T>, string>;
|
|
66
|
+
export interface StyleRulesOptions<T extends StyleBuilder<T>> {
|
|
67
|
+
colors: StylemakerColors<T>;
|
|
68
|
+
fonts: StylemakerFontStrings<T>;
|
|
58
69
|
languageSuffix: string;
|
|
59
70
|
}
|
|
60
71
|
export interface RecolorOptions {
|
|
@@ -67,4 +78,15 @@ export interface RecolorOptions {
|
|
|
67
78
|
tint?: number;
|
|
68
79
|
tintColor?: string;
|
|
69
80
|
}
|
|
81
|
+
export interface StylemakerOptions<T extends StyleBuilder<T>> {
|
|
82
|
+
baseUrl?: string;
|
|
83
|
+
glyphsUrl?: string;
|
|
84
|
+
spriteUrl?: string;
|
|
85
|
+
tilesUrls?: string[];
|
|
86
|
+
hideLabels?: boolean;
|
|
87
|
+
languageSuffix?: LanguageSuffix;
|
|
88
|
+
colors?: Partial<StylemakerColorStrings<T>>;
|
|
89
|
+
fonts?: Partial<StylemakerFontStrings<T>>;
|
|
90
|
+
recolor?: RecolorOptions;
|
|
91
|
+
}
|
|
70
92
|
export declare function isTileJSONSpecification(obj: unknown): obj is TileJSONSpecification;
|
package/dist/lib/types.js
CHANGED
|
@@ -44,19 +44,19 @@ export function isTileJSONSpecification(obj) {
|
|
|
44
44
|
if (typeof spec.template !== 'undefined' && typeof spec.template !== 'string') {
|
|
45
45
|
throw Error('spec.template must be a string if present');
|
|
46
46
|
}
|
|
47
|
+
if (!Array.isArray(spec.tiles) || spec.tiles.length === 0 || spec.tiles.some(url => typeof url !== 'string')) {
|
|
48
|
+
throw Error('spec.tiles must be an array of strings');
|
|
49
|
+
}
|
|
47
50
|
if (spec.type === 'raster') {
|
|
48
51
|
if (!['avif', 'jpg', 'png', 'webp'].includes(spec.format)) {
|
|
49
52
|
throw Error('spec.format must be "avif", "jpg", "png", or "webp"');
|
|
50
53
|
}
|
|
51
|
-
if (!Array.isArray(spec.tiles) || spec.tiles.some(url => typeof url !== 'string')) {
|
|
52
|
-
throw Error('spec.tiles must be an array of strings');
|
|
53
|
-
}
|
|
54
54
|
}
|
|
55
55
|
else if (spec.type === 'vector') {
|
|
56
56
|
if (spec.format !== 'pbf') {
|
|
57
57
|
throw Error('spec.format must be "pbf"');
|
|
58
58
|
}
|
|
59
|
-
if (!Array.isArray(spec.vector_layers) || spec.vector_layers.some(layer => !validateVectorLayer(layer))) {
|
|
59
|
+
if (!Array.isArray(spec.vector_layers) || spec.vector_layers.length === 0 || spec.vector_layers.some(layer => !validateVectorLayer(layer))) {
|
|
60
60
|
throw Error('spec.vector_layers must be an array of VectorLayer');
|
|
61
61
|
}
|
|
62
62
|
}
|
package/dist/style/colorful.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import StyleBuilder from '../lib/style_builder.js';
|
|
2
2
|
import type { StyleRules, StyleRulesOptions } from '../lib/types.js';
|
|
3
|
-
export default class Colorful extends StyleBuilder {
|
|
3
|
+
export default class Colorful extends StyleBuilder<Colorful> {
|
|
4
4
|
readonly name: string;
|
|
5
|
-
|
|
5
|
+
defaultFonts: {
|
|
6
6
|
regular: string;
|
|
7
7
|
bold: string;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
defaultColors: {
|
|
10
10
|
land: string;
|
|
11
11
|
water: string;
|
|
12
12
|
glacier: string;
|
|
@@ -49,5 +49,5 @@ export default class Colorful extends StyleBuilder {
|
|
|
49
49
|
hospital: string;
|
|
50
50
|
poi: string;
|
|
51
51
|
};
|
|
52
|
-
protected getStyleRules(options: StyleRulesOptions): StyleRules;
|
|
52
|
+
protected getStyleRules(options: StyleRulesOptions<Colorful>): StyleRules;
|
|
53
53
|
}
|
package/dist/style/colorful.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
2
|
import StyleBuilder from '../lib/style_builder.js';
|
|
3
3
|
export default class Colorful extends StyleBuilder {
|
|
4
|
-
name = '
|
|
5
|
-
|
|
4
|
+
name = 'Colorful';
|
|
5
|
+
defaultFonts = {
|
|
6
6
|
regular: 'noto_sans_regular',
|
|
7
7
|
bold: 'noto_sans_bold',
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
defaultColors = {
|
|
10
10
|
land: '#F9F4EE',
|
|
11
11
|
water: '#BEDDF3',
|
|
12
12
|
glacier: '#FFFFFF',
|
package/dist/style/graybeard.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Colorful from './colorful.js';
|
|
2
2
|
export default class Graybeard extends Colorful {
|
|
3
|
-
name = '
|
|
3
|
+
name = 'Graybeard';
|
|
4
4
|
constructor() {
|
|
5
5
|
super();
|
|
6
|
-
this.
|
|
6
|
+
this.transformDefaultColors(color => color.desaturate(1));
|
|
7
7
|
}
|
|
8
8
|
}
|
package/dist/style/neutrino.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import StyleBuilder from '../lib/style_builder.js';
|
|
2
2
|
import type { StyleRules, StyleRulesOptions } from '../lib/types.js';
|
|
3
|
-
export default class Neutrino extends StyleBuilder {
|
|
3
|
+
export default class Neutrino extends StyleBuilder<Neutrino> {
|
|
4
4
|
readonly name: string;
|
|
5
|
-
|
|
5
|
+
defaultFonts: {
|
|
6
6
|
regular: string;
|
|
7
7
|
bold: string;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
defaultColors: {
|
|
10
10
|
land: string;
|
|
11
11
|
water: string;
|
|
12
12
|
grass: string;
|
|
@@ -20,5 +20,5 @@ export default class Neutrino extends StyleBuilder {
|
|
|
20
20
|
rail: string;
|
|
21
21
|
label: string;
|
|
22
22
|
};
|
|
23
|
-
protected getStyleRules(options: StyleRulesOptions): StyleRules;
|
|
23
|
+
protected getStyleRules(options: StyleRulesOptions<Neutrino>): StyleRules;
|
|
24
24
|
}
|
package/dist/style/neutrino.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
2
|
import StyleBuilder from '../lib/style_builder.js';
|
|
3
3
|
export default class Neutrino extends StyleBuilder {
|
|
4
|
-
name = '
|
|
5
|
-
|
|
4
|
+
name = 'Neutrino';
|
|
5
|
+
defaultFonts = {
|
|
6
6
|
regular: 'noto_sans_regular',
|
|
7
7
|
bold: 'noto_sans_bold',
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
defaultColors = {
|
|
10
10
|
land: '#f6f0f6',
|
|
11
11
|
water: '#cbd2df',
|
|
12
12
|
grass: '#e7e9e5',
|