@versatiles/style 3.4.0
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/LICENSE.md +24 -0
- package/README.MD +94 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +38 -0
- package/dist/lib/decorator.d.ts +3 -0
- package/dist/lib/decorator.js +123 -0
- package/dist/lib/decorator.test.d.ts +1 -0
- package/dist/lib/decorator.test.js +56 -0
- package/dist/lib/recolor.d.ts +13 -0
- package/dist/lib/recolor.js +92 -0
- package/dist/lib/recolor.test.d.ts +1 -0
- package/dist/lib/recolor.test.js +179 -0
- package/dist/lib/shortbread/layers.d.ts +7 -0
- package/dist/lib/shortbread/layers.js +508 -0
- package/dist/lib/shortbread/layers.test.d.ts +1 -0
- package/dist/lib/shortbread/layers.test.js +27 -0
- package/dist/lib/shortbread/properties.d.ts +7 -0
- package/dist/lib/shortbread/properties.js +124 -0
- package/dist/lib/shortbread/properties.test.d.ts +1 -0
- package/dist/lib/shortbread/properties.test.js +36 -0
- package/dist/lib/shortbread/template.d.ts +2 -0
- package/dist/lib/shortbread/template.js +339 -0
- package/dist/lib/shortbread/template.test.d.ts +1 -0
- package/dist/lib/shortbread/template.test.js +57 -0
- package/dist/lib/style_builder.d.ts +32 -0
- package/dist/lib/style_builder.js +84 -0
- package/dist/lib/style_builder.test.d.ts +1 -0
- package/dist/lib/style_builder.test.js +77 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +106 -0
- package/dist/lib/utils.test.d.ts +1 -0
- package/dist/lib/utils.test.js +97 -0
- package/dist/styles/colorful.d.ts +53 -0
- package/dist/styles/colorful.js +871 -0
- package/dist/styles/graybeard.d.ts +5 -0
- package/dist/styles/graybeard.js +9 -0
- package/dist/styles/neutrino.d.ts +24 -0
- package/dist/styles/neutrino.js +356 -0
- package/package.json +60 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Import necessary modules and files
|
|
2
|
+
import Color from 'color';
|
|
3
|
+
import getShortbreadTemplate from './shortbread/template.js';
|
|
4
|
+
import getShortbreadLayers from './shortbread/layers.js';
|
|
5
|
+
import { decorate } from './decorator.js';
|
|
6
|
+
import { getDefaultRecolorFlags, recolor } from './recolor.js';
|
|
7
|
+
// Stylemaker class definition
|
|
8
|
+
export default class StyleBuilder {
|
|
9
|
+
baseUrl;
|
|
10
|
+
glyphsUrl = '/assets/fonts/{fontstack}/{range}.pbf';
|
|
11
|
+
spriteUrl = '/assets/sprites/sprites';
|
|
12
|
+
tilesUrls = ['/tiles/osm/{z}/{x}/{y}'];
|
|
13
|
+
hideLabels = false;
|
|
14
|
+
languageSuffix = '';
|
|
15
|
+
recolor = getDefaultRecolorFlags();
|
|
16
|
+
#sourceName = 'versatiles-shortbread';
|
|
17
|
+
// Constructor
|
|
18
|
+
constructor() {
|
|
19
|
+
try {
|
|
20
|
+
// @ts-expect-error: I'm not sure if I'm in a browser
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
22
|
+
this.baseUrl = document.location.href;
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
this.baseUrl = 'https://tiles.versatiles.org'; // set me in the browser
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
build() {
|
|
29
|
+
// get empty shortbread style
|
|
30
|
+
const style = getShortbreadTemplate();
|
|
31
|
+
const colors = Object.fromEntries(Object.entries(this.colors)
|
|
32
|
+
.map(([name, colorString]) => [name, Color(colorString)]));
|
|
33
|
+
// transform colors
|
|
34
|
+
recolor(colors, this.recolor);
|
|
35
|
+
// get layer style rules from child class
|
|
36
|
+
const layerStyleRules = this.getStyleRules({
|
|
37
|
+
colors,
|
|
38
|
+
fonts: this.fonts,
|
|
39
|
+
languageSuffix: this.languageSuffix,
|
|
40
|
+
});
|
|
41
|
+
// get shortbread layers
|
|
42
|
+
let layers = getShortbreadLayers({ languageSuffix: this.languageSuffix });
|
|
43
|
+
// apply layer rules
|
|
44
|
+
layers = decorate(layers, layerStyleRules);
|
|
45
|
+
// hide labels, if wanted
|
|
46
|
+
if (this.hideLabels)
|
|
47
|
+
layers = layers.filter(l => l.type !== 'symbol');
|
|
48
|
+
// set source, if needed
|
|
49
|
+
layers.forEach(layer => {
|
|
50
|
+
switch (layer.type) {
|
|
51
|
+
case 'background':
|
|
52
|
+
delete layer.source;
|
|
53
|
+
return;
|
|
54
|
+
case 'fill':
|
|
55
|
+
case 'line':
|
|
56
|
+
case 'symbol':
|
|
57
|
+
layer.source = this.#sourceName;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
throw Error('unknown layer type');
|
|
61
|
+
});
|
|
62
|
+
style.layers = layers;
|
|
63
|
+
style.name = 'versatiles-' + this.name;
|
|
64
|
+
style.glyphs = resolveUrl(this.baseUrl, this.glyphsUrl);
|
|
65
|
+
style.sprite = resolveUrl(this.baseUrl, this.spriteUrl);
|
|
66
|
+
const source = style.sources[this.#sourceName];
|
|
67
|
+
if ('tiles' in source)
|
|
68
|
+
source.tiles = this.tilesUrls.map(url => resolveUrl(this.baseUrl, url));
|
|
69
|
+
return style;
|
|
70
|
+
function resolveUrl(baseUrl, url) {
|
|
71
|
+
if (!Boolean(baseUrl))
|
|
72
|
+
return url;
|
|
73
|
+
url = new URL(url, baseUrl).href;
|
|
74
|
+
url = url.replace(/%7B/gi, '{');
|
|
75
|
+
url = url.replace(/%7D/gi, '}');
|
|
76
|
+
return url;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
resetColors(callback) {
|
|
80
|
+
const colors = Object.fromEntries(Object.entries(this.colors)
|
|
81
|
+
.map(([name, color]) => [name, callback(Color(color)).hexa()]));
|
|
82
|
+
this.colors = colors;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import Color from 'color';
|
|
3
|
+
import StyleBuilder from './style_builder.js';
|
|
4
|
+
// Mock class for abstract class StyleBuilder
|
|
5
|
+
class MockStyleBuilder extends StyleBuilder {
|
|
6
|
+
name = 'mock';
|
|
7
|
+
fonts = { regular: 'Arial' };
|
|
8
|
+
colors = { primary: '#FF8800' };
|
|
9
|
+
negateColors() {
|
|
10
|
+
this.resetColors((color) => color.negate());
|
|
11
|
+
}
|
|
12
|
+
getStyleRules(opt) {
|
|
13
|
+
for (const color of Object.values(opt.colors))
|
|
14
|
+
if (!(color instanceof Color))
|
|
15
|
+
throw Error();
|
|
16
|
+
for (const font of Object.values(opt.fonts))
|
|
17
|
+
if (typeof font !== 'string')
|
|
18
|
+
throw Error();
|
|
19
|
+
return {
|
|
20
|
+
'water-area': {
|
|
21
|
+
textColor: opt.colors.primary,
|
|
22
|
+
textSize: 12,
|
|
23
|
+
textFont: [opt.fonts.Arial],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
describe('StyleBuilder', () => {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
30
|
+
let builder;
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
builder = new MockStyleBuilder();
|
|
33
|
+
});
|
|
34
|
+
it('should create an instance of StyleBuilder', () => {
|
|
35
|
+
expect(builder).toBeInstanceOf(StyleBuilder);
|
|
36
|
+
});
|
|
37
|
+
it('should build a MaplibreStyle object', () => {
|
|
38
|
+
const style = builder.build();
|
|
39
|
+
expect(style).toBeDefined();
|
|
40
|
+
expect(style).toHaveProperty('name');
|
|
41
|
+
expect(style).toHaveProperty('layers');
|
|
42
|
+
expect(style).toHaveProperty('glyphs');
|
|
43
|
+
expect(style).toHaveProperty('sprite');
|
|
44
|
+
});
|
|
45
|
+
it('should reset colors correctly', () => {
|
|
46
|
+
const initialColor = builder.colors.primary;
|
|
47
|
+
builder.negateColors();
|
|
48
|
+
expect(builder.colors.primary).not.toBe(initialColor);
|
|
49
|
+
expect(builder.colors.primary).toBe(Color(initialColor).negate().hexa());
|
|
50
|
+
});
|
|
51
|
+
describe('build method', () => {
|
|
52
|
+
it('should create a style object', () => {
|
|
53
|
+
const style = builder.build();
|
|
54
|
+
expect(style).toBeDefined();
|
|
55
|
+
expect(style).toHaveProperty('layers');
|
|
56
|
+
expect(style).toHaveProperty('name');
|
|
57
|
+
expect(style).toHaveProperty('glyphs');
|
|
58
|
+
expect(style).toHaveProperty('sprite');
|
|
59
|
+
});
|
|
60
|
+
it('should convert color strings to Color instances', () => {
|
|
61
|
+
builder.build();
|
|
62
|
+
const colors = Object.values(builder.colors);
|
|
63
|
+
expect(colors.every((color) => typeof color === 'string')).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it('should resolve urls correctly', () => {
|
|
66
|
+
builder.baseUrl = 'https://my.base.url/';
|
|
67
|
+
const style = builder.build();
|
|
68
|
+
expect(style.glyphs).toBe('https://my.base.url/assets/fonts/{fontstack}/{range}.pbf');
|
|
69
|
+
expect(style.sprite).toBe('https://my.base.url/assets/sprites/sprites');
|
|
70
|
+
const source = style.sources['versatiles-shortbread'];
|
|
71
|
+
expect(source).toHaveProperty('tiles');
|
|
72
|
+
if (!source.tiles)
|
|
73
|
+
return;
|
|
74
|
+
expect(source.tiles[0]).toBe('https://my.base.url/tiles/osm/{z}/{x}/{y}');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import Color from 'color';
|
|
2
|
+
// Utility function to deep clone an object
|
|
3
|
+
export function deepClone(obj) {
|
|
4
|
+
const type = typeof obj;
|
|
5
|
+
if (type !== 'object') {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case 'boolean':
|
|
8
|
+
case 'number':
|
|
9
|
+
case 'string':
|
|
10
|
+
case 'undefined':
|
|
11
|
+
return obj;
|
|
12
|
+
default: throw new Error(`Not implemented yet: "${type}" case`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (isSimpleObject(obj)) {
|
|
16
|
+
// @ts-expect-error: Too complicated to handle
|
|
17
|
+
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, deepClone(value)]));
|
|
18
|
+
}
|
|
19
|
+
if (obj instanceof Array) {
|
|
20
|
+
// @ts-expect-error: Too complicated to handle
|
|
21
|
+
return obj.map((e) => deepClone(e));
|
|
22
|
+
}
|
|
23
|
+
if (obj instanceof Color) {
|
|
24
|
+
// @ts-expect-error: Too complicated to handle
|
|
25
|
+
return Color(obj);
|
|
26
|
+
}
|
|
27
|
+
console.log('obj', obj);
|
|
28
|
+
console.log('obj.prototype', Object.getPrototypeOf(obj));
|
|
29
|
+
throw Error();
|
|
30
|
+
}
|
|
31
|
+
export function isSimpleObject(item) {
|
|
32
|
+
if (item === null)
|
|
33
|
+
return false;
|
|
34
|
+
if (typeof item !== 'object')
|
|
35
|
+
return false;
|
|
36
|
+
if (Array.isArray(item))
|
|
37
|
+
return false;
|
|
38
|
+
const prototypeKeyCount = Object.keys(Object.getPrototypeOf(item)).length;
|
|
39
|
+
if (prototypeKeyCount !== 0)
|
|
40
|
+
return false;
|
|
41
|
+
if (item.constructor.name !== 'Object')
|
|
42
|
+
return false;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
export function isBasicType(item) {
|
|
46
|
+
switch (typeof item) {
|
|
47
|
+
case 'boolean':
|
|
48
|
+
case 'number':
|
|
49
|
+
case 'string':
|
|
50
|
+
case 'undefined':
|
|
51
|
+
return true;
|
|
52
|
+
case 'object':
|
|
53
|
+
return false;
|
|
54
|
+
default:
|
|
55
|
+
throw Error('unknown type: ' + typeof item);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function deepMerge(source0, ...sources) {
|
|
59
|
+
const target = deepClone(source0);
|
|
60
|
+
for (const source of sources) {
|
|
61
|
+
if (typeof source !== 'object')
|
|
62
|
+
continue;
|
|
63
|
+
for (const key in source) {
|
|
64
|
+
if (!Object.hasOwn(source, key))
|
|
65
|
+
continue;
|
|
66
|
+
const sourceValue = source[key];
|
|
67
|
+
// *********
|
|
68
|
+
// overwrite
|
|
69
|
+
// *********
|
|
70
|
+
switch (typeof sourceValue) {
|
|
71
|
+
case 'number':
|
|
72
|
+
case 'string':
|
|
73
|
+
case 'boolean':
|
|
74
|
+
target[key] = sourceValue;
|
|
75
|
+
continue;
|
|
76
|
+
default:
|
|
77
|
+
}
|
|
78
|
+
if (isBasicType(target[key])) {
|
|
79
|
+
target[key] = deepClone(sourceValue);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (sourceValue instanceof Color) {
|
|
83
|
+
// @ts-expect-error: Too complicated to handle
|
|
84
|
+
target[key] = Color(sourceValue);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (isSimpleObject(target[key]) && isSimpleObject(sourceValue)) {
|
|
88
|
+
// @ts-expect-error: Too complicated to handle
|
|
89
|
+
target[key] = deepMerge(target[key], sourceValue);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
// *********
|
|
93
|
+
// merge
|
|
94
|
+
// *********
|
|
95
|
+
if (isSimpleObject(target[key]) && isSimpleObject(sourceValue)) {
|
|
96
|
+
// @ts-expect-error: Too complicated to handle
|
|
97
|
+
target[key] = deepMerge(target[key], sourceValue);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
console.log('target[key]:', target[key]);
|
|
101
|
+
console.log('source[key]:', source[key]);
|
|
102
|
+
throw Error('unpredicted case');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return target;
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { deepClone, isSimpleObject, isBasicType, deepMerge } from './utils.js';
|
|
2
|
+
import Color from 'color';
|
|
3
|
+
describe('Utilities tests', () => {
|
|
4
|
+
describe('deepClone', () => {
|
|
5
|
+
it('clones primitive types correctly', () => {
|
|
6
|
+
expect(deepClone(10)).toBe(10);
|
|
7
|
+
expect(deepClone(true)).toBe(true);
|
|
8
|
+
expect(deepClone('string')).toBe('string');
|
|
9
|
+
});
|
|
10
|
+
it('clones an array correctly', () => {
|
|
11
|
+
const array = [1, 2, { a: 'b' }];
|
|
12
|
+
const clonedArray = deepClone(array);
|
|
13
|
+
expect(clonedArray).toEqual(array);
|
|
14
|
+
expect(clonedArray).not.toBe(array);
|
|
15
|
+
});
|
|
16
|
+
it('clones a simple object correctly', () => {
|
|
17
|
+
const obj = { a: 'b', c: 1, d: true };
|
|
18
|
+
const clonedObj = deepClone(obj);
|
|
19
|
+
expect(clonedObj).toEqual(obj);
|
|
20
|
+
expect(clonedObj).not.toBe(obj);
|
|
21
|
+
});
|
|
22
|
+
it('clones a Color instance correctly', () => {
|
|
23
|
+
const color = new Color('#FF5733');
|
|
24
|
+
const clonedColor = deepClone(color);
|
|
25
|
+
expect(clonedColor.hex()).toBe(color.hex());
|
|
26
|
+
});
|
|
27
|
+
it('throws an error for non-implemented types', () => {
|
|
28
|
+
const func = () => true;
|
|
29
|
+
expect(() => deepClone(func)).toThrow('Not implemented yet: "function" case');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('isSimpleObject', () => {
|
|
33
|
+
it('identifies simple objects correctly', () => {
|
|
34
|
+
expect(isSimpleObject({ a: 1 })).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it('rejects non-objects', () => {
|
|
37
|
+
expect(isSimpleObject(1)).toBe(false);
|
|
38
|
+
expect(isSimpleObject('a')).toBe(false);
|
|
39
|
+
expect(isSimpleObject(true)).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it('rejects arrays', () => {
|
|
42
|
+
expect(isSimpleObject([1, 2, 3])).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
it('rejects objects with prototype properties', () => {
|
|
45
|
+
class MyClass {
|
|
46
|
+
#property = true;
|
|
47
|
+
}
|
|
48
|
+
expect(isSimpleObject(new MyClass())).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('isBasicType', () => {
|
|
52
|
+
it('returns true for basic types', () => {
|
|
53
|
+
expect(isBasicType(1)).toBe(true);
|
|
54
|
+
expect(isBasicType('string')).toBe(true);
|
|
55
|
+
expect(isBasicType(true)).toBe(true);
|
|
56
|
+
expect(isBasicType(undefined)).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
it('returns false for objects', () => {
|
|
59
|
+
expect(isBasicType({})).toBe(false);
|
|
60
|
+
expect(isBasicType([])).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
it('throws error for functions', () => {
|
|
63
|
+
expect(() => isBasicType(() => true)).toThrow();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('deepMerge', () => {
|
|
67
|
+
it('merges simple objects correctly', () => {
|
|
68
|
+
const target = { a: 1, b: 2 };
|
|
69
|
+
const source = { b: 3, c: 4 };
|
|
70
|
+
const result = deepMerge(target, source);
|
|
71
|
+
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
72
|
+
});
|
|
73
|
+
it('merges nested objects correctly', () => {
|
|
74
|
+
const target = { a: { d: 4 }, b: 2 };
|
|
75
|
+
const source = { a: { e: 5 }, b: 3 };
|
|
76
|
+
const result = deepMerge(target, source);
|
|
77
|
+
expect(result).toEqual({ a: { d: 4, e: 5 }, b: 3 });
|
|
78
|
+
});
|
|
79
|
+
it('overrides primitives with object types', () => {
|
|
80
|
+
const target = { a: 1, b: 2 };
|
|
81
|
+
const source = { a: { d: 4 }, b: { e: 5 } };
|
|
82
|
+
const result = deepMerge(target, source);
|
|
83
|
+
expect(result).toEqual({ a: { d: 4 }, b: { e: 5 } });
|
|
84
|
+
});
|
|
85
|
+
it('merges Color instances correctly', () => {
|
|
86
|
+
const target = { color: new Color('#FF5733') };
|
|
87
|
+
const source = { color: new Color('#33FF57') };
|
|
88
|
+
const result = deepMerge(target, source);
|
|
89
|
+
expect(result.color.hex()).toBe(source.color.hex());
|
|
90
|
+
});
|
|
91
|
+
it('throws error for unpredicted cases', () => {
|
|
92
|
+
const target = { a: () => false };
|
|
93
|
+
const source = { a: { b: 1 } };
|
|
94
|
+
expect(() => deepMerge(target, source)).toThrow('Not implemented yet: "function" case');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import StyleBuilder from '../lib/style_builder.js';
|
|
2
|
+
import type { StyleRules, StyleRulesOptions } from '../lib/style_builder.js';
|
|
3
|
+
export default class Colorful extends StyleBuilder {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
fonts: {
|
|
6
|
+
regular: string;
|
|
7
|
+
bold: string;
|
|
8
|
+
};
|
|
9
|
+
colors: {
|
|
10
|
+
land: string;
|
|
11
|
+
water: string;
|
|
12
|
+
glacier: string;
|
|
13
|
+
wood: string;
|
|
14
|
+
grass: string;
|
|
15
|
+
park: string;
|
|
16
|
+
street: string;
|
|
17
|
+
streetbg: string;
|
|
18
|
+
motorway: string;
|
|
19
|
+
motorwaybg: string;
|
|
20
|
+
trunk: string;
|
|
21
|
+
trunkbg: string;
|
|
22
|
+
buildingbg: string;
|
|
23
|
+
building: string;
|
|
24
|
+
boundary: string;
|
|
25
|
+
disputed: string;
|
|
26
|
+
residential: string;
|
|
27
|
+
commercial: string;
|
|
28
|
+
industrial: string;
|
|
29
|
+
foot: string;
|
|
30
|
+
label: string;
|
|
31
|
+
labelHalo: string;
|
|
32
|
+
shield: string;
|
|
33
|
+
agriculture: string;
|
|
34
|
+
rail: string;
|
|
35
|
+
subway: string;
|
|
36
|
+
cycle: string;
|
|
37
|
+
waste: string;
|
|
38
|
+
burial: string;
|
|
39
|
+
sand: string;
|
|
40
|
+
rock: string;
|
|
41
|
+
leisure: string;
|
|
42
|
+
wetland: string;
|
|
43
|
+
symbol: string;
|
|
44
|
+
danger: string;
|
|
45
|
+
prison: string;
|
|
46
|
+
parking: string;
|
|
47
|
+
construction: string;
|
|
48
|
+
education: string;
|
|
49
|
+
hospital: string;
|
|
50
|
+
poi: string;
|
|
51
|
+
};
|
|
52
|
+
protected getStyleRules(options: StyleRulesOptions): StyleRules;
|
|
53
|
+
}
|