-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
95 lines (86 loc) · 2.56 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import * as fs from 'fs/promises';
import sources from './sources.js'
function fixLayerFont(layer) {
const fonts = layer.layout?.['text-font'];
if (fonts) {
const font = fonts[fonts.length - 1].replace(/.*(Regular|Bold|Italic)/, 'Klokantech Noto Sans $1');
layer.layout['text-font'] = [font];
}
}
async function parseVectorTileLayerUrl(url, id) {
const style = await (await fetch(url)).json();
const metadataUrl = style.sources.esri.url;
const metadata = await (await fetch(metadataUrl)).json();
for (const layer of style.layers) {
layer.source = id
fixLayerFont(layer);
}
style.sources[id] = {
type: 'vector',
scheme: 'xyz',
format: metadata.tileInfo?.format || 'pbf',
tilejson: metadata.tilejson || '2.0.0',
maxzoom: metadata.maxzoom || 22,
tiles: [
style.sources.esri.url + '/' + metadata.tiles[0]
],
attribution: metadata.copyrightText,
description: metadata.description,
name: metadata.name,
};
style.glyphs = 'https://fonts.openmaptiles.org/{fontstack}/{range}.pbf';
delete style.sources.esri;
return style;
}
async function parseArcGISTiledMapServiceLayerUrl(url, id) {
const metadata = await (await fetch(url + '?f=json')).json();
return {
version: 8,
sources: {
[id]: {
type: 'raster',
tiles: [url + '/tile/{z}/{y}/{x}'],
tileSize: metadata.tileInfo.rows,
attribution: metadata.copyrightText,
minzoom: metadata.minScale || 0,
maxzoom: metadata.maxScale || 22,
}
},
layers: [{
id: id,
type: 'raster',
source: id,
}]
}
}
async function parseBasemap(id) {
const url = `https://www.arcgis.com/sharing/rest/content/items/${id}/data?f=json`;
let style = { sources: {}, layers: [] };
const { baseMapLayers } = (await (await fetch(url)).json())?.baseMap;
if (!baseMapLayers)
return style;
let parsed;
for (const layer of baseMapLayers) {
let { id, layerType, styleUrl, url } = layer;
if (layerType == 'VectorTileLayer') {
parsed = await parseVectorTileLayerUrl(styleUrl, id);
} else
if (layerType == 'ArcGISTiledMapServiceLayer') {
parsed = await parseArcGISTiledMapServiceLayerUrl(url, id);
}
let { sources, layers, ...rest } = parsed;
Object.assign(style, rest || {});
Object.assign(style.sources, sources);
style.layers.push(...layers);
}
return style;
}
async function main() {
await fs.rm('styles', { force: true, recursive: true });
await fs.mkdir('styles');
await Promise.all(sources.map(async (source, idx) => {
const style = await parseBasemap(source.id);
await fs.writeFile(`styles/${source.title}.json`, JSON.stringify(style, null, 4));
}))
}
await main();