• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iTowns / itowns / 7130392985

07 Dec 2023 03:32PM UTC coverage: 76.987% (-0.09%) from 77.075%
7130392985

Pull #2128

github

web-flow
Merge 23323f2ff into 6737c9307
Pull Request #2128: Mapbox style multiple source

4032 of 5980 branches covered (0.0%)

Branch coverage included in aggregate %.

13 of 18 new or added lines in 3 files covered. (72.22%)

14 existing lines in 1 file now uncovered.

7991 of 9637 relevant lines covered (82.92%)

1872.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.06
/src/Source/VectorTilesSource.js
1
import { featureFilter } from '@mapbox/mapbox-gl-style-spec';
1✔
2
import Style from 'Core/Style';
1✔
3
import TMSSource from 'Source/TMSSource';
1✔
4
import Fetcher from 'Provider/Fetcher';
1✔
5
import urlParser from 'Parser/MapBoxUrlParser';
41✔
6

7
function toTMSUrl(url) {
8
    return url.replace(/\{/g, '${');
2✔
9
}
10

11
/**
12
 * @classdesc
13
 * VectorTilesSource are object containing informations on how to fetch vector
14
 * tiles resources.
15
 *
16
 * @property {function} filter - function to filter vector tiles layers, the
17
 * parameter function is a layer.
18
 * @property {boolean} [symbolToCircle=false] - If true, all symbols from a tile
19
 * will be considered as circle, and render as circles.
20
 */
21
class VectorTilesSource extends TMSSource {
2✔
22
    /**
23
     * @param {Object} source - An object that can contain all properties of a
24
     * VectorTilesSource and {@link Source}.
25
     * @param {string|Object} source.style - The URL of the JSON style, of the
26
     * JSON style directly.
27
     * @param {string} [source.sprite] - The base URL to load informations about
28
     * the sprite of the style. If this is set, it overrides the `sprite` value
29
     * of the `source.style`. A style's sprite property supplies a URL template
30
     * for loading small images.
31
     * ```js
32
     * {
33
     *      sprite: 'http//:xxxxx/maps/sprites/'
34
     * }
35
     * ```
36
     * A valid sprite source must supply two types of files:
37
     * * An index file, which is a JSON document containing a description of each image contained in the sprite.
38
     * * Image files, which are PNG images containing the sprite data.
39
     *
40
     * For more specification : [the Mapbox sprite Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sprite/)
41
     *
42
     * @param {string} [source.url] - The base URL to load the tiles. If no url
43
     * is specified, it reads it from the loaded style. Read [the Mapbox Style
44
     * Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/)
45
     * for more informations.
46
     * @param {string} [source.accessToken] - Mapbox access token
47
     * @constructor
48
     */
49
    constructor(source) {
7✔
50
        source.format = 'application/x-protobuf;type=mapbox-vector';
7✔
51
        source.crs = 'EPSG:3857';
7✔
52
        source.isInverted = true;
7✔
53
        source.url = source.url || '.';
7✔
54
        super(source);
7✔
55
        const ffilter = source.filter || (() => true);
8✔
56
        this.layers = {};
7✔
57
        this.styles = {};
7✔
58
        let promise;
59
        this.isVectorTileSource = true;
7✔
60

61
        this.accessToken = source.accessToken;
7✔
62

63
        if (source.style) {
7✔
64
            if (typeof source.style == 'string') {
6✔
65
                const styleUrl = urlParser.normalizeStyleURL(source.style, this.accessToken);
1✔
66
                promise = Fetcher.json(styleUrl, this.networkOptions);
1✔
67
            } else {
68
                promise = Promise.resolve(source.style);
5✔
69
            }
70
        } else {
71
            throw new Error('New VectorTilesSource: style is required');
1✔
72
        }
73

74
        this.whenReady = promise.then((style) => {
6✔
75
            this.jsonStyle = style;
6✔
76
            const baseurl = source.sprite || style.sprite;
6✔
77
            if (baseurl) {
6✔
78
                const spriteUrl = urlParser.normalizeSpriteURL(baseurl, '', '.json', this.accessToken);
1✔
79
                return Fetcher.json(spriteUrl, this.networkOptions).then((sprites) => {
1✔
80
                    this.sprites = sprites;
1✔
81
                    const imgUrl = urlParser.normalizeSpriteURL(baseurl, '', '.png', this.accessToken);
1✔
82
                    this.sprites.source = imgUrl;
1✔
83
                    return style;
1✔
84
                });
85
            }
86

87
            return style;
5✔
88
        }).then((style) => {
89
            style.layers.forEach((layer, order) => {
6✔
90
                layer.sourceUid = this.uid;
10✔
91
                if (layer.type === 'background') {
10✔
92
                    this.backgroundLayer = layer;
2✔
93
                } else if (ffilter(layer)) {
8!
94
                    const style = new Style().setFromVectorTileLayer(layer, this.sprites, order, this.symbolToCircle);
8✔
95
                    style.zoom.min = layer.minzoom || 0;
8✔
96
                    style.zoom.max = layer.maxzoom || 24;
8✔
97
                    this.styles[layer.id] = style;
8✔
98

99
                    if (!this.layers[layer['source-layer']]) {
8✔
100
                        this.layers[layer['source-layer']] = [];
4✔
101
                    }
102
                    this.layers[layer['source-layer']].push({
8✔
103
                        id: layer.id,
104
                        order,
105
                        filterExpression: featureFilter(layer.filter),
106
                        zoom: {
107
                            min: layer.minzoom || 0,
13✔
108
                            max: layer.maxzoom || 24,
15✔
109
                        },
110
                    });
111
                }
112
            });
113

114
            if (this.url == '.') {
6✔
115
                const styleNames = Object.keys(style.sources);
2✔
116
                if (styleNames.length === 1 || this.isUniqueSource(styleNames, style)) {
2!
117
                    this.urlCreation(style.sources[styleNames[0]]);
2✔
118
                } else {
UNCOV
119
                    const urlArray = [];
×
UNCOV
120
                    styleNames.forEach((styleName) => {
×
UNCOV
121
                        this.urlCreation(style.sources[styleName]);
×
UNCOV
122
                        urlArray.push(this.url);
×
123
                    });
UNCOV
124
                    this.url = urlArray;
×
125
                }
126
            }
127
        });
6✔
128
    }
1✔
129

UNCOV
130
    onLayerAdded(options) {
×
UNCOV
131
        super.onLayerAdded(options);
×
UNCOV
132
        if (options.out.style) {
×
UNCOV
133
            if (options.out.isFeatureGeometryLayer && options.out.accurate) {
×
UNCOV
134
                console.warn('With VectorTilesSource and FeatureGeometryLayer, the accurate option is always false');
×
UNCOV
135
                options.out.accurate = false;
×
136
            }
UNCOV
137
            const keys = Object.keys(this.styles);
×
138

NEW
139
            keys.forEach((k) => { this.styles[k].parent = options.out.style; });
×
140
        }
141
    }
142

143
    urlCreation(styleSource) {
2✔
144
        if (styleSource.url) {
2✔
145
            const urlSource = urlParser.normalizeSourceURL(styleSource.url, this.accessToken);
1✔
146
            return Fetcher.json(urlSource, this.networkOptions).then((tileJSON) => {
1✔
147
                if (tileJSON.tiles[0]) {
1!
148
                    this.url = toTMSUrl(tileJSON.tiles[0]);
1✔
149
                }
NEW
150
            }).catch(error => console.error('Please check Mapbox Style Specification to make sure your style is correct\n', error));
×
151
        } else if (styleSource.tiles[0]) {
1!
152
            this.url = toTMSUrl(styleSource.tiles[0]);
1✔
153
        }
154
    }
155

156
    isUniqueSource(styleNames, style) {
157
        const urlArray = styleNames.map((x) => {
×
158
            if (style.sources[x].tiles) {
×
159
                return style.sources[x].tiles[0];
×
160
            } else {
161
                return style.sources[x].url;
×
162
            }
163
        });
UNCOV
164
        for (let i = 0; i < urlArray.length - 1; i++) {
×
UNCOV
165
            if (urlArray[i] == urlArray[i + 1]) {
×
NEW
166
                console.warn('Your URL is defined twice in your sources');
×
NEW
167
                return true;
×
168
            }
169
        }
NEW
170
        return false;
×
171
    }
1✔
172
}
173

174
export default VectorTilesSource;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc