@versatiles/style 5.8.2 → 5.8.4

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.
Files changed (54) hide show
  1. package/README.md +14 -14
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +570 -333
  4. package/dist/index.js.map +1 -1
  5. package/package.json +13 -8
  6. package/src/color/abstract.ts +1 -1
  7. package/src/color/hsl.test.ts +10 -16
  8. package/src/color/hsl.ts +11 -15
  9. package/src/color/hsv.test.ts +4 -10
  10. package/src/color/hsv.ts +38 -22
  11. package/src/color/index.test.ts +2 -4
  12. package/src/color/index.ts +1 -1
  13. package/src/color/random.test.ts +1 -1
  14. package/src/color/random.ts +127 -25
  15. package/src/color/rgb.test.ts +55 -36
  16. package/src/color/rgb.ts +35 -48
  17. package/src/color/utils.test.ts +4 -6
  18. package/src/color/utils.ts +1 -3
  19. package/src/guess_style/guess_style.test.ts +49 -43
  20. package/src/guess_style/guess_style.ts +64 -21
  21. package/src/guess_style/index.ts +0 -1
  22. package/src/index.test.ts +34 -7
  23. package/src/index.ts +29 -19
  24. package/src/lib/utils.test.ts +2 -2
  25. package/src/lib/utils.ts +2 -1
  26. package/src/shortbread/index.ts +0 -1
  27. package/src/shortbread/layers.test.ts +19 -3
  28. package/src/shortbread/layers.ts +204 -194
  29. package/src/shortbread/properties.test.ts +3 -4
  30. package/src/shortbread/properties.ts +18 -4
  31. package/src/shortbread/template.test.ts +7 -2
  32. package/src/shortbread/template.ts +7 -14
  33. package/src/style_builder/decorator.test.ts +4 -4
  34. package/src/style_builder/decorator.ts +29 -21
  35. package/src/style_builder/recolor.test.ts +6 -31
  36. package/src/style_builder/recolor.ts +20 -20
  37. package/src/style_builder/style_builder.test.ts +50 -13
  38. package/src/style_builder/style_builder.ts +29 -31
  39. package/src/style_builder/types.ts +85 -2
  40. package/src/styles/LICENSE.md +15 -15
  41. package/src/styles/colorful.test.ts +91 -0
  42. package/src/styles/colorful.ts +229 -122
  43. package/src/styles/eclipse.ts +1 -1
  44. package/src/styles/empty.ts +1 -1
  45. package/src/styles/graybeard.ts +2 -2
  46. package/src/styles/index.ts +0 -3
  47. package/src/styles/neutrino.ts +14 -16
  48. package/src/styles/shadow.ts +2 -2
  49. package/src/types/index.ts +0 -1
  50. package/src/types/maplibre.ts +17 -3
  51. package/src/types/tilejson.test.ts +8 -5
  52. package/src/types/tilejson.ts +13 -13
  53. package/src/types/vector_layer.test.ts +4 -1
  54. package/src/types/vector_layer.ts +7 -7
@@ -1,7 +1,22 @@
1
- import type { TileJSONSpecification, TileJSONSpecificationRaster, TileJSONSpecificationVector, VectorLayer } from '../types/index.js';
1
+ import type {
2
+ TileJSONSpecification,
3
+ TileJSONSpecificationRaster,
4
+ TileJSONSpecificationVector,
5
+ VectorLayer,
6
+ } from '../types/index.js';
2
7
  import { isTileJSONSpecification } from '../types/index.js';
3
8
  import { deepClone, resolveUrl } from '../lib/utils.js';
4
- import type { BackgroundLayerSpecification, CircleLayerSpecification, FillLayerSpecification, LineLayerSpecification, RasterSourceSpecification, SourceSpecification, SpriteSpecification, StyleSpecification, VectorSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
9
+ import type {
10
+ BackgroundLayerSpecification,
11
+ CircleLayerSpecification,
12
+ FillLayerSpecification,
13
+ LineLayerSpecification,
14
+ RasterSourceSpecification,
15
+ SourceSpecification,
16
+ SpriteSpecification,
17
+ StyleSpecification,
18
+ VectorSourceSpecification,
19
+ } from '@maplibre/maplibre-gl-style-spec';
5
20
  import { colorful } from '../styles/index.js';
6
21
  import { isRasterTileJSONSpecification } from '../types/tilejson.js';
7
22
  import randomColor from '../color/random.js';
@@ -40,7 +55,7 @@ export function guessStyle(tileJSON: TileJSONSpecification, options?: GuessStyle
40
55
 
41
56
  if (options && options.baseUrl) {
42
57
  const { baseUrl } = options;
43
- tileJSON.tiles = tileJSON.tiles.map(url => resolveUrl(baseUrl, url));
58
+ tileJSON.tiles = tileJSON.tiles.map((url) => resolveUrl(baseUrl, url));
44
59
  }
45
60
 
46
61
  if (!isTileJSONSpecification(tileJSON)) throw Error('Invalid TileJSON specification');
@@ -68,13 +83,42 @@ function isShortbread(spec: TileJSONSpecificationVector): boolean {
68
83
  if (!('vector_layers' in spec)) return false;
69
84
  if (!Array.isArray(spec.vector_layers)) return false;
70
85
 
71
-
72
- const layerIds = new Set(spec.vector_layers.map(l => String(l.id)));
73
- 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'];
74
- return shortbreadIds.every(id => layerIds.has(id));
86
+ const layerIds = new Set(spec.vector_layers.map((l) => String(l.id)));
87
+ const shortbreadIds = [
88
+ 'place_labels',
89
+ 'boundaries',
90
+ 'boundary_labels',
91
+ 'addresses',
92
+ 'water_lines',
93
+ 'water_lines_labels',
94
+ 'dam_lines',
95
+ 'dam_polygons',
96
+ 'pier_lines',
97
+ 'pier_polygons',
98
+ 'bridges',
99
+ 'street_polygons',
100
+ 'streets_polygons_labels',
101
+ 'ferries',
102
+ 'streets',
103
+ 'street_labels',
104
+ 'street_labels_points',
105
+ 'aerialways',
106
+ 'public_transport',
107
+ 'buildings',
108
+ 'water_polygons',
109
+ 'ocean',
110
+ 'water_polygons_labels',
111
+ 'land',
112
+ 'sites',
113
+ 'pois',
114
+ ];
115
+ return shortbreadIds.every((id) => layerIds.has(id));
75
116
  }
76
117
 
77
- function getShortbreadStyle(spec: TileJSONSpecificationVector, builderOption: { baseUrl?: string; glyphs?: string; sprite?: SpriteSpecification }): StyleSpecification {
118
+ function getShortbreadStyle(
119
+ spec: TileJSONSpecificationVector,
120
+ builderOption: { baseUrl?: string; glyphs?: string; sprite?: SpriteSpecification }
121
+ ): StyleSpecification {
78
122
  return colorful({
79
123
  tiles: spec.tiles,
80
124
  baseUrl: builderOption.baseUrl,
@@ -110,10 +154,12 @@ function getInspectorStyle(spec: TileJSONSpecificationVector): StyleSpecificatio
110
154
  fill: FillLayerSpecification[];
111
155
  } = { background: [], circle: [], line: [], fill: [] };
112
156
 
113
- layers.background.push({ 'id': 'background', 'type': 'background', 'paint': { 'background-color': '#fff' } });
157
+ layers.background.push({ id: 'background', type: 'background', paint: { 'background-color': '#fff' } });
114
158
 
115
159
  spec.vector_layers.forEach((vector_layer: VectorLayer) => {
116
- let luminosity = 'bright', saturation, hue;
160
+ let luminosity = 'bright',
161
+ saturation,
162
+ hue;
117
163
 
118
164
  if (/water|ocean|lake|sea|river/.test(vector_layer.id)) hue = 'blue';
119
165
  if (/state|country|place/.test(vector_layer.id)) hue = 'pink';
@@ -170,12 +216,7 @@ function getInspectorStyle(spec: TileJSONSpecificationVector): StyleSpecificatio
170
216
  sources: {
171
217
  [sourceName]: sourceFromSpec(spec, 'vector'),
172
218
  },
173
- layers: [
174
- ...layers.background,
175
- ...layers.fill,
176
- ...layers.line,
177
- ...layers.circle,
178
- ],
219
+ layers: [...layers.background, ...layers.fill, ...layers.line, ...layers.circle],
179
220
  };
180
221
  }
181
222
 
@@ -186,11 +227,13 @@ function getRasterStyle(spec: TileJSONSpecificationRaster): StyleSpecification {
186
227
  sources: {
187
228
  [sourceName]: sourceFromSpec(spec, 'raster'),
188
229
  },
189
- layers: [{
190
- id: 'raster',
191
- type: 'raster',
192
- source: sourceName,
193
- }],
230
+ layers: [
231
+ {
232
+ id: 'raster',
233
+ type: 'raster',
234
+ source: sourceName,
235
+ },
236
+ ],
194
237
  };
195
238
  }
196
239
 
@@ -1,3 +1,2 @@
1
-
2
1
  export type { GuessStyleOptions } from './guess_style.js';
3
2
  export { guessStyle } from './guess_style.js';
package/src/index.test.ts CHANGED
@@ -18,7 +18,7 @@ describe('styles', () => {
18
18
 
19
19
  const style = builder({ baseUrl: 'https://example.org' });
20
20
 
21
- const minSize = (name === 'empty') ? 4000 : 50000;
21
+ const minSize = name === 'empty' ? 4000 : 50000;
22
22
  expect(JSON.stringify(style).length).toBeGreaterThan(minSize);
23
23
 
24
24
  expect(style.name).toBe('versatiles-' + name);
@@ -39,7 +39,7 @@ describe('Colorful', () => {
39
39
  colors: { commercial: '#f00' },
40
40
  });
41
41
  expect(style.glyphs).toBe('https://dev.null/assets/glyphs/{fontstack}/{range}.pbf');
42
- const paint = style.layers.find(l => l.id === 'land-commercial')?.paint;
42
+ const paint = style.layers.find((l) => l.id === 'land-commercial')?.paint;
43
43
 
44
44
  expect(paint).toBeDefined();
45
45
  if (paint == null) throw Error();
@@ -69,12 +69,39 @@ describe('guessStyle', () => {
69
69
  expect(style).toStrictEqual({
70
70
  layers: [
71
71
  { id: 'background', paint: { 'background-color': '#fff' }, type: 'background' },
72
- { id: 'vectorSource-hallo-fill', filter: ['==', '$type', 'Polygon'], paint: { 'fill-antialias': true, 'fill-color': 'hsla(14,50%,52%,0.6)', 'fill-opacity': 0.3, 'fill-outline-color': 'hsla(14,50%,52%,0.6)' }, source: 'vectorSource', 'source-layer': 'hallo', type: 'fill' },
73
- { id: 'vectorSource-hallo-line', filter: ['==', '$type', 'LineString'], layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': 'hsla(14,50%,52%,0.6)' }, source: 'vectorSource', 'source-layer': 'hallo', type: 'line' },
74
- { id: 'vectorSource-hallo-circle', filter: ['==', '$type', 'Point'], paint: { 'circle-color': 'hsla(14,50%,52%,0.6)', 'circle-radius': 2 }, source: 'vectorSource', 'source-layer': 'hallo', type: 'circle' },
72
+ {
73
+ id: 'vectorSource-hallo-fill',
74
+ filter: ['==', '$type', 'Polygon'],
75
+ paint: {
76
+ 'fill-antialias': true,
77
+ 'fill-color': 'hsla(14,50%,52%,0.6)',
78
+ 'fill-opacity': 0.3,
79
+ 'fill-outline-color': 'hsla(14,50%,52%,0.6)',
80
+ },
81
+ source: 'vectorSource',
82
+ 'source-layer': 'hallo',
83
+ type: 'fill',
84
+ },
85
+ {
86
+ id: 'vectorSource-hallo-line',
87
+ filter: ['==', '$type', 'LineString'],
88
+ layout: { 'line-cap': 'round', 'line-join': 'round' },
89
+ paint: { 'line-color': 'hsla(14,50%,52%,0.6)' },
90
+ source: 'vectorSource',
91
+ 'source-layer': 'hallo',
92
+ type: 'line',
93
+ },
94
+ {
95
+ id: 'vectorSource-hallo-circle',
96
+ filter: ['==', '$type', 'Point'],
97
+ paint: { 'circle-color': 'hsla(14,50%,52%,0.6)', 'circle-radius': 2 },
98
+ source: 'vectorSource',
99
+ 'source-layer': 'hallo',
100
+ type: 'circle',
101
+ },
75
102
  ],
76
103
  sources: { vectorSource: { tiles, type: 'vector' } },
77
- 'version': 8,
104
+ version: 8,
78
105
  });
79
106
  });
80
107
  });
@@ -101,4 +128,4 @@ describe('exports', () => {
101
128
  expect(typeof lib.Color.HSV.randomColor).toBe('function');
102
129
  expect(typeof lib.Color.RGB).toBe('function');
103
130
  });
104
- })
131
+ });
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * This library provides everything you need to build a map style.
3
- *
3
+ *
4
4
  * You can use it in the browser:
5
5
  * ```html
6
6
  * <html>
@@ -16,7 +16,7 @@
16
16
  * </body>
17
17
  * </html>
18
18
  * ```
19
- *
19
+ *
20
20
  * or in Node.js:
21
21
  * ```shell
22
22
  * npm i @versatiles/style
@@ -26,22 +26,22 @@
26
26
  * // OR: const { colorful } = require('@versatiles/style');
27
27
  * const style = colorful();
28
28
  * ```
29
- *
29
+ *
30
30
  * You probably want to use one of the following functions:
31
- *
31
+ *
32
32
  * ---
33
- *
33
+ *
34
34
  * ## Generate a style for OpenStreetMap data:
35
- *
35
+ *
36
36
  * To generate a style from scratch you can use on of the prepared style functions:
37
37
  * - {@link colorful}
38
38
  * - {@link eclipse}
39
39
  * - {@link graybeard}
40
40
  * - {@link neutrino}
41
41
  * - {@link shadow}
42
- *
42
+ *
43
43
  * Each function accepts optional {@link StyleBuilderOptions} as argument to customize the style.
44
- *
44
+ *
45
45
  * Example:
46
46
  * ```
47
47
  * import { colorful } from 'versatiles-style';
@@ -53,11 +53,11 @@
53
53
  * }
54
54
  * });
55
55
  * ```
56
- *
56
+ *
57
57
  * ---
58
- *
58
+ *
59
59
  * ## Guess a style based on a TileJSON:
60
- *
60
+ *
61
61
  * To guess a style from a TileJSON you can use {@link guessStyle}.
62
62
  * This function needs a {@link TileJSONSpecification} and an optional {@link GuessStyleOptions} object.
63
63
  * Example:
@@ -65,18 +65,18 @@
65
65
  * import { guessStyle } from 'versatiles-style';
66
66
  * const style = guessStyle(tilejson);
67
67
  * ```
68
- *
68
+ *
69
69
  * ---
70
- *
70
+ *
71
71
  * ## Please help us to improve this library:
72
- *
72
+ *
73
73
  * This library is used in quite some projects of the VersaTiles ecosystem but it is still in an early stage.
74
74
  * We are always looking for feedback, contributions, ideas, bug reports and help with the documentation.
75
- *
75
+ *
76
76
  * If you have any suggestions, please [open an issue](https://github.com/versatiles-org/versatiles-style/issues) or a pull request on [GitHub](https://github.com/versatiles-org/versatiles-style).
77
- *
77
+ *
78
78
  * If you want to know more about the VersaTiles project, please visit [versatiles.org](https://versatiles.org).
79
- *
79
+ *
80
80
  * @module
81
81
  */
82
82
 
@@ -92,9 +92,19 @@ export const styles = {
92
92
 
93
93
  export type { GuessStyleOptions } from './guess_style/index.js';
94
94
  export type { RGB, HSL, HSV, RandomColorOptions } from './color/index.js';
95
- export type { TileJSONSpecification, TileJSONSpecificationRaster, TileJSONSpecificationVector } from './types/tilejson.js';
95
+ export type {
96
+ TileJSONSpecification,
97
+ TileJSONSpecificationRaster,
98
+ TileJSONSpecificationVector,
99
+ } from './types/tilejson.js';
96
100
  export type { VectorLayer } from './types/index.js';
97
- export type { StyleBuilderOptions, Language, StyleBuilderColors, StyleBuilderColorKey, StyleBuilderFonts } from './style_builder/types.js';
101
+ export type {
102
+ StyleBuilderOptions,
103
+ Language,
104
+ StyleBuilderColors,
105
+ StyleBuilderColorKey,
106
+ StyleBuilderFonts,
107
+ } from './style_builder/types.js';
98
108
  export type { RecolorOptions } from './style_builder/recolor.js';
99
109
 
100
110
  export { guessStyle } from './guess_style/index.js';
@@ -98,14 +98,14 @@ describe('deepMerge', () => {
98
98
  });
99
99
 
100
100
  it('merges nested objects correctly', () => {
101
- const target = { a: { d: 4, e: 3 }, b: 2 } as { a: { d?: number, e: number }, b: number };
101
+ const target = { a: { d: 4, e: 3 }, b: 2 } as { a: { d?: number; e: number }; b: number };
102
102
  const source = { a: { e: 5 }, b: 3 };
103
103
  const result = deepMerge(target, source);
104
104
  expect(result).toEqual({ a: { d: 4, e: 5 }, b: 3 });
105
105
  });
106
106
 
107
107
  it('overrides primitives with objects', () => {
108
- const target = { a: 1, b: 2 } as { a: object | number, b: object | number };
108
+ const target = { a: 1, b: 2 } as { a: object | number; b: object | number };
109
109
  const source = { a: { d: 4 }, b: { e: 5 } };
110
110
  const result = deepMerge(target, source);
111
111
  expect(result).toEqual({ a: { d: 4 }, b: { e: 5 } });
package/src/lib/utils.ts CHANGED
@@ -10,7 +10,8 @@ export function deepClone<T>(obj: T): T {
10
10
  case 'string':
11
11
  case 'undefined':
12
12
  return obj;
13
- default: throw new Error(`Not implemented yet: "${type}" case`);
13
+ default:
14
+ throw new Error(`Not implemented yet: "${type}" case`);
14
15
  }
15
16
  }
16
17
 
@@ -1,3 +1,2 @@
1
-
2
1
  export { getShortbreadTemplate } from './template.js';
3
2
  export { getShortbreadLayers } from './layers.js';
@@ -34,7 +34,8 @@ describe('layers', () => {
34
34
  expect(labelLayer).toBeDefined();
35
35
 
36
36
  expect(labelLayer.layout?.['text-field']).toStrictEqual([
37
- "coalesce",
37
+ 'case',
38
+ ['to-boolean', ['get', 'name_en']],
38
39
  ['get', 'name_en'],
39
40
  ['get', 'name'],
40
41
  ]);
@@ -48,7 +49,8 @@ describe('layers', () => {
48
49
  expect(labelLayer).toBeDefined();
49
50
 
50
51
  expect(labelLayer.layout?.['text-field']).toStrictEqual([
51
- "coalesce",
52
+ 'case',
53
+ ['to-boolean', ['get', 'name_fr']],
52
54
  ['get', 'name_fr'],
53
55
  ['get', 'name'],
54
56
  ]);
@@ -60,6 +62,20 @@ describe('layers', () => {
60
62
  const landLayer = layers.find((layer) => layer.id === 'land-agriculture') as FillLayerSpecification;
61
63
 
62
64
  expect(landLayer).toBeDefined();
63
- expect(landLayer.filter).toEqual(['all', ['in', 'kind', 'brownfield', 'farmland', 'farmyard', 'greenfield', 'greenhouse_horticulture', 'orchard', 'plant_nursery', 'vineyard']]);
65
+ expect(landLayer.filter).toEqual([
66
+ 'all',
67
+ [
68
+ 'in',
69
+ 'kind',
70
+ 'brownfield',
71
+ 'farmland',
72
+ 'farmyard',
73
+ 'greenfield',
74
+ 'greenhouse_horticulture',
75
+ 'orchard',
76
+ 'plant_nursery',
77
+ 'vineyard',
78
+ ],
79
+ ]);
64
80
  });
65
81
  });