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

iTowns / itowns / 10902507646

17 Sep 2024 11:56AM UTC coverage: 86.931% (-0.03%) from 86.964%
10902507646

push

github

Desplandis
release v2.44.2

2791 of 3694 branches covered (75.55%)

Branch coverage included in aggregate %.

24241 of 27402 relevant lines covered (88.46%)

1027.5 hits per line

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

93.39
/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 URLBuilder from 'Provider/URLBuilder';
1✔
5
import Fetcher from 'Provider/Fetcher';
1✔
6
import urlParser from 'Parser/MapBoxUrlParser';
1✔
7

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

1✔
12
function mergeCollections(collections) {
1✔
13
    const collection = collections[0];
1✔
14
    collections.forEach((col, index) => {
1✔
15
        if (index === 0) { return; }
2✔
16
        col.features.forEach((feature) => {
1✔
17
            collection.features.push(feature);
1✔
18
        });
1✔
19
    });
1✔
20
    return collection;
1✔
21
}
1✔
22

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

10✔
72
        this.accessToken = source.accessToken;
10✔
73

10✔
74
        if (source.style) {
10✔
75
            if (typeof source.style == 'string') {
9✔
76
                const styleUrl = urlParser.normalizeStyleURL(source.style, this.accessToken);
1✔
77
                promise = Fetcher.json(styleUrl, this.networkOptions);
1✔
78
            } else {
9✔
79
                promise = Promise.resolve(source.style);
8✔
80
            }
8✔
81
        } else {
10✔
82
            throw new Error('New VectorTilesSource: style is required');
1✔
83
        }
1✔
84

9✔
85
        this.whenReady = promise.then((style) => {
9✔
86
            this.jsonStyle = style;
9✔
87
            const baseurl = source.sprite || style.sprite;
9✔
88
            if (baseurl) {
9✔
89
                const spriteUrl = urlParser.normalizeSpriteURL(baseurl, '', '.json', this.accessToken);
1✔
90
                return Fetcher.json(spriteUrl, this.networkOptions).then((sprites) => {
1✔
91
                    this.sprites = sprites;
1✔
92
                    const imgUrl = urlParser.normalizeSpriteURL(baseurl, '', '.png', this.accessToken);
1✔
93
                    this.sprites.source = imgUrl;
1✔
94
                    return style;
1✔
95
                });
1✔
96
            }
1✔
97

8✔
98
            return style;
8✔
99
        }).then((style) => {
9✔
100
            style.layers.forEach((layer, order) => {
9✔
101
                layer.sourceUid = this.uid;
11✔
102
                if (layer.type === 'background') {
11✔
103
                    this.backgroundLayer = layer;
2✔
104
                } else if (ffilter(layer)) {
11✔
105
                    const style = Style.setFromVectorTileLayer(layer, this.sprites, order, this.symbolToCircle);
9✔
106
                    this.styles[layer.id] = style;
9✔
107

9✔
108
                    if (!this.layers[layer['source-layer']]) {
9✔
109
                        this.layers[layer['source-layer']] = [];
5✔
110
                    }
5✔
111
                    this.layers[layer['source-layer']].push({
9✔
112
                        id: layer.id,
9✔
113
                        order,
9✔
114
                        filterExpression: featureFilter(layer.filter),
9✔
115
                        zoom: {
9✔
116
                            min: layer.minzoom || 0,
9✔
117
                            max: layer.maxzoom || 24,
9✔
118
                        },
9✔
119
                    });
9✔
120
                }
9✔
121
            });
9✔
122

9✔
123
            if (this.url == '.') {
9✔
124
                const TMSUrlList = Object.values(style.sources).map((sourceVT) => {
6✔
125
                    if (sourceVT.url) {
9✔
126
                        const urlSource = urlParser.normalizeSourceURL(sourceVT.url, this.accessToken);
2✔
127
                        return Fetcher.json(urlSource, this.networkOptions).then((tileJSON) => {
2✔
128
                            if (tileJSON.tiles[0]) {
2✔
129
                                return toTMSUrl(tileJSON.tiles[0]);
2✔
130
                            }
2✔
131
                        });
2✔
132
                    } else if (sourceVT.tiles) {
9✔
133
                        return Promise.resolve(toTMSUrl(sourceVT.tiles[0]));
7✔
134
                    }
7!
135
                    return Promise.reject();
×
136
                });
6✔
137
                return Promise.all(TMSUrlList);
6✔
138
            }
6✔
139
            return (Promise.resolve([this.url]));
3✔
140
        }).then((TMSUrlList) => {
9✔
141
            this.urls = Array.from(new Set(TMSUrlList));
9✔
142
        });
9✔
143
    }
9✔
144

1✔
145
    urlFromExtent(extent, url) {
1✔
146
        return URLBuilder.xyz(extent, { tileMatrixCallback: this.tileMatrixCallback, url });
2✔
147
    }
2✔
148

1✔
149
    onLayerAdded(options) {
1✔
150
        super.onLayerAdded(options);
1✔
151
        if (options.out.style) {
1!
152
            if (options.out.isFeatureGeometryLayer && options.out.accurate) {
×
153
                console.warn('With VectorTilesSource and FeatureGeometryLayer, the accurate option is always false');
×
154
                options.out.accurate = false;
×
155
            }
×
156
        }
×
157
    }
1✔
158

1✔
159
    loadData(extent, out) {
1✔
160
        const cache = this._featuresCaches[out.crs];
1✔
161
        const key = this.requestToKey(extent);
1✔
162
        // try to get parsed data from cache
1✔
163
        let features = cache.getByArray(key);
1✔
164
        if (!features) {
1✔
165
            // otherwise fetch/parse the data
1✔
166
            features = cache.setByArray(
1✔
167
                Promise.all(this.urls.map(url =>
1✔
168
                    this.fetcher(this.urlFromExtent(extent, url), this.networkOptions)
2✔
169
                        .then(file => this.parser(file, { out, in: this, extent }))))
1✔
170
                    .then(collections => mergeCollections(collections))
1✔
171
                    .catch(err => this.handlingError(err)),
1✔
172
                key);
1✔
173

1✔
174
            /* istanbul ignore next */
1✔
175
            if (this.onParsedFile) {
1!
176
                features.then((feat) => {
×
177
                    this.onParsedFile(feat);
×
178
                    console.warn('Source.onParsedFile was deprecated');
×
179
                    return feat;
×
180
                });
×
181
            }
×
182
        }
1✔
183
        return features;
1✔
184
    }
1✔
185
}
1✔
186

1✔
187
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