-
Notifications
You must be signed in to change notification settings - Fork 270
Expand file tree
/
Copy pathleaflet_options.js
More file actions
371 lines (325 loc) · 12.1 KB
/
leaflet_options.js
File metadata and controls
371 lines (325 loc) · 12.1 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
'use strict';
var L = require('leaflet');
// Load runtime configuration (from window.osrmConfig set by index.html)
// In Node/test environments, window won't exist, so use empty config
var config = (typeof window !== 'undefined' ? window.osrmConfig : null) || {};
var osmAttribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
cartoAttribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attribution">CARTO</a>',
esriAttribution = 'Tiles © <a href="https://www.esri.com/">Esri</a> — Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community',
waymarkedtrailsAttribution = '© <a href="https://waymarkedtrails.org/">Sarah Hoffmann</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)';
var streets = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
attribution: cartoAttribution,
subdomains: 'abcd',
maxZoom: 19
}),
outdoors = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
attribution: osmAttribution + ', <a href="https://opentopomap.org/">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)',
maxZoom: 17
}),
satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: esriAttribution,
maxZoom: 19
}),
osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: osmAttribution
}),
osm_de = L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', {
attribution: osmAttribution
}),
hiking = L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {
attribution: waymarkedtrailsAttribution
}),
bike = L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {
attribution: waymarkedtrailsAttribution
}),
small_components = L.tileLayer('https://tools.geofabrik.de/osmi/tiles/routing/{z}/{x}/{y}.png', {});
// Parse center coordinates from config with validation
function parseCenter() {
var defaultCenterStr = '38.8995,-77.0269';
var centerStr = config.OSRM_CENTER || defaultCenterStr;
var parts = centerStr.split(/[, ]+/);
var lat;
var lng;
if (parts.length < 2) {
parts = defaultCenterStr.split(/[, ]+/);
}
lat = parseFloat(parts[0]);
lng = parseFloat(parts[1]);
if (!isFinite(lat) || !isFinite(lng)) {
parts = defaultCenterStr.split(/[, ]+/);
lat = parseFloat(parts[0]);
lng = parseFloat(parts[1]);
}
return L.latLng(lat, lng);
}
// Get service label from config
function getLabel() {
return config.OSRM_LABEL || 'Car (fastest)';
}
// Parse routing modes from runtime config.
// OSRM_MODES is the preferred JSON-based format: [{ name, url }, ...].
// OSRM_BACKEND is deprecated and only kept as a single-backend fallback.
// Priority: OSRM_MODES > OSRM_BACKEND (with deprecation warning) > environment defaults.
function parseModes() {
// Read config fresh from window each time, not the captured config variable
var currentConfig = (typeof window !== 'undefined' ? window.osrmConfig : null) || {};
var modesValue = currentConfig.OSRM_MODES;
var legacyBackend = currentConfig.OSRM_BACKEND;
var modes;
var hasModes;
if (Array.isArray(modesValue)) {
modes = modesValue;
hasModes = modes.length > 0;
} else if (typeof modesValue === 'string') {
hasModes = modesValue.trim().length > 0;
} else {
hasModes = false;
}
// If both are configured, prefer OSRM_MODES and warn about the deprecated fallback.
if (hasModes && legacyBackend) {
console.warn('DEPRECATION WARNING: Both OSRM_MODES and OSRM_BACKEND are set. Using OSRM_MODES. Please migrate to OSRM_MODES only.');
}
// If OSRM_MODES is provided, parse it and use the configured modes.
if (hasModes) {
try {
if (!Array.isArray(modes)) {
modes = JSON.parse(modesValue);
}
// If modes is an array of strings and contains multiple entries, map them to Mode 1/2/..
if (Array.isArray(modes) && modes.length > 1 && modes.every(function(m) {
return typeof m === 'string';
})) {
var profileNames = ['driving', 'bike', 'foot'];
return modes.map(function(url, index) {
return {
name: 'Mode ' + (index + 1),
url: url,
profile: profileNames[index] || 'driving'
};
});
}
// Special-case: accept a single-string array as the legacy single backend URL
if (Array.isArray(modes) && modes.length === 1 && typeof modes[0] === 'string') {
return [
{
name: 'default',
url: modes[0],
profile: 'driving'
}
];
}
if (Array.isArray(modes) && modes.length > 0) {
// Keep freely named user-facing modes while assigning known internal routing profiles.
return modes.map(function(mode, index) {
var profileNames = ['driving', 'bike', 'foot'];
return {
name: mode.name || ('Mode ' + (index + 1)),
url: mode.url || 'http://localhost:5000',
profile: profileNames[index] || 'driving' // Use standard profile for routing
};
});
}
} catch (e) {
console.warn('Failed to parse OSRM_MODES JSON:', e);
}
}
// Legacy support: OSRM_BACKEND alone configures one backend named "default".
if (legacyBackend) {
console.warn('DEPRECATION WARNING: OSRM_BACKEND is deprecated. Please use OSRM_MODES instead. Example: OSRM_MODES=\'[{"name":"default","url":"' + legacyBackend + '"}]\'');
return [
{
name: 'default',
url: legacyBackend,
profile: 'driving'
}
];
}
// If in dev mode (no OSRM_ENVIRONMENT or not 'docker'), use three public profiles
if (currentConfig.OSRM_ENVIRONMENT !== 'docker') {
return [
{ name: 'driving', url: 'https://router.project-osrm.org', path: 'https://router.project-osrm.org/route/v1', profile: 'driving' },
{ name: 'bike', url: 'https://routing.openstreetmap.de', path: 'https://routing.openstreetmap.de/routed-bike/route/v1', profile: 'bike' },
{ name: 'foot', url: 'https://routing.openstreetmap.de', path: 'https://routing.openstreetmap.de/routed-foot/route/v1', profile: 'foot' }
];
}
// Docker mode default: single "default" profile using localhost:5000
return [
{ name: 'default', url: 'http://localhost:5000', profile: 'driving' }
];
}
// Get backend URL based on environment and profile
// In Docker: use configured OSRM_BACKEND_* (defaults to OSRM_BACKEND)
// In dev: use public OSRM services
function getBackendForProfile(profile) {
var profileBackend = config['OSRM_BACKEND_' + profile.toUpperCase()];
var backend = profileBackend || config.OSRM_BACKEND;
if (config.OSRM_ENVIRONMENT === 'docker') {
return backend || 'http://localhost:5000';
}
// Local dev mode: use public OSRM services based on profile
if (backend) {
return backend; // Explicit override
}
if (profile === 'driving') {
return 'https://router.project-osrm.org';
}
// Bike and foot use routing.openstreetmap.de in dev mode
return 'https://routing.openstreetmap.de';
}
// Legacy functions for backward compatibility
// Get backend URL based on environment
// In Docker: use configured OSRM_BACKEND (defaults to localhost:5000)
// In dev: use public routing.project-osrm.org service
function getBackend() {
return getBackendForProfile('driving');
}
// Get bike/foot backend URL based on environment
// In Docker: use configured OSRM_BACKEND_BIKE/OSRM_BACKEND_FOOT
// In local dev: use known public services (routing.openstreetmap.de)
function getAlternativeBackend() {
// In Docker: use bike backend
if (config.OSRM_ENVIRONMENT === 'docker') {
return getBackendForProfile('bike') || getBackend();
}
// Local dev mode: use public routing services
return undefined;
}
// Get zoom level from config with validation
function getZoom() {
var zoomValue = config.OSRM_ZOOM;
var parsedZoom;
if (zoomValue === undefined || zoomValue === null) {
return 13;
}
parsedZoom = parseInt(zoomValue, 10);
if (isNaN(parsedZoom)) {
return 13;
}
return parsedZoom;
}
// Get language, prefer browser settings when available; fallback to 'en'.
// Precedence (effective): URL param (handled in index.js) > browser language > 'en'
function getLanguage() {
try {
// Read runtime config each time (honor OSRM_LANGUAGE when set at runtime)
var currentConfig = (typeof window !== 'undefined' ? window.osrmConfig : null) || {};
var localization = require('./localization');
var languages = localization.getLanguages();
function resolveCandidate(candidate) {
if (!candidate) return undefined;
candidate = String(candidate).trim();
// exact match (case-sensitive)
if (localization.get(candidate)) return candidate;
// case-insensitive exact match against available keys (e.g., pt-br -> pt-BR)
var lower = candidate.toLowerCase();
var keys = Object.keys(languages);
for (var k = 0; k < keys.length; k++) {
if (keys[k].toLowerCase() === lower) return keys[k];
}
// primary subtag fallback (e.g., en-US -> en)
var primary = candidate.split(/[-_]/)[0];
if (!primary) return undefined;
if (localization.get(primary)) return primary;
var lowerPrimary = primary.toLowerCase();
for (var j = 0; j < keys.length; j++) {
if (keys[j].toLowerCase() === lowerPrimary) return keys[j];
}
return undefined;
}
if (currentConfig.OSRM_LANGUAGE) {
var resolved = resolveCandidate(currentConfig.OSRM_LANGUAGE);
return resolved || currentConfig.OSRM_LANGUAGE;
}
if (typeof window !== 'undefined' && window.navigator) {
var nav = window.navigator;
var candidates = [];
if (Array.isArray(nav.languages)) {
candidates = candidates.concat(nav.languages);
}
if (nav.language) candidates.push(nav.language);
if (nav.userLanguage) candidates.push(nav.userLanguage); // IE fallback
for (var i = 0; i < candidates.length; i++) {
var lang = candidates[i];
if (!lang) continue;
var resolvedLang = resolveCandidate(lang);
if (resolvedLang) return resolvedLang;
}
}
} catch (e) {
// Ignore detection errors and fall back to default
console.warn('Error detecting browser language:', e);
}
// Fallback to English when no browser language matches
return 'en';
}
// Get default layer from config
function getDefaultLayer() {
return config.OSRM_DEFAULT_LAYER || 'streets';
}
var layerMap = {
streets: streets,
outdoors: outdoors,
satellite: satellite,
osm: osm,
osm_de: osm_de
};
var defaultLayer = layerMap[getDefaultLayer()] || streets;
// Build services array from OSRM_MODES config
// Each service has a name, URL prefix, and internal profile for routing
function buildServices() {
var modes = parseModes();
var defaultLabelMapping = {
driving: 'Car',
bike: 'Bike',
foot: 'Foot',
default: 'Car'
};
return modes.map(function(mode) {
var name = mode.name;
var label = mode.label || name;
var labelKey = mode.labelKey || defaultLabelMapping[name] || label;
return {
label: label,
labelKey: labelKey,
path: mode.path || (mode.url + '/route/v1'),
profile: mode.profile
};
});
}
var leafletOptions = {
defaultState: {
center: parseCenter(),
zoom: getZoom(),
waypoints: [],
language: getLanguage(),
units: 'metric',
alternative: 0,
layer: defaultLayer
},
get services() {
return buildServices();
},
layer: [{
'Streets': streets,
'Outdoors': outdoors,
'Satellite': satellite,
'openstreetmap.org': osm,
'openstreetmap.de': osm_de
}],
overlay: {
'Hiking': hiking,
'Bike': bike,
'Small Components': small_components
},
baselayer: {
one: streets,
two: outdoors,
three: satellite,
four: osm,
five: osm_de
},
nominatim: {
path: 'https://nominatim.openstreetmap.org/'
}
};
module.exports = leafletOptions;